From 4cfc2e4457d0844bce7831f4eccca07d412641b3 Mon Sep 17 00:00:00 2001 From: Markus Chmelar Date: Fri, 16 Jun 2017 18:58:33 +0200 Subject: [PATCH 1/2] Update for ReactiveCocoa 5.0, Swift 3.2 --- Cartfile | 2 +- Cartfile.resolved | 7 +- Carthage/Checkouts/LlamaKit | 1 - Carthage/Checkouts/ReactiveCocoa | 2 +- .../.github/PULL_REQUEST_TEMPLATE.md | 3 + Carthage/Checkouts/ReactiveSwift/.gitignore | 30 + Carthage/Checkouts/ReactiveSwift/.gitmodules | 12 + Carthage/Checkouts/ReactiveSwift/.jazzy.yaml | 87 + .../Checkouts/ReactiveSwift/.swift-version | 1 + Carthage/Checkouts/ReactiveSwift/.travis.yml | 110 + Carthage/Checkouts/ReactiveSwift/CHANGELOG.md | 216 ++ .../Checkouts/ReactiveSwift/CONTRIBUTING.md | 156 + Carthage/Checkouts/ReactiveSwift/Cartfile | 1 + .../Checkouts/ReactiveSwift/Cartfile.private | 3 + .../Checkouts/ReactiveSwift/Cartfile.resolved | 4 + .../Checkouts/Nimble/.github/ISSUE_TEMPLATE | 36 + .../Nimble/.github/PULL_REQUEST_TEMPLATE | 14 + .../Carthage/Checkouts/Nimble/.gitignore | 21 + .../Carthage/Checkouts/Nimble/.hound.yml | 2 + .../Carthage/Checkouts/Nimble/.swift-version | 1 + .../Carthage/Checkouts/Nimble/.swiftlint.yml | 19 + .../Carthage/Checkouts/Nimble/.travis.yml | 25 + .../Carthage/Checkouts/Nimble/CONTRIBUTING.md | 120 + .../Carthage/Checkouts/Nimble/Dockerfile.test | 3 + .../Carthage/Checkouts/Nimble/Gemfile | 4 + .../Carthage/Checkouts/Nimble/Gemfile.lock | 73 + .../Carthage/Checkouts/Nimble/LICENSE | 201 ++ .../Carthage/Checkouts/Nimble/Nimble.podspec | 49 + .../Nimble/Nimble.xcodeproj/project.pbxproj | 2293 ++++++++++++ .../contents.xcworkspacedata | 7 + .../xcschemes/Nimble-iOS.xcscheme | 82 + .../xcschemes/Nimble-macOS.xcscheme | 82 + .../xcschemes/Nimble-tvOS.xcscheme | 99 + .../Carthage/Checkouts/Nimble/Package.swift | 12 + .../Carthage/Checkouts/Nimble/README.md | 1760 +++++++++ .../CwlCatchException/CwlCatchException.swift | 37 + .../CwlCatchException.m | 37 + .../include/CwlCatchException.h | 32 + .../CwlMachBadInstructionHandler.m | 50 + .../include/CwlMachBadInstructionHandler.h | 70 + .../mach_excServer.c | 537 +++ .../mach_excServer.h | 321 ++ .../CwlBadInstructionException.swift | 89 + .../CwlCatchBadInstruction.swift | 199 ++ .../CwlCatchBadInstructionPOSIX.swift | 108 + .../CwlDarwinDefinitions.swift | 55 + .../Mach/CwlPreconditionTesting.h | 30 + .../Posix/CwlPreconditionTesting.h | 27 + .../Lib/CwlPreconditionTesting/README.md | 80 + .../Nimble/Adapters/AdapterProtocols.swift | 17 + .../Nimble/Adapters/AssertionDispatcher.swift | 19 + .../Nimble/Adapters/AssertionRecorder.swift | 100 + .../Nimble/Adapters/NMBExpectation.swift | 183 + .../Nimble/Adapters/NMBObjCMatcher.swift | 81 + .../Nimble/Adapters/NimbleEnvironment.swift | 45 + .../Nimble/Adapters/NimbleXCTestHandler.swift | 76 + .../NonObjectiveC/ExceptionCapture.swift | 31 + .../Nimble/Sources/Nimble/DSL+Wait.swift | 98 + .../Checkouts/Nimble/Sources/Nimble/DSL.swift | 64 + .../Nimble/Sources/Nimble/Expectation.swift | 131 + .../Sources/Nimble/ExpectationMessage.swift | 261 ++ .../Nimble/Sources/Nimble/Expression.swift | 90 + .../Sources/Nimble/FailureMessage.swift | 92 + .../Nimble/Sources/Nimble/Info.plist | 28 + .../Sources/Nimble/Matchers/AllPass.swift | 120 + .../Nimble/Matchers/AsyncMatcherWrapper.swift | 226 ++ .../Sources/Nimble/Matchers/BeAKindOf.swift | 68 + .../Nimble/Matchers/BeAnInstanceOf.swift | 56 + .../Sources/Nimble/Matchers/BeCloseTo.swift | 126 + .../Sources/Nimble/Matchers/BeEmpty.swift | 92 + .../Nimble/Matchers/BeGreaterThan.swift | 41 + .../Matchers/BeGreaterThanOrEqualTo.swift | 44 + .../Nimble/Matchers/BeIdenticalTo.swift | 46 + .../Sources/Nimble/Matchers/BeLessThan.swift | 41 + .../Nimble/Matchers/BeLessThanOrEqual.swift | 42 + .../Sources/Nimble/Matchers/BeLogical.swift | 167 + .../Sources/Nimble/Matchers/BeNil.swift | 19 + .../Sources/Nimble/Matchers/BeVoid.swift | 18 + .../Sources/Nimble/Matchers/BeginWith.swift | 60 + .../Sources/Nimble/Matchers/Contain.swift | 94 + .../Matchers/ContainElementSatisfying.swift | 59 + .../Sources/Nimble/Matchers/EndWith.swift | 72 + .../Sources/Nimble/Matchers/Equal.swift | 220 ++ .../Sources/Nimble/Matchers/HaveCount.swift | 57 + .../Sources/Nimble/Matchers/Match.swift | 30 + .../Sources/Nimble/Matchers/MatchError.swift | 53 + .../Sources/Nimble/Matchers/MatcherFunc.swift | 85 + .../Nimble/Matchers/MatcherProtocols.swift | 170 + .../Nimble/Matchers/PostNotification.swift | 70 + .../Sources/Nimble/Matchers/Predicate.swift | 348 ++ .../Nimble/Matchers/RaisesException.swift | 183 + .../Nimble/Matchers/SatisfyAnyOf.swift | 107 + .../Nimble/Matchers/ThrowAssertion.swift | 55 + .../Sources/Nimble/Matchers/ThrowError.swift | 240 ++ .../Sources/Nimble/Matchers/ToSucceed.swift | 37 + .../Checkouts/Nimble/Sources/Nimble/Nimble.h | 9 + .../Nimble/Sources/Nimble/Utils/Async.swift | 360 ++ .../Nimble/Sources/Nimble/Utils/Errors.swift | 59 + .../Sources/Nimble/Utils/Functional.swift | 12 + .../Sources/Nimble/Utils/SourceLocation.swift | 31 + .../Sources/Nimble/Utils/Stringers.swift | 212 ++ .../NimbleObjectiveC/CurrentTestCaseTracker.h | 9 + .../Nimble/Sources/NimbleObjectiveC/DSL.h | 383 ++ .../Nimble/Sources/NimbleObjectiveC/DSL.m | 160 + .../NimbleObjectiveC/NMBExceptionCapture.h | 11 + .../NimbleObjectiveC/NMBExceptionCapture.m | 35 + .../Sources/NimbleObjectiveC/NMBStringify.h | 18 + .../Sources/NimbleObjectiveC/NMBStringify.m | 6 + .../XCTestObservationCenter+Register.m | 78 + .../Checkouts/Nimble/Tests/LinuxMain.swift | 37 + .../Tests/NimbleTests/AsynchronousTest.swift | 220 ++ .../Helpers/ObjectWithLazyProperty.swift | 7 + .../Helpers/XCTestCaseProvider.swift | 52 + .../Tests/NimbleTests/Helpers/utils.swift | 98 + .../Nimble/Tests/NimbleTests/Info.plist | 24 + .../Tests/NimbleTests/LinuxSupport.swift | 9 + .../NimbleTests/Matchers/AllPassTest.swift | 126 + .../NimbleTests/Matchers/BeAKindOfTest.swift | 89 + .../Matchers/BeAnInstanceOfTest.swift | 79 + .../NimbleTests/Matchers/BeCloseToTest.swift | 160 + .../NimbleTests/Matchers/BeEmptyTest.swift | 82 + .../Matchers/BeGreaterThanOrEqualToTest.swift | 54 + .../Matchers/BeGreaterThanTest.swift | 53 + .../Matchers/BeIdenticalToObjectTest.swift | 64 + .../Matchers/BeIdenticalToTest.swift | 68 + .../Matchers/BeLessThanOrEqualToTest.swift | 52 + .../NimbleTests/Matchers/BeLessThanTest.swift | 57 + .../NimbleTests/Matchers/BeLogicalTest.swift | 270 ++ .../NimbleTests/Matchers/BeNilTest.swift | 28 + .../NimbleTests/Matchers/BeVoidTest.swift | 32 + .../NimbleTests/Matchers/BeginWithTest.swift | 53 + .../ContainElementSatisfyingTest.swift | 86 + .../NimbleTests/Matchers/ContainTest.swift | 95 + .../NimbleTests/Matchers/EndWithTest.swift | 56 + .../NimbleTests/Matchers/EqualTest.swift | 276 ++ .../NimbleTests/Matchers/HaveCountTest.swift | 56 + .../NimbleTests/Matchers/MatchErrorTest.swift | 84 + .../NimbleTests/Matchers/MatchTest.swift | 46 + .../Matchers/PostNotificationTest.swift | 91 + .../Matchers/RaisesExceptionTest.swift | 166 + .../Matchers/SatisfyAnyOfTest.swift | 56 + .../Matchers/ThrowAssertionTest.swift | 62 + .../NimbleTests/Matchers/ThrowErrorTest.swift | 155 + .../NimbleTests/Matchers/ToSucceedTest.swift | 36 + .../Tests/NimbleTests/SynchronousTests.swift | 128 + .../NimbleTests/UserDescriptionTest.swift | 64 + .../Tests/NimbleTests/objc/NimbleSpecHelper.h | 15 + .../Tests/NimbleTests/objc/ObjCAllPassTest.m | 38 + .../Tests/NimbleTests/objc/ObjCAsyncTest.m | 55 + .../NimbleTests/objc/ObjCBeAnInstanceOfTest.m | 34 + .../NimbleTests/objc/ObjCBeCloseToTest.m | 47 + .../Tests/NimbleTests/objc/ObjCBeEmptyTest.m | 89 + .../Tests/NimbleTests/objc/ObjCBeFalseTest.m | 46 + .../Tests/NimbleTests/objc/ObjCBeFalsyTest.m | 58 + .../objc/ObjCBeGreaterThanOrEqualToTest.m | 44 + .../NimbleTests/objc/ObjCBeGreaterThanTest.m | 42 + .../NimbleTests/objc/ObjCBeIdenticalToTest.m | 68 + .../Tests/NimbleTests/objc/ObjCBeKindOfTest.m | 34 + .../objc/ObjCBeLessThanOrEqualToTest.m | 43 + .../NimbleTests/objc/ObjCBeLessThanTest.m | 42 + .../Tests/NimbleTests/objc/ObjCBeNilTest.m | 24 + .../Tests/NimbleTests/objc/ObjCBeTrueTest.m | 47 + .../Tests/NimbleTests/objc/ObjCBeTruthyTest.m | 55 + .../NimbleTests/objc/ObjCBeginWithTest.m | 37 + .../objc/ObjCContainElementSatisfying.m | 64 + .../Tests/NimbleTests/objc/ObjCContainTest.m | 67 + .../Tests/NimbleTests/objc/ObjCEndWithTest.m | 37 + .../Tests/NimbleTests/objc/ObjCEqualTest.m | 94 + .../Tests/NimbleTests/objc/ObjCHaveCount.m | 174 + .../Tests/NimbleTests/objc/ObjCMatchTest.m | 33 + .../NimbleTests/objc/ObjCRaiseExceptionTest.m | 178 + .../NimbleTests/objc/ObjCSatisfyAnyOfTest.m | 32 + .../Tests/NimbleTests/objc/ObjCSyncTest.m | 21 + .../objc/ObjCUserDescriptionTest.m | 52 + .../NimbleTests/objc/ObjcStringersTest.m | 31 + .../Carthage/Checkouts/Nimble/script/release | 187 + .../Carthage/Checkouts/Nimble/test | 156 + .../Checkouts/Quick/.Package.test.swift | 39 + .../Checkouts/Quick/.github/ISSUE_TEMPLATE | 36 + .../Quick/.github/PULL_REQUEST_TEMPLATE | 14 + .../Carthage/Checkouts/Quick/.gitignore | 65 + .../Carthage/Checkouts/Quick/.gitmodules | 3 + .../Carthage/Checkouts/Quick/.hound.yml | 2 + .../Carthage/Checkouts/Quick/.swift-version | 1 + .../Carthage/Checkouts/Quick/.swiftlint.yml | 9 + .../Carthage/Checkouts/Quick/.travis.yml | 34 + .../Checkouts/Quick/CODE_OF_CONDUCT.md | 74 + .../Carthage/Checkouts/Quick/CONTRIBUTING.md | 111 + .../Carthage/Checkouts/Quick/Dangerfile | 53 + .../Checkouts/Quick/Documentation/README.md | 6 + .../Documentation/en-us/ArrangeActAssert.md | 220 ++ .../Documentation/en-us/BehavioralTesting.md | 87 + .../Documentation/en-us/ConfiguringQuick.md | 103 + .../en-us/InstallingFileTemplates.md | 28 + .../Documentation/en-us/InstallingQuick.md | 157 + .../Documentation/en-us/MoreResources.md | 28 + .../Documentation/en-us/NimbleAssertions.md | 106 + .../en-us/QuickExamplesAndGroups.md | 491 +++ .../Documentation/en-us/QuickInObjectiveC.md | 57 + .../Quick/Documentation/en-us/README.md | 46 + .../en-us/SettingUpYourXcodeProject.md | 89 + .../Documentation/en-us/SharedExamples.md | 125 + .../en-us/TestUsingTestDoubles.md | 129 + .../Quick/Documentation/en-us/TestingApps.md | 179 + .../Documentation/en-us/Troubleshooting.md | 9 + .../Documentation/ja/ArrangeActAssert.md | 212 ++ .../Documentation/ja/BehavioralTesting.md | 81 + .../Documentation/ja/ConfiguringQuick.md | 101 + .../ja/InstallingFileTemplates.md | 26 + .../Quick/Documentation/ja/InstallingQuick.md | 152 + .../Quick/Documentation/ja/MoreResources.md | 27 + .../Documentation/ja/NimbleAssertions.md | 100 + .../ja/QuickExamplesAndGroups.md | 477 +++ .../Documentation/ja/QuickInObjectiveC.md | 48 + .../Quick/Documentation/ja/README.md | 50 + .../ja/SettingUpYourXcodeProject.md | 77 + .../Quick/Documentation/ja/SharedExamples.md | 122 + .../Documentation/ja/TestUsingTestDoubles.md | 138 + .../Quick/Documentation/ja/TestingApps.md | 174 + .../Quick/Documentation/ja/Troubleshooting.md | 9 + .../Documentation/pt-br/BehavioralTesting.md | 78 + .../Quick/Documentation/pt-br/README.md | 39 + .../Documentation/pt-br/SharedExamples.md | 116 + .../Documentation/zh-cn/ArrangeActAssert.md | 205 ++ .../Documentation/zh-cn/BehavioralTesting.md | 75 + .../Documentation/zh-cn/ConfiguringQuick.md | 102 + .../zh-cn/InstallingFileTemplates.md | 26 + .../Documentation/zh-cn/InstallingQuick.md | 157 + .../Documentation/zh-cn/MoreResources.md | 23 + .../Documentation/zh-cn/NimbleAssertions.md | 100 + .../zh-cn/QuickExamplesAndGroups.md | 461 +++ .../Documentation/zh-cn/QuickInObjectiveC.md | 52 + .../Quick/Documentation/zh-cn/README.md | 18 + .../zh-cn/SettingUpYourXcodeProject.md | 75 + .../Documentation/zh-cn/SharedExamples.md | 113 + .../zh-cn/TestUsingTestDoubles.md | 131 + .../Quick/Documentation/zh-cn/TestingApps.md | 174 + .../Documentation/zh-cn/Troubleshooting.md | 10 + .../Externals/Nimble/.github/ISSUE_TEMPLATE | 36 + .../Nimble/.github/PULL_REQUEST_TEMPLATE | 14 + .../Quick/Externals/Nimble/.gitignore | 21 + .../Quick/Externals/Nimble/.hound.yml | 2 + .../Quick/Externals/Nimble/.swift-version | 1 + .../Quick/Externals/Nimble/.swiftlint.yml | 16 + .../Quick/Externals/Nimble/.travis.yml | 25 + .../Quick/Externals/Nimble/CONTRIBUTING.md | 120 + .../Checkouts/Quick/Externals/Nimble/Gemfile | 4 + .../Quick/Externals/Nimble/Gemfile.lock | 69 + .../Checkouts/Quick/Externals/Nimble/LICENSE | 201 ++ .../Quick/Externals/Nimble/Nimble.podspec | 47 + .../Nimble/Nimble.xcodeproj/project.pbxproj | 2171 ++++++++++++ .../contents.xcworkspacedata | 7 + .../xcschemes/Nimble-iOS.xcscheme | 82 + .../xcschemes/Nimble-macOS.xcscheme | 82 + .../xcschemes/Nimble-tvOS.xcscheme | 99 + .../Quick/Externals/Nimble/Package.swift | 10 + .../Quick/Externals/Nimble/README.md | 1443 ++++++++ .../CwlCatchException/.gitignore | 3 + .../CwlCatchException/CwlCatchException.h | 30 + .../CwlCatchException/CwlCatchException.m | 35 + .../CwlCatchException/CwlCatchException.swift | 32 + .../CwlCatchException/Info.plist | 28 + .../CwlBadInstructionException.swift | 76 + .../CwlCatchBadInstruction.h | 61 + .../CwlCatchBadInstruction.m | 50 + .../CwlCatchBadInstruction.swift | 193 + .../CwlCatchBadInstructionPOSIX.swift | 100 + .../CwlDarwinDefinitions.swift | 63 + .../CwlPreconditionTesting/Info.plist | 28 + .../CwlPreconditionTesting/mach_excServer.c | 537 +++ .../CwlPreconditionTesting/mach_excServer.h | 298 ++ .../Lib/CwlPreconditionTesting/README.md | 80 + .../Nimble/Adapters/AdapterProtocols.swift | 17 + .../Nimble/Adapters/AssertionDispatcher.swift | 19 + .../Nimble/Adapters/AssertionRecorder.swift | 100 + .../Nimble/Adapters/NMBExpectation.swift | 131 + .../Nimble/Adapters/NMBObjCMatcher.swift | 81 + .../Nimble/Adapters/NimbleEnvironment.swift | 45 + .../Nimble/Adapters/NimbleXCTestHandler.swift | 76 + .../NonObjectiveC/ExceptionCapture.swift | 31 + .../Nimble/Sources/Nimble/DSL+Wait.swift | 98 + .../Externals/Nimble/Sources/Nimble/DSL.swift | 64 + .../Nimble/Sources/Nimble/Expectation.swift | 71 + .../Nimble/Sources/Nimble/Expression.swift | 90 + .../Sources/Nimble/FailureMessage.swift | 65 + .../Nimble/Sources/Nimble/Info.plist | 28 + .../Sources/Nimble/Matchers/AllPass.swift | 94 + .../Nimble/Matchers/AsyncMatcherWrapper.swift | 141 + .../Sources/Nimble/Matchers/BeAKindOf.swift | 48 + .../Nimble/Matchers/BeAnInstanceOf.swift | 50 + .../Sources/Nimble/Matchers/BeCloseTo.swift | 122 + .../Sources/Nimble/Matchers/BeEmpty.swift | 91 + .../Nimble/Matchers/BeGreaterThan.swift | 41 + .../Matchers/BeGreaterThanOrEqualTo.swift | 44 + .../Nimble/Matchers/BeIdenticalTo.swift | 46 + .../Sources/Nimble/Matchers/BeLessThan.swift | 41 + .../Nimble/Matchers/BeLessThanOrEqual.swift | 42 + .../Sources/Nimble/Matchers/BeLogical.swift | 173 + .../Sources/Nimble/Matchers/BeNil.swift | 20 + .../Sources/Nimble/Matchers/BeVoid.swift | 18 + .../Sources/Nimble/Matchers/BeginWith.swift | 63 + .../Sources/Nimble/Matchers/Contain.swift | 94 + .../Matchers/ContainElementSatisfying.swift | 59 + .../Sources/Nimble/Matchers/EndWith.swift | 72 + .../Sources/Nimble/Matchers/Equal.swift | 181 + .../Sources/Nimble/Matchers/HaveCount.swift | 57 + .../Sources/Nimble/Matchers/Match.swift | 30 + .../Sources/Nimble/Matchers/MatchError.swift | 26 + .../Sources/Nimble/Matchers/MatcherFunc.swift | 69 + .../Nimble/Matchers/MatcherProtocols.swift | 153 + .../Nimble/Matchers/PostNotification.swift | 70 + .../Nimble/Matchers/RaisesException.swift | 183 + .../Nimble/Matchers/SatisfyAnyOf.swift | 62 + .../Nimble/Matchers/ThrowAssertion.swift | 55 + .../Sources/Nimble/Matchers/ThrowError.swift | 53 + .../Externals/Nimble/Sources/Nimble/Nimble.h | 14 + .../Nimble/Sources/Nimble/Utils/Async.swift | 361 ++ .../Nimble/Sources/Nimble/Utils/Errors.swift | 141 + .../Sources/Nimble/Utils/Functional.swift | 12 + .../Sources/Nimble/Utils/SourceLocation.swift | 31 + .../Sources/Nimble/Utils/Stringers.swift | 212 ++ .../NimbleObjectiveC/CurrentTestCaseTracker.h | 9 + .../Nimble/Sources/NimbleObjectiveC/DSL.h | 381 ++ .../Nimble/Sources/NimbleObjectiveC/DSL.m | 160 + .../NimbleObjectiveC/NMBExceptionCapture.h | 11 + .../NimbleObjectiveC/NMBExceptionCapture.m | 35 + .../Sources/NimbleObjectiveC/NMBStringify.h | 18 + .../Sources/NimbleObjectiveC/NMBStringify.m | 6 + .../XCTestObservationCenter+Register.m | 78 + .../Externals/Nimble/Tests/LinuxMain.swift | 37 + .../Tests/NimbleTests/AsynchronousTest.swift | 222 ++ .../Helpers/ObjectWithLazyProperty.swift | 7 + .../Helpers/XCTestCaseProvider.swift | 52 + .../Tests/NimbleTests/Helpers/utils.swift | 98 + .../Nimble/Tests/NimbleTests/Info.plist | 24 + .../Tests/NimbleTests/LinuxSupport.swift | 9 + .../NimbleTests/Matchers/AllPassTest.swift | 126 + .../NimbleTests/Matchers/BeAKindOfTest.swift | 89 + .../Matchers/BeAnInstanceOfTest.swift | 79 + .../NimbleTests/Matchers/BeCloseToTest.swift | 160 + .../NimbleTests/Matchers/BeEmptyTest.swift | 82 + .../Matchers/BeGreaterThanOrEqualToTest.swift | 50 + .../Matchers/BeGreaterThanTest.swift | 50 + .../Matchers/BeIdenticalToObjectTest.swift | 64 + .../Matchers/BeIdenticalToTest.swift | 68 + .../Matchers/BeLessThanOrEqualToTest.swift | 52 + .../NimbleTests/Matchers/BeLessThanTest.swift | 57 + .../NimbleTests/Matchers/BeLogicalTest.swift | 270 ++ .../NimbleTests/Matchers/BeNilTest.swift | 28 + .../NimbleTests/Matchers/BeVoidTest.swift | 32 + .../NimbleTests/Matchers/BeginWithTest.swift | 53 + .../ContainElementSatisfyingTest.swift | 86 + .../NimbleTests/Matchers/ContainTest.swift | 95 + .../NimbleTests/Matchers/EndWithTest.swift | 56 + .../NimbleTests/Matchers/EqualTest.swift | 274 ++ .../NimbleTests/Matchers/HaveCountTest.swift | 56 + .../NimbleTests/Matchers/MatchErrorTest.swift | 83 + .../NimbleTests/Matchers/MatchTest.swift | 46 + .../Matchers/PostNotificationTest.swift | 91 + .../Matchers/RaisesExceptionTest.swift | 166 + .../Matchers/SatisfyAnyOfTest.swift | 56 + .../Matchers/ThrowAssertionTest.swift | 62 + .../NimbleTests/Matchers/ThrowErrorTest.swift | 154 + .../Tests/NimbleTests/SynchronousTests.swift | 128 + .../NimbleTests/UserDescriptionTest.swift | 64 + .../Tests/NimbleTests/objc/NimbleSpecHelper.h | 15 + .../Tests/NimbleTests/objc/ObjCAllPassTest.m | 38 + .../Tests/NimbleTests/objc/ObjCAsyncTest.m | 55 + .../NimbleTests/objc/ObjCBeAnInstanceOfTest.m | 34 + .../NimbleTests/objc/ObjCBeCloseToTest.m | 47 + .../Tests/NimbleTests/objc/ObjCBeEmptyTest.m | 89 + .../Tests/NimbleTests/objc/ObjCBeFalseTest.m | 46 + .../Tests/NimbleTests/objc/ObjCBeFalsyTest.m | 58 + .../objc/ObjCBeGreaterThanOrEqualToTest.m | 42 + .../NimbleTests/objc/ObjCBeGreaterThanTest.m | 41 + .../NimbleTests/objc/ObjCBeIdenticalToTest.m | 68 + .../Tests/NimbleTests/objc/ObjCBeKindOfTest.m | 34 + .../objc/ObjCBeLessThanOrEqualToTest.m | 43 + .../NimbleTests/objc/ObjCBeLessThanTest.m | 42 + .../Tests/NimbleTests/objc/ObjCBeNilTest.m | 24 + .../Tests/NimbleTests/objc/ObjCBeTrueTest.m | 47 + .../Tests/NimbleTests/objc/ObjCBeTruthyTest.m | 55 + .../NimbleTests/objc/ObjCBeginWithTest.m | 37 + .../objc/ObjCContainElementSatisfying.m | 64 + .../Tests/NimbleTests/objc/ObjCContainTest.m | 67 + .../Tests/NimbleTests/objc/ObjCEndWithTest.m | 37 + .../Tests/NimbleTests/objc/ObjCEqualTest.m | 94 + .../Tests/NimbleTests/objc/ObjCHaveCount.m | 174 + .../Tests/NimbleTests/objc/ObjCMatchTest.m | 33 + .../NimbleTests/objc/ObjCRaiseExceptionTest.m | 178 + .../NimbleTests/objc/ObjCSatisfyAnyOfTest.m | 32 + .../Tests/NimbleTests/objc/ObjCSyncTest.m | 21 + .../objc/ObjCUserDescriptionTest.m | 52 + .../NimbleTests/objc/ObjcStringersTest.m | 31 + .../Quick/Externals/Nimble/script/release | 186 + .../Checkouts/Quick/Externals/Nimble/test | 142 + .../Carthage/Checkouts/Quick/Gemfile | 5 + .../Carthage/Checkouts/Quick/Gemfile.lock | 113 + .../Carthage/Checkouts/Quick/LICENSE | 201 ++ .../Carthage/Checkouts/Quick/Package.swift | 33 + .../Objective-C/___FILEBASENAME___.h | 13 + .../Objective-C/___FILEBASENAME___.m | 17 + .../Swift/___FILEBASENAME___.swift | 15 + .../TemplateIcon.icns | Bin 0 -> 529473 bytes .../TemplateInfo.plist | 73 + .../Objective-C/___FILEBASENAME___.m | 14 + .../Swift/___FILEBASENAME___.swift | 16 + .../TemplateIcon.icns | Bin 0 -> 529473 bytes .../TemplateInfo.plist | 73 + .../Carthage/Checkouts/Quick/Quick.podspec | 38 + .../Quick/Quick.xcodeproj/project.pbxproj | 2649 ++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Quick-iOS.xcscheme | 119 + .../xcschemes/Quick-macOS.xcscheme | 119 + .../xcschemes/Quick-tvOS.xcscheme | 119 + .../contents.xcworkspacedata | 10 + .../Carthage/Checkouts/Quick/README.md | 88 + .../Carthage/Checkouts/Quick/Rakefile | 68 + .../Quick/Sources/Quick/Callsite.swift | 32 + .../Quick/Configuration/Configuration.swift | 161 + .../Configuration/QuickConfiguration.swift | 39 + .../Quick/Sources/Quick/DSL/DSL.swift | 241 ++ .../Quick/Sources/Quick/DSL/World+DSL.swift | 175 + .../Quick/Sources/Quick/ErrorUtility.swift | 10 + .../Quick/Sources/Quick/Example.swift | 113 + .../Quick/Sources/Quick/ExampleGroup.swift | 103 + .../Quick/Sources/Quick/ExampleMetadata.swift | 24 + .../Quick/Sources/Quick/Filter.swift | 31 + .../Quick/Sources/Quick/Hooks/Closures.swift | 35 + .../Sources/Quick/Hooks/ExampleHooks.swift | 42 + .../Sources/Quick/Hooks/HooksPhase.swift | 11 + .../Sources/Quick/Hooks/SuiteHooks.swift | 32 + .../Checkouts/Quick/Sources/Quick/Info.plist | 28 + .../Quick/NSBundle+CurrentTestBundle.swift | 25 + .../NSString+C99ExtendedIdentifier.swift | 33 + .../Quick/Sources/Quick/QuickMain.swift | 38 + .../Quick/QuickSelectedTestSuiteBuilder.swift | 74 + .../Quick/Sources/Quick/QuickSpec.swift | 122 + .../Quick/Sources/Quick/QuickTestSuite.swift | 52 + .../Quick/Sources/Quick/URL+FileName.swift | 12 + .../Checkouts/Quick/Sources/Quick/World.swift | 233 ++ .../Configuration/QuickConfiguration.h | 30 + .../Configuration/QuickConfiguration.m | 83 + .../Sources/QuickObjectiveC/DSL/QCKDSL.h | 234 ++ .../Sources/QuickObjectiveC/DSL/QCKDSL.m | 79 + .../Sources/QuickObjectiveC/DSL/World+DSL.h | 20 + .../Quick/Sources/QuickObjectiveC/Quick.h | 11 + .../Quick/Sources/QuickObjectiveC/QuickSpec.h | 50 + .../Quick/Sources/QuickObjectiveC/QuickSpec.m | 141 + .../Quick/Sources/QuickObjectiveC/World.h | 18 + .../XCTestSuite+QuickTestSuiteBuilder.m | 40 + .../Sources/QuickSpecBase/QuickSpecBase.m | 55 + .../QuickSpecBase/include/QuickSpecBase.h | 11 + .../Checkouts/Quick/Tests/LinuxMain.swift | 45 + .../AfterSuiteTests+ObjC.m | 32 + .../AfterSuiteTests.swift | 26 + .../QuickAfterSuiteTests/Info.plist | 24 + .../QuickFocusedTests/FocusedTests+ObjC.m | 56 + .../QuickFocusedTests/FocusedTests.swift | 59 + .../QuickTests/QuickFocusedTests/Info.plist | 24 + .../QuickTestHelpers/SpecRunner.swift | 30 + .../QuickTests/QuickTestHelpers/TestRun.swift | 9 + .../QuickTestHelpers/XCTestCaseProvider.swift | 52 + ...s_SharedExamplesTests_SharedExamples.swift | 20 + .../FunctionalTests/AfterEachTests.swift | 93 + .../FunctionalTests/BeforeEachTests.swift | 76 + .../FunctionalTests/BeforeSuiteTests.swift | 39 + .../BundleModuleNameTests.swift | 30 + .../AfterEach/Configuration+AfterEach.swift | 11 + .../Configuration+AfterEachTests.swift | 31 + .../BeforeEach/Configuration+BeforeEach.swift | 11 + .../Configuration+BeforeEachTests.swift | 28 + .../FunctionalTests/ContextTests.swift | 20 + .../CrossReferencingSpecs.swift | 19 + .../FunctionalTests/DescribeTests.swift | 34 + .../QuickTests/FunctionalTests/ItTests.swift | 127 + .../ObjC/AfterEachTests+ObjC.m | 81 + .../ObjC/BeforeEachTests+ObjC.m | 68 + .../ObjC/BeforeSuiteTests+ObjC.m | 39 + .../FunctionalTests/ObjC/FailureTests+ObjC.m | 61 + .../ObjC/FailureUsingXCTAssertTests+ObjC.m | 55 + .../FunctionalTests/ObjC/ItTests+ObjC.m | 42 + .../FunctionalTests/ObjC/PendingTests+ObjC.m | 60 + .../SharedExamples+BeforeEachTests+ObjC.m | 59 + .../ObjC/SharedExamplesTests+ObjC.m | 65 + .../FunctionalTests/PendingTests.swift | 54 + .../SharedExamples+BeforeEachTests.swift | 48 + .../FunctionalTests/SharedExamplesTests.swift | 54 + .../QuickTests/Helpers/QCKSpecRunner.h | 22 + .../QuickTests/Helpers/QCKSpecRunner.m | 33 + .../Helpers/QuickSpec+QuickSpec_MethodList.h | 11 + .../Helpers/QuickSpec+QuickSpec_MethodList.m | 31 + .../Helpers/QuickTestsBridgingHeader.h | 2 + ...tObservationCenter+QCKSuspendObservation.h | 20 + ...tObservationCenter+QCKSuspendObservation.m | 54 + .../Tests/QuickTests/QuickTests/Info.plist | 24 + .../QuickTests/QuickConfigurationTests.m | 12 + .../Carthage/Checkouts/Quick/script/release | 182 + .../Quick/script/travis-install-linux | 5 + .../Quick/script/travis-install-macos | 4 + .../Quick/script/travis-script-linux | 4 + .../Quick/script/travis-script-macos | 10 + .../Carthage/Checkouts/Result/.gitignore | 9 + .../Carthage/Checkouts/Result/.swift-version | 1 + .../Carthage/Checkouts/Result/.travis.yml | 44 + .../Carthage/Checkouts/Result/CONTRIBUTING.md | 23 + .../Carthage/Checkouts/Result/LICENSE | 21 + .../Carthage/Checkouts/Result/Package.swift | 10 + .../Carthage/Checkouts/Result/README.md | 113 + .../Carthage/Checkouts/Result/Result.podspec | 16 + .../Result/Result.xcodeproj/project.pbxproj | 1012 ++++++ .../contents.xcworkspacedata | 7 + .../xcschemes/Result-Mac.xcscheme | 113 + .../xcschemes/Result-iOS.xcscheme | 113 + .../xcschemes/Result-tvOS.xcscheme | 99 + .../xcschemes/Result-watchOS.xcscheme | 99 + .../Checkouts/Result/Result/Info.plist | 28 + .../Carthage/Checkouts/Result/Result/Result.h | 8 + .../Checkouts/Result/Result/Result.swift | 271 ++ .../Result/Result/ResultProtocol.swift | 200 ++ .../Checkouts/Result/Tests/LinuxMain.swift | 8 + .../Result/Tests/ResultTests/Info.plist | 24 + .../Tests/ResultTests/ResultTests.swift | 349 ++ .../Carthage/Checkouts/xcconfigs/.gitignore | 1 + .../Checkouts/xcconfigs/Base/Common.xcconfig | 190 + .../Base/Configurations/Debug.xcconfig | 43 + .../Base/Configurations/Profile.xcconfig | 27 + .../Base/Configurations/Release.xcconfig | 34 + .../Base/Configurations/Test.xcconfig | 10 + .../Base/Targets/Application.xcconfig | 12 + .../xcconfigs/Base/Targets/Framework.xcconfig | 37 + .../Base/Targets/StaticLibrary.xcconfig | 32 + .../Mac OS X/Mac-Application.xcconfig | 15 + .../xcconfigs/Mac OS X/Mac-Base.xcconfig | 19 + .../Mac OS X/Mac-DynamicLibrary.xcconfig | 18 + .../xcconfigs/Mac OS X/Mac-Framework.xcconfig | 11 + .../Mac OS X/Mac-StaticLibrary.xcconfig | 11 + .../Carthage/Checkouts/xcconfigs/README.md | 13 + .../xcconfigs/iOS/iOS-Application.xcconfig | 11 + .../Checkouts/xcconfigs/iOS/iOS-Base.xcconfig | 18 + .../xcconfigs/iOS/iOS-Framework.xcconfig | 11 + .../xcconfigs/iOS/iOS-StaticLibrary.xcconfig | 11 + .../xcconfigs/tvOS/tvOS-Application.xcconfig | 11 + .../xcconfigs/tvOS/tvOS-Base.xcconfig | 15 + .../xcconfigs/tvOS/tvOS-Framework.xcconfig | 11 + .../tvOS/tvOS-StaticLibrary.xcconfig | 11 + .../watchOS/watchOS-Application.xcconfig | 11 + .../xcconfigs/watchOS/watchOS-Base.xcconfig | 15 + .../watchOS/watchOS-Framework.xcconfig | 11 + .../watchOS/watchOS-StaticLibrary.xcconfig | 11 + .../Checkouts/ReactiveSwift/CodeOfConduct.md | 74 + .../Documentation/APIContracts.md | 568 +++ .../Documentation/BasicOperators.md | 519 +++ .../Documentation/DebuggingTechniques.md | 100 + .../Documentation/Example.OnlineSearch.md | 173 + .../Documentation/FrameworkOverview.md | 228 ++ .../Documentation/ReactivePrimitives.md | 115 + .../Documentation/RxComparison.md | 89 + Carthage/Checkouts/ReactiveSwift/LICENSE.md | 19 + .../ReactiveSwift/Logo/AF/Docs.afdesign | Bin 0 -> 17668 bytes .../ReactiveSwift/Logo/AF/JoinSlack.afdesign | Bin 0 -> 1108845 bytes .../Logo/AF/ReactiveSwift.afdesign | Bin 0 -> 26616 bytes .../ReactiveSwift/Logo/Icons/Swift.png | Bin 0 -> 111851 bytes .../ReactiveSwift/Logo/Icons/docset-icon.png | Bin 0 -> 1438 bytes .../Logo/Icons/docset-icon@2x.png | Bin 0 -> 2231 bytes .../Checkouts/ReactiveSwift/Logo/PNG/Docs.png | Bin 0 -> 6247 bytes .../ReactiveSwift/Logo/PNG/JoinSlack.png | Bin 0 -> 7065 bytes .../Logo/PNG/logo-Swift-unpadded.png | Bin 0 -> 54197 bytes .../ReactiveSwift/Logo/PNG/logo-Swift.png | Bin 0 -> 42578 bytes .../Checkouts/ReactiveSwift/Logo/Palette.png | Bin 0 -> 11112 bytes .../Checkouts/ReactiveSwift/Logo/README.md | 24 + .../ReactiveSwift/Logo/SVG/logo-Swift.svg | 34 + .../Checkouts/ReactiveSwift/Logo/header.png | Bin 0 -> 43393 bytes Carthage/Checkouts/ReactiveSwift/Package.pins | 24 + .../Checkouts/ReactiveSwift/Package.resolved | 34 + .../Checkouts/ReactiveSwift/Package.swift | 23 + Carthage/Checkouts/ReactiveSwift/README.md | 176 + .../Contents.swift | 154 + .../Sources/FormView.swift | 88 + .../Sources/StdlibExtensions.swift | 10 + .../Sources/UIKitExtensions.swift | 123 + .../Sources/PlaygroundUtility.swift | 10 + .../contents.xcplayground | 2 + .../Property.xcplaygroundpage/Contents.swift | 273 ++ .../Sandbox.xcplaygroundpage/Contents.swift | 25 + .../Signal.xcplaygroundpage/Contents.swift | 240 ++ .../Contents.swift | 767 ++++ .../Sources/PlaygroundUtility.swift | 10 + .../contents.xcplayground | 9 + .../ReactiveSwift/ReactiveSwift.podspec | 23 + .../ReactiveSwift.xcodeproj/project.pbxproj | 1620 +++++++++ .../contents.xcworkspacedata | 22 + .../ReactiveSwift/Sources/Action.swift | 299 ++ .../ReactiveSwift/Sources/Atomic.swift | 289 ++ .../Checkouts/ReactiveSwift/Sources/Bag.swift | 102 + .../Sources/Deprecations+Removals.swift | 195 + .../ReactiveSwift/Sources/Disposable.swift | 364 ++ .../ReactiveSwift/Sources/Event.swift | 180 + .../ReactiveSwift/Sources/EventLogger.swift | 139 + .../ReactiveSwift/Sources/Flatten.swift | 921 +++++ .../Sources/FoundationExtensions.swift | 138 + .../ReactiveSwift/Sources/Info.plist | 28 + .../Sources/InhabitableTypeGuards.swift | 132 + .../ReactiveSwift/Sources/Lifetime.swift | 98 + .../ReactiveSwift/Sources/Observer.swift | 97 + .../ReactiveSwift/Sources/Optional.swift | 42 + .../ReactiveSwift/Sources/Property.swift | 751 ++++ .../ReactiveSwift/Sources/Reactive.swift | 33 + .../ReactiveSwift/Sources/ReactiveSwift.h | 15 + .../Sources/ResultExtensions.swift | 13 + .../ReactiveSwift/Sources/Scheduler.swift | 556 +++ .../ReactiveSwift/Sources/Signal.swift | 2669 ++++++++++++++ .../Sources/SignalProducer.swift | 2293 ++++++++++++ .../Sources/UnidirectionalBinding.swift | 151 + .../Sources/ValidatingProperty.swift | 327 ++ .../ReactiveSwift/Tests/LinuxMain.swift | 21 + .../Tests/ReactiveSwiftTests/ActionSpec.swift | 336 ++ .../Tests/ReactiveSwiftTests/AtomicSpec.swift | 44 + .../Tests/ReactiveSwiftTests/BagSpec.swift | 54 + .../ReactiveSwiftTests/DeprecationSpec.swift | 8 + .../ReactiveSwiftTests/DisposableSpec.swift | 149 + .../ReactiveSwiftTests/FlattenSpec.swift | 1065 ++++++ .../FoundationExtensionsSpec.swift | 116 + .../Tests/ReactiveSwiftTests/Info.plist | 24 + .../ReactiveSwiftTests/LifetimeSpec.swift | 94 + .../ReactiveSwiftTests/PropertySpec.swift | 1756 +++++++++ .../ReactiveExtensionsSpec.swift | 33 + .../ReactiveSwiftTests/SchedulerSpec.swift | 311 ++ .../SignalLifetimeSpec.swift | 441 +++ .../SignalProducerLiftingSpec.swift | 2011 +++++++++++ .../SignalProducerNimbleMatchers.swift | 57 + .../SignalProducerSpec.swift | 2817 +++++++++++++++ .../Tests/ReactiveSwiftTests/SignalSpec.swift | 3144 +++++++++++++++++ .../Tests/ReactiveSwiftTests/TestError.swift | 43 + .../Tests/ReactiveSwiftTests/TestLogger.swift | 24 + .../UnidirectionalBindingSpec.swift | 135 + .../ValidatingPropertySpec.swift | 304 ++ Carthage/Checkouts/ReactiveSwift/script/build | 52 + .../ReactiveSwift/script/feed.xml.template | 4 + .../Checkouts/ReactiveSwift/script/gen-docs | 93 + .../ReactiveSwift/script/update-version | 24 + .../script/validate-playground.sh | 28 + Carthage/Checkouts/Result/.gitignore | 9 + Carthage/Checkouts/Result/.swift-version | 1 + Carthage/Checkouts/Result/.travis.yml | 44 + Carthage/Checkouts/Result/CONTRIBUTING.md | 23 + Carthage/Checkouts/Result/LICENSE | 21 + Carthage/Checkouts/Result/Package.swift | 10 + Carthage/Checkouts/Result/README.md | 113 + Carthage/Checkouts/Result/Result.podspec | 16 + .../Result/Result.xcodeproj/project.pbxproj | 1024 ++++++ .../contents.xcworkspacedata | 7 + Carthage/Checkouts/Result/Result/Info.plist | 28 + Carthage/Checkouts/Result/Result/Result.h | 8 + Carthage/Checkouts/Result/Result/Result.swift | 274 ++ .../Result/Result/ResultProtocol.swift | 203 ++ .../Checkouts/Result/Tests/LinuxMain.swift | 8 + .../Result/Tests/ResultTests/Info.plist | 24 + .../Tests/ResultTests/ResultTests.swift | 370 ++ Carthage/Checkouts/xcconfigs | 2 +- ReactiveAnimation.xcodeproj/project.pbxproj | 405 ++- .../xcschemes/ReactiveAnimation Mac.xcscheme | 19 +- .../xcschemes/ReactiveAnimation iOS.xcscheme | 19 +- .../contents.xcworkspacedata | 6 - .../ReactiveAnimation.xcscmblueprint | 42 + ReactiveAnimation/Animation.swift | 162 +- ReactiveAnimation/View.swift | 190 +- ReactiveAnimationDemo | 1 + 668 files changed, 82603 insertions(+), 253 deletions(-) delete mode 160000 Carthage/Checkouts/LlamaKit create mode 100644 Carthage/Checkouts/ReactiveSwift/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 Carthage/Checkouts/ReactiveSwift/.gitignore create mode 100644 Carthage/Checkouts/ReactiveSwift/.gitmodules create mode 100644 Carthage/Checkouts/ReactiveSwift/.jazzy.yaml create mode 100644 Carthage/Checkouts/ReactiveSwift/.swift-version create mode 100644 Carthage/Checkouts/ReactiveSwift/.travis.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/CHANGELOG.md create mode 100644 Carthage/Checkouts/ReactiveSwift/CONTRIBUTING.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Cartfile create mode 100644 Carthage/Checkouts/ReactiveSwift/Cartfile.private create mode 100644 Carthage/Checkouts/ReactiveSwift/Cartfile.resolved create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.github/ISSUE_TEMPLATE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.github/PULL_REQUEST_TEMPLATE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.gitignore create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.hound.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.swift-version create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.swiftlint.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.travis.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/CONTRIBUTING.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Dockerfile.test create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Gemfile create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Gemfile.lock create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/LICENSE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.podspec create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Package.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchExceptionSupport/CwlCatchException.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchExceptionSupport/include/CwlCatchException.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/mach_excServer.c create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/mach_excServer.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/DSL.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/FailureMessage.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThan.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLogical.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeNil.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeVoid.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeginWith.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/EndWith.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Equal.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Match.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ToSucceed.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Async.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Errors.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Functional.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/SourceLocation.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Stringers.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/LinuxMain.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/LinuxSupport.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/SynchronousTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/UserDescriptionTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfying.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCount.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/script/release create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/test create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.Package.test.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.github/ISSUE_TEMPLATE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.github/PULL_REQUEST_TEMPLATE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.gitignore create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.gitmodules create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.hound.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.swift-version create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.swiftlint.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.travis.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/CODE_OF_CONDUCT.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/CONTRIBUTING.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Dangerfile create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/ArrangeActAssert.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/BehavioralTesting.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/ConfiguringQuick.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/InstallingFileTemplates.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/InstallingQuick.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/MoreResources.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/NimbleAssertions.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/QuickExamplesAndGroups.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/QuickInObjectiveC.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/SettingUpYourXcodeProject.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/SharedExamples.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/TestUsingTestDoubles.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/Troubleshooting.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/ArrangeActAssert.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/BehavioralTesting.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/ConfiguringQuick.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/InstallingFileTemplates.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/InstallingQuick.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/MoreResources.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/NimbleAssertions.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/QuickExamplesAndGroups.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/QuickInObjectiveC.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/SettingUpYourXcodeProject.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/SharedExamples.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/TestUsingTestDoubles.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/TestingApps.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/Troubleshooting.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/pt-br/BehavioralTesting.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/pt-br/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/pt-br/SharedExamples.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/ArrangeActAssert.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/BehavioralTesting.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/ConfiguringQuick.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingFileTemplates.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingQuick.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/MoreResources.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/NimbleAssertions.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickExamplesAndGroups.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickInObjectiveC.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/SettingUpYourXcodeProject.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/SharedExamples.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/TestUsingTestDoubles.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/TestingApps.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/Troubleshooting.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.github/ISSUE_TEMPLATE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.github/PULL_REQUEST_TEMPLATE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/CONTRIBUTING.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/LICENSE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/.gitignore create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.c create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThan.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeVoid.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/EndWith.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Match.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Functional.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/SourceLocation.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Stringers.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/LinuxMain.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/LinuxSupport.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/SynchronousTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/UserDescriptionTest.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfying.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCount.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/script/release create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/test create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Gemfile create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Gemfile.lock create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/LICENSE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Package.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Objective-C/___FILEBASENAME___.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.podspec create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Rakefile create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Configuration/Configuration.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Configuration/QuickConfiguration.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/DSL/DSL.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Example.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/Closures.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/ExampleHooks.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/HooksPhase.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/SuiteHooks.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickMain.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/URL+FileName.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/World.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Quick.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/World.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickSpecBase/QuickSpecBase.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/LinuxMain.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/SpecRunner.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/TestRun.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/XCTestCaseProvider.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeSuiteTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BundleModuleNameTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CrossReferencingSpecs.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ItTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/AfterEachTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeEachTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeSuiteTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureUsingXCTAssertTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/ItTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/PendingTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamples+BeforeEachTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamplesTests+ObjC.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamplesTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.m create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/QuickConfigurationTests.m create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/release create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-install-linux create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-install-macos create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-script-linux create mode 100755 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-script-macos create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.gitignore create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.swift-version create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.travis.yml create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/CONTRIBUTING.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/LICENSE create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Package.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.podspec create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/Result.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/Result.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/ResultProtocol.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/LinuxMain.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/.gitignore create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Common.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Debug.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Profile.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Release.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Test.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/Application.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/Framework.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/StaticLibrary.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Application.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Base.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-DynamicLibrary.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Framework.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-StaticLibrary.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-Application.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-Base.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-Framework.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-StaticLibrary.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Application.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Base.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Framework.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-StaticLibrary.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Application.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Base.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Framework.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-StaticLibrary.xcconfig create mode 100644 Carthage/Checkouts/ReactiveSwift/CodeOfConduct.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Documentation/APIContracts.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Documentation/BasicOperators.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Documentation/DebuggingTechniques.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Documentation/Example.OnlineSearch.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Documentation/FrameworkOverview.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Documentation/ReactivePrimitives.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Documentation/RxComparison.md create mode 100644 Carthage/Checkouts/ReactiveSwift/LICENSE.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/AF/Docs.afdesign create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/AF/JoinSlack.afdesign create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/AF/ReactiveSwift.afdesign create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/Icons/Swift.png create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/Icons/docset-icon.png create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/Icons/docset-icon@2x.png create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/PNG/Docs.png create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/PNG/JoinSlack.png create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/PNG/logo-Swift-unpadded.png create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/PNG/logo-Swift.png create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/Palette.png create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/SVG/logo-Swift.svg create mode 100644 Carthage/Checkouts/ReactiveSwift/Logo/header.png create mode 100644 Carthage/Checkouts/ReactiveSwift/Package.pins create mode 100644 Carthage/Checkouts/ReactiveSwift/Package.resolved create mode 100644 Carthage/Checkouts/ReactiveSwift/Package.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/README.md create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Contents.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/FormView.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/StdlibExtensions.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/UIKitExtensions.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Sources/PlaygroundUtility.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/contents.xcplayground create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Property.xcplaygroundpage/Contents.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Sandbox.xcplaygroundpage/Contents.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Signal.xcplaygroundpage/Contents.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/SignalProducer.xcplaygroundpage/Contents.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Sources/PlaygroundUtility.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/contents.xcplayground create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift.podspec create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift.xcodeproj/project.pbxproj create mode 100644 Carthage/Checkouts/ReactiveSwift/ReactiveSwift.xcworkspace/contents.xcworkspacedata create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Action.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Atomic.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Bag.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Deprecations+Removals.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Disposable.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Event.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/EventLogger.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Flatten.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/FoundationExtensions.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/InhabitableTypeGuards.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Lifetime.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Observer.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Optional.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Property.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Reactive.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/ReactiveSwift.h create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/ResultExtensions.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Scheduler.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/Signal.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/SignalProducer.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/UnidirectionalBinding.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Sources/ValidatingProperty.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/LinuxMain.swift create mode 100755 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ActionSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/AtomicSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/BagSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/DeprecationSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/DisposableSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/FlattenSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/FoundationExtensionsSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/Info.plist create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/LifetimeSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/PropertySpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ReactiveExtensionsSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SchedulerSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalLifetimeSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerNimbleMatchers.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerSpec.swift create mode 100755 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/TestError.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/TestLogger.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/UnidirectionalBindingSpec.swift create mode 100644 Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ValidatingPropertySpec.swift create mode 100755 Carthage/Checkouts/ReactiveSwift/script/build create mode 100644 Carthage/Checkouts/ReactiveSwift/script/feed.xml.template create mode 100755 Carthage/Checkouts/ReactiveSwift/script/gen-docs create mode 100755 Carthage/Checkouts/ReactiveSwift/script/update-version create mode 100755 Carthage/Checkouts/ReactiveSwift/script/validate-playground.sh create mode 100644 Carthage/Checkouts/Result/.gitignore create mode 100644 Carthage/Checkouts/Result/.swift-version create mode 100644 Carthage/Checkouts/Result/.travis.yml create mode 100644 Carthage/Checkouts/Result/CONTRIBUTING.md create mode 100644 Carthage/Checkouts/Result/LICENSE create mode 100644 Carthage/Checkouts/Result/Package.swift create mode 100644 Carthage/Checkouts/Result/README.md create mode 100644 Carthage/Checkouts/Result/Result.podspec create mode 100644 Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj create mode 100644 Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Carthage/Checkouts/Result/Result/Info.plist create mode 100644 Carthage/Checkouts/Result/Result/Result.h create mode 100644 Carthage/Checkouts/Result/Result/Result.swift create mode 100644 Carthage/Checkouts/Result/Result/ResultProtocol.swift create mode 100644 Carthage/Checkouts/Result/Tests/LinuxMain.swift create mode 100644 Carthage/Checkouts/Result/Tests/ResultTests/Info.plist create mode 100644 Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift create mode 100644 ReactiveAnimation.xcworkspace/xcshareddata/ReactiveAnimation.xcscmblueprint create mode 160000 ReactiveAnimationDemo diff --git a/Cartfile b/Cartfile index d5386ab..77938c7 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "ReactiveCocoa/ReactiveCocoa" "v3.0-alpha.3" +github "ReactiveCocoa/ReactiveCocoa" "6.0.0-alpha.1" \ No newline at end of file diff --git a/Cartfile.resolved b/Cartfile.resolved index b6c5fa9..ef6f9f5 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1,4 @@ -github "LlamaKit/LlamaKit" "v0.6.0" -github "jspahrsummers/xcconfigs" "0.7.2" -github "ReactiveCocoa/ReactiveCocoa" "ad02d8356b43e2c38f3d4d87ea0127c5f8572668" +github "ReactiveCocoa/ReactiveCocoa" "6.0.0-alpha.1" +github "ReactiveCocoa/ReactiveSwift" "2.0.0-alpha.2" +github "antitypical/Result" "3.2.3" +github "jspahrsummers/xcconfigs" "0.10" diff --git a/Carthage/Checkouts/LlamaKit b/Carthage/Checkouts/LlamaKit deleted file mode 160000 index e28d7f6..0000000 --- a/Carthage/Checkouts/LlamaKit +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e28d7f6e82fbd5dcd5388b36e2acf4eedb44b4e8 diff --git a/Carthage/Checkouts/ReactiveCocoa b/Carthage/Checkouts/ReactiveCocoa index ad02d83..13f30bb 160000 --- a/Carthage/Checkouts/ReactiveCocoa +++ b/Carthage/Checkouts/ReactiveCocoa @@ -1 +1 @@ -Subproject commit ad02d8356b43e2c38f3d4d87ea0127c5f8572668 +Subproject commit 13f30bb79fb37fa8c79ef1885d6f2e355dac3da0 diff --git a/Carthage/Checkouts/ReactiveSwift/.github/PULL_REQUEST_TEMPLATE.md b/Carthage/Checkouts/ReactiveSwift/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..3ddb9d4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,3 @@ + +#### Checklist +- [ ] Updated CHANGELOG.md. diff --git a/Carthage/Checkouts/ReactiveSwift/.gitignore b/Carthage/Checkouts/ReactiveSwift/.gitignore new file mode 100644 index 0000000..69aeaa0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/.gitignore @@ -0,0 +1,30 @@ +# macOS +.DS_Store + +# Xcode +build/* +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +!default.xcworkspace +xcuserdata +profile +*.moved-aside +PlaygroundUtility.remap +*.xctimeline +*.xcscmblueprint + +# SwiftPM +.build +Packages + +# Carthage +Carthage/Build + +# Jazzy +docs diff --git a/Carthage/Checkouts/ReactiveSwift/.gitmodules b/Carthage/Checkouts/ReactiveSwift/.gitmodules new file mode 100644 index 0000000..8283dfc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/.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/ReactiveSwift/.jazzy.yaml b/Carthage/Checkouts/ReactiveSwift/.jazzy.yaml new file mode 100644 index 0000000..8484254 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/.jazzy.yaml @@ -0,0 +1,87 @@ +custom_categories: + - name: Getting Started + children: + - ReactivePrimitives + - BasicOperators + - Example.OnlineSearch + - RxComparison + - name: Advanced Topics + children: + - APIContracts + - DebuggingTechniques + - name: Signal + children: + - Signal + - SignalProtocol + - FlattenStrategy + - name: SignalProducer + children: + - SignalProducer + - SignalProducerProtocol + - name: Property + children: + - Property + - PropertyProtocol + - MutableProperty + - MutablePropertyProtocol + - ValidatingProperty + - name: Action + children: + - Action + - ActionError + - name: Bindings + children: + - BindingSource + - BindingTarget + - BindingTargetProvider + - name: Scheduler Protocols + children: + - DateScheduler + - Scheduler + - name: Schedulers + children: + - ImmediateScheduler + - QueueScheduler + - TestScheduler + - UIScheduler + - name: Reactive Extensions + children: + - Reactive + - ReactiveExtensionsProvider + - name: Lifetime + children: + - Lifetime + - name: Disposable + children: + - AnyDisposable + - ActionDisposable + - Disposable + - CompositeDisposable + - ScopedDisposable + - SerialDisposable + - SimpleDisposable + - +=(_:_:) + - name: Debugging + children: + - EventLogger + - LoggingEvent + - name: Utilities + children: + - Atomic + - Bag + - Optional + - OptionalProtocol +theme: fullwidth +skip_undocumented: true +readme: README.md +documentation: Documentation/*.md +hide_documentation_coverage: true +xcodebuild_arguments: + - -workspace + - ReactiveSwift.xcworkspace + - -scheme + - ReactiveSwift-macOS +author: ReactiveCocoa +author_url: https://reactivecocoa.io/ +github_url: https://github.com/ReactiveCocoa/ReactiveSwift/ +dash_url: http://reactivecocoa.io/reactiveswift/docs/ReactiveSwift.xml diff --git a/Carthage/Checkouts/ReactiveSwift/.swift-version b/Carthage/Checkouts/ReactiveSwift/.swift-version new file mode 100644 index 0000000..8c50098 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/.swift-version @@ -0,0 +1 @@ +3.1 diff --git a/Carthage/Checkouts/ReactiveSwift/.travis.yml b/Carthage/Checkouts/ReactiveSwift/.travis.yml new file mode 100644 index 0000000..b0549f6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/.travis.yml @@ -0,0 +1,110 @@ +language: objective-c +osx_image: xcode8.3 +before_install: + - brew uninstall carthage + - HOMEBREW_NO_AUTO_UPDATE=1 brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/6ae4f69a652fb0ecb102b0c9216378679a4f1b92/Formula/carthage.rb # 0.22.0 +install: true +branches: + only: + - master + # Credit: @Omnikron13, https://github.com/mojombo/semver/issues/32 + - /^(\d+\.\d+\.\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/ + - /^hotfix-(\d+\.\d+\.\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/ +script: + - script/build +xcode_workspace: ReactiveSwift.xcworkspace +cache: + directories: Carthage/Build +jobs: + include: + - xcode_scheme: ReactiveSwift-macOS + env: + - XCODE_SDK=macosx + - XCODE_ACTION="build test" + - XCODE_DESTINATION="arch=x86_64" + - XCODE_PLAYGROUND_TARGET="x86_64-apple-macosx10.10" + - xcode_scheme: ReactiveSwift-iOS + env: + - XCODE_SDK=iphonesimulator + - XCODE_ACTION="build-for-testing test-without-building" + - XCODE_DESTINATION="platform=iOS Simulator,name=iPhone 6s" + - xcode_scheme: ReactiveSwift-iOS + env: + - XCODE_SDK=iphonesimulator + - XCODE_ACTION="build-for-testing test-without-building" + - XCODE_DESTINATION="platform=iOS Simulator,name=iPhone 5" + - xcode_scheme: ReactiveSwift-tvOS + env: + - XCODE_SDK=appletvsimulator + - XCODE_ACTION="build-for-testing test-without-building" + - XCODE_DESTINATION="platform=tvOS Simulator,name=Apple TV 1080p" + - xcode_scheme: ReactiveSwift-watchOS + env: + - XCODE_SDK=watchsimulator + - XCODE_ACTION=build + - XCODE_DESTINATION="platform=watchOS Simulator,name=Apple Watch - 38mm,OS=2.2" + - script: + - pod repo update --silent + - pod lib lint ReactiveSwift.podspec + env: + - JOB=PODSPEC + - script: + - swift --version + - swift build + - SWIFTPM_TEST_ReactiveSwift=YES swift test + git: + submodules: false + env: + - JOB=SWIFTPM_DARWIN + - before_install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" + script: + - swift --version + - swift build + - SWIFTPM_TEST_ReactiveSwift=YES swift test + git: + submodules: false + env: + - JOB=SWIFT_4 + - SWIFT_VERSION=4.0-DEVELOPMENT-SNAPSHOT-2017-06-06-a + - os: linux + language: generic + sudo: required + dist: trusty + before_install: + - eval "$(curl -sL https://gist.githubusercontent.com/kylef/5c0475ff02b7c7671d2a/raw/9f442512a46d7a2af7b850d65a7e9bd31edfb09b/swiftenv-install.sh)" + script: + - swift --version + - swift build + - SWIFTPM_TEST_ReactiveSwift=YES swift test + git: + submodules: false + env: JOB=SWIFTPM_LINUX + - stage: prepare carthage cache + script: carthage build --cache-builds + - stage: carthage + script: + - carthage build --cache-builds --no-skip-current --platform mac + - script: + - carthage build --cache-builds --no-skip-current --platform iOS + - script: + - carthage build --cache-builds --no-skip-current --platform tvOS + - script: + - carthage build --cache-builds --no-skip-current --platform watchOS + - stage: deploy + before_install: true + script: skip + deploy: + provider: script + script: script/gen-docs + on: + repo: ReactiveCocoa/ReactiveSwift + tags: true + env: + - JOB=JAZZY_DOCS_GEN + - secure: "FZmWA8jEF1nNYEeolK+bDT/n+AJtQGa9/s5SXYg05Zs4GWReDimqo41y2UBJxdeaeixHab4N14sR5OL6R2pf4ZE0LVq4Ln17nsIPTRvMQeH74apJ/+d8y9pzQuyw8MsPeV9VwWAbhie+fjOKFEoqwo98junGJFFqNVKhZX3AdDgB50jNffEqzG7qedwHX5oM+Me8T7oq0UWblGe4CppCXEvDshIKPXxIC1foiVyJoK31WRLIX7c1m99ECFjfqqopal5EUtvgCabZkRBilsYB8rAngrpTg5NpHSPxV3VAiheCmXs12txHek8fPUNIjPf8dhP5QfwK3VUUCS4VcSOJSoTP3HzAn1OirYOhpnmrymLw2TCo4kzPGhpF+58cQQcjbO7TxA1KgLvTtLfSc2MSQTUniPC0jOzl42q5PVttxkE2wDcGBiraxVa++uGWGbjyfJBXVXNz2KnvmVmxn9YMNw2kGbptZrBQw73tHuA0w8cfK+AqckpuY2XDZEzjcumTb5Tr1AC2KWNP3sjsVVlE0yShQDyqVrHE2XP2UPKux04ZgaEciVnBisAN9c4Tm5RjbDw7EOqpy583bxtIvWkAY1rkf4+SXyfNWcHqGWkANGcgeSe9k7C6hwEWb9v90iMrD/D7hzvhioUBfgRhlrbvnAtA9K3fH2VvKGIkTj/blcY=" + - secure: "sisLYdFh8r7WHW3c5sPhuIuuQucAeH66Hx/D8M9Ax9bZthITrw4JGyC+sfnLRLM4rCYrVSBAj6kiJTxK5aWjYEijKZoMf1o5/6s6IkKZv7ocaoIbIF8tVCf9uEIwzoQlStz7wRngz5Qi2PDoeuB9j/p98GV24+/09BVPSnDQ968bPrze1hJTj6xjOz3/A891rNp43g3+mA+mtnEDPmF57f51LWoJRMSdv/IlYKbJxNjKH/xWTufCfHkyKWoPWiSHiloaqWWj0MU8QNxhGHFl/gLa2ljNgSE0cEO1769v6uFK/3PJugjRAqZCs8ssbmtRBikV56LUKcF9TqQVMn5Pu08aHexnsa5P9S2+LAHGjA54rhHiJJaQB58y9UXRUTpZIx7BSajZi1+D507stWfrNB6dl1rt6txNidXDNGPF27WiViwYuET9eLrraPpzdMQzxBn0QYSfbadORwDwUP0hDOS9LC8HQMN8ECRc4mOHgoXfC2qYeKfadFpwBlRYgWKH2S+O3AcwCPUdvxe98EGLR7U5/YeHawu32qm3M1QJHeW0lvHIEnRzV7vQzrOFPO6JjKCpsObsHniy0PSfaLL3NajXBQiiYiR+qTAOT5fRuUNV6ZR648w+y1dto1Bykb+h2Z2B0/sgXQNsl4IcAfJjo7xUNh2F75PQeh7u55aDXyY=" +notifications: + email: false + slack: + secure: C9QTry5wUG9CfeH3rm3Z19R5rDWqDO7EhHAqHDXBxT6CpGRkTPFliJexpjBYB4sroJ8CiY5ZgTI2sjRBiAdGoE5ZQkfnwSoKQhWXkwo19TnbSnufr3cKO2SZkUhBqOlZcA+mgfjZ7rm2wm7RhpCR/4z8oBXDN4/xv0U5R2fLCLE= diff --git a/Carthage/Checkouts/ReactiveSwift/CHANGELOG.md b/Carthage/Checkouts/ReactiveSwift/CHANGELOG.md new file mode 100644 index 0000000..0092124 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/CHANGELOG.md @@ -0,0 +1,216 @@ +# master +*Please add new entries at the top.* + +# 2.0.0-alpha.2 +1. In Swift 3.2 or later, you can use `map()` with the new Smart Key Paths. (#435, kudos to @sharplet) + +1. When composing `Signal` and `SignalProducer` of inhabitable types, e.g. `Never` or `NoError`, ReactiveSwift now warns about operators that are illogical to use, and traps at runtime when such operators attempt to instantiate an instance. (#429, kudos to @andersio) + +1. N-ary `SignalProducer` operators are now generic and accept any type that can be expressed as `SignalProducer`. (#410, kudos to @andersio) + Types may conform to `SignalProducerConvertible` to be an eligible operand. + +1. The performance of `SignalProducer` has been improved significantly. (#140, kudos to @andersio) + + All lifted `SignalProducer` operators no longer yield an extra `Signal`. As a result, the calling overhead of event delivery is generally reduced proportionally to the level of chaining of lifted operators. + +1. `interrupted` now respects `observe(on:)`. (#140) + + When a produced `Signal` is interrupted, if `observe(on:)` is the last applied operator, `interrupted` would now be delivered on the `Scheduler` passed to `observe(on:)` just like other events. + +1. Feedbacks from `isExecuting` to the state of the same `Action`, including all `enabledIf` convenience initializers, no longer deadlocks. (#400, kudos to @andersio) + +1. `MutableProperty` now enforces exclusivity of access. (#419, kudos to @andersio) + + In other words, nested modification in `MutableProperty.modify` is now prohibited. Generally speaking, it should have extremely limited impact as in most cases the `MutableProperty` would have been deadlocked already. + +1. `promoteError` can now infer the new error type from the context. (#413, kudos to @andersio) + +# 2.0.0-alpha.1 +This is the first alpha release of ReactiveSwift 2.0. It requires Swift 3.1 (Xcode 8.3). + +## Changes +### Modified `Signal` lifetime semantics (#355) +The `Signal` lifetime semantics is modified to improve interoperability with memory debugging tools. ReactiveSwift 2.0 adopted a new `Signal` internal which does not exploit deliberate retain cycles that consequentially confuse memory debugging tools. + +A `Signal` is now automatically and silently disposed of, when: + +1. the `Signal` is not retained and has no active observer; or +1. **(New)** both the `Signal` and its input observer are not retained. + +It is expected that memory debugging tools would no longer report irrelevant negative leaks that were once caused by the ReactiveSwift internals. + +### `SignalProducer` resource management (#334) +`SignalProducer` now uses `Lifetime` for resource management. You may observe the `Lifetime` for the disposal of the produced `Signal`. + +```swift +let producer = SignalProducer { observer, lifetime in + if let disposable = numbers.observe(observer) { + lifetime.observeEnded(disposable.dispose) + } +} +``` + +Two `Disposable`-accepting methods `Lifetime.Type.+=` and `Lifetime.add` are provided to aid migration, and are subject to removal in a future release. + +### Signal and SignalProducer +1. All `Signal` and `SignalProducer` operators now belongs to the respective concrete types. (#304) + + Custom operators should extend the concrete types directly. `SignalProtocol` and `SignalProducerProtocol` should be used only for constraining associated types. + +1. `combineLatest` and `zip` are optimised to have a constant overhead regardless of arity, mitigating the possibility of stack overflow. (#345) + +1. `flatMap(_:transform:)` is renamed to `flatMap(_:_:)`. (#339) + +1. `promoteErrors(_:)`is renamed to `promoteError(_:)`. (#408) + +1. `Event` is renamed to `Signal.Event`. (#376) + +1. `Observer` is renamed to `Signal.Observer`. (#376) + +### Action + +1. `Action(input:_:)`, `Action(_:)`, `Action(enabledIf:_:)` and `Action(state:enabledIf:_:)` are renamed to `Action(state:execute:)`, `Action(execute:)`, `Action(enabledIf:execute:)` and `Action(state:enabledIf:execute:)` respectively. (#325) + +### Properties +1. The memory overhead of property composition has been considerably reduced. (#340) + +### Bindings +1. The `BindingSource` now requires only a producer representation of `self`. (#359) + +1. The `<~` operator overloads are now provided by `BindingTargetProvider`. (#359) + +### Disposables +1. `SimpleDisposable` and `ActionDisposable` has been folded into `AnyDisposable`. (#412) + +1. `CompositeDisposable.DisposableHandle` is replaced by `Disposable?`. (#363) + +1. The `+=` operator overloads for `CompositeDisposable` are now hosted inside the concrete types. (#412) + +### Bag + +1. Improved the performance of `Bag`. (#354) + +1. `RemovalToken` is renamed to `Bag.Token`. (#354) + +### Schedulers + +1. `Scheduler` gains a class bound. (#333) + +### Lifetime + +1. `Lifetime.ended` now uses the inhabitable `Never` as its value type. (#392) + +### Atomic + +1. `Signal` and `Atomic` now use `os_unfair_lock` when it is available. (#342) + +## Additions +1. `FlattenStrategy.race` is introduced. (#233, kudos to @inamiy) + + `race` flattens whichever inner signal that first sends an event, and ignores the rest. + +1. `FlattenStrategy.concurrent` is introduced. (#298, kudos to @andersio) + + `concurrent` starts and flattens inner signals according to the specified concurrency limit. If an inner signal is received after the limit is reached, it would be queued and drained later as the in-flight inner signals terminate. + +1. New operators: `reduce(into:)` and `scan(into:)`. (#365, kudos to @ikesyo) + + These variants pass to the closure an `inout` reference to the accumulator, which helps the performance when a large value type is used, e.g. collection. + +1. `Property(initial:then:)` gains overloads that accept a producer or signal of the wrapped value type when the value type is an `Optional`. (#396) + +## Deprecations and Removals +1. The requirement `BindingSource.observe(_:during:)` and the implementations have been removed. + +1. All Swift 2 (ReactiveCocoa 4) obsolete symbols have been removed. + +1. All deprecated methods and protocols in ReactiveSwift 1.1.x are no longer available. + +## Acknowledgement + +Thank you to all of @ReactiveCocoa/reactiveswift and all our contributors, but especially to @andersio, @calebd, @eimantas, @ikesyo, @inamiy, @Marcocanc, @mdiep, @NachoSoto, @sharplet and @tjnet. ReactiveSwift is only possible due to the many hours of work that these individuals have volunteered. ❤️ + +# 1.1.3 +## Deprecation +1. `observe(_:during:)` is now deprecated. It would be removed in ReactiveSwift 2.0. + Use `take(during:)` and the relevant observation API of `Signal`, `SignalProducer` and `Property` instead. (#374) + +# 1.1.2 +## Changes +1. Fixed a rare occurrence of `interrupted` events being emitted by a `Property`. (#362) + +# 1.1.1 +## Changes +1. The properties `Signal.negated`, `SignalProducer.negated` and `Property.negated` are deprecated. Use its operator form `negate()` instead. + +# 1.1 +## Additions + +#### General +1. New boolean operators: `and`, `or` and `negated`; available on `Signal`, `SignalProducer` and `Property` types. (#160, kudos to @cristianames92) +2. New operator `filterMap`. (#232, kudos to @RuiAAPeres) +3. New operator `lazyMap(on:_:)`. It coalesces `value` events when they are emitted at a rate faster than the rate the given scheduler can handle. The transform is applied on only the coalesced and the uncontended values. (#240, kudos to @liscio) +4. New protocol `BindingTargetProvider`, which replaces `BindingTargetProtocol`. (#254, kudos to @andersio) + +#### SignalProducer +5. New initializer `SignalProducer(_:)`, which takes a `@escaping () -> Value` closure. It is similar to `SignalProducer(value:)`, but it lazily evaluates the value every time the producer is started. (#240, kudos to @liscio) + +#### Lifetime +6. New method `Lifetime.observeEnded(self:)`. This is now the recommended way to explicitly observe the end of a `Lifetime`. Use `Lifetime.ended` only if composition is needed. (#229, kudos to @andersio) +7. New factory method `Lifetime.make()`, which returns a tuple of `Lifetime` and `Lifetime.Token`. (#236, kudos to @sharplet) + +#### Properties +8. `ValidatingProperty`: A mutable property that validates mutations before committing them. (#182, kudos to @andersio). +9. A new interactive UI playground: `ReactiveSwift-UIExamples.playground`. It demonstrates how `ValidatingProperty` can be used in an interactive form UI. (#182) + +## Changes +1. Flattening a signal of `Sequence` no longer requires an explicit `FlattenStrategy`. (#199, kudos to @dmcrodrigues) +2. `BindingSourceProtocol` has been renamed to `BindingSource`. (#254) +3. `SchedulerProtocol` and `DateSchedulerProtocol` has been renamed to `Scheduler` and `DateScheduler`, respectively. (#257) +4. `take(during:)` now handles ended `Lifetime` properly. (#229) + +## Deprecations +1. `AtomicProtocol` has been deprecated. (#279) +2. `ActionProtocol` has been deprecated. (#284) +3. `ObserverProtocol` has been deprecated. (#262) +4. `BindingTargetProtocol` has been deprecated. (#254) + +# 1.0.1 +## Changes +1. Fixed a couple of infinite feedback loops in `Action`. (#221) +2. Fixed a race condition of `Signal` which might result in a deadlock when a signal is sent a terminal event as a result of an observer of it being released. (#267) + +Kudos to @mdiep, @sharplet and @andersio who helped review the pull requests. + +# 1.0 + +This is the first major release of ReactiveSwift, a multi-platform, pure-Swift functional reactive programming library spun off from [ReactiveCocoa](https://github.com/ReactiveCocoa/ReactiveCocoa). As Swift continues to expand beyond Apple’s platforms, we hope that ReactiveSwift will see broader adoption. To learn more, please refer to ReactiveCocoa’s [CHANGELOG](https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/CHANGELOG.md). + +Major changes since ReactiveCocoa 4 include: +- **Updated for Swift 3** + + APIs have been updated and renamed to adhere to the Swift 3 [API Design Guidelines](https://swift.org/documentation/api-design-guidelines/). +- **Signal Lifetime Semantics** + + `Signal`s now live and continue to emit events only while either (a) they have observers or (b) they are retained. This clears up a number of unexpected cases and makes Signals much less dangerous. +- **Reactive Proxies** + + Types can now declare conformance to `ReactiveExtensionsProvider` to expose a `reactive` property that’s generic over `self`. This property hosts reactive extensions to the type, such as the ones provided on `NotificationCenter` and `URLSession`. +- **Property Composition** + + `Property`s can now be composed. They expose many of the familiar operators from `Signal` and `SignalProducer`, including `map`, `flatMap`, `combineLatest`, etc. +- **Binding Primitives** + + `BindingTargetProtocol` and `BindingSourceProtocol` have been introduced to allow binding of observable instances to targets. `BindingTarget` is a new concrete type that can be used to wrap a settable but non-observable property. +- **Lifetime** + + `Lifetime` is introduced to represent the lifetime of any arbitrary reference type. This can be used with the new `take(during:)` operator, but also forms part of the new binding APIs. +- **Race-free Action** + + A new `Action` initializer `Action(state:enabledIf:_:)` has been introduced. It allows the latest value of any arbitrary property to be supplied to the execution closure in addition to the input from `apply(_:)`, while having the availability being derived from the property. + + This eliminates a data race in ReactiveCocoa 4.x, when both the `enabledIf` predicate and the execution closure depend on an overlapping set of properties. + +Extensive use of Swift’s `@available` declaration has been used to ease migration from ReactiveCocoa 4. Xcode should have fix-its for almost all changes from older APIs. + +Thank you to all of @ReactiveCocoa/ReactiveSwift and all our contributors, but especially to @andersio, @liscio, @mdiep, @nachosoto, and @sharplet. ReactiveSwift is only possible due to the many hours of work that these individuals have volunteered. ❤️ diff --git a/Carthage/Checkouts/ReactiveSwift/CONTRIBUTING.md b/Carthage/Checkouts/ReactiveSwift/CONTRIBUTING.md new file mode 100644 index 0000000..8f5d77c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/CONTRIBUTING.md @@ -0,0 +1,156 @@ +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. We are also happy to help you in our Slack room (ping [@ReactiveCocoa](https://twitter.com/ReactiveCocoa) for an invitation). + +## 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 ([Objective-c](https://github.com/github/objective-c-conventions) and [Swift](https://github.com/github/swift-style-guide)). If your particular case is not described in the coding convention, check the ReactiveCocoa codebase. + +Thanks for contributing! :boom::camel: + +## Documenting Code + +Please follow these guidelines when documenting code using [Xcode's markup](https://developer.apple.com/library/mac/documentation/Xcode/Reference/xcode_markup_formatting_ref/): + +- Expand lines up to 80 characters per line. If the line extends beyond 80 characters the next line must be indented at the previous markup delimiter's colon position + 1 space: + +``` +/// DO: +/// For the sake of the demonstration we will use the lorem ipsum text here. +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ullamcorper +/// tempor dolor a cras amet. +/// +/// - returns: Cras a convallis dolor, sed pellentesque mi. Integer suscipit +/// fringilla turpis in bibendum volutpat. +/// ... +/// DON'T +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ullamcorper tempor dolor a cras amet. +/// +/// - returns: Cras a convallis dolor, sed pellentesque mi. Integer suscipit fringilla turpis in bibendum volutpat. +/// ... +/// DON'T II +/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ullamcorper +/// tempor dolor a cras amet. +/// +/// - returns: Cras a convallis dolor, sed pellentesque mi. Integer suscipit +/// fringilla turpis in bibendum volutpat. +``` + +- Always use the `parameters` delimiter instead of the `parameter` delimiter even if a function has only one parameter: + +``` +/// DO: +/// - parameters: +/// - foo: Instance of `Foo`. +/// DON'T: +/// - parameter foo: Instance of `Foo`. +``` + +- Do not add a `return` delimiter to an initializer's markup: + +``` +/// DO: +/// Initialises instance of `Foo` with given arguments. +init(withBar bar: Bar = Bar.defaultBar()) { + ... +/// DON'T: +/// Initialises instance of `Foo` with given arguments. +/// +/// - returns: Initialized `Foo` with default `Bar` +init(withBar bar: Bar = Bar.defaultBar()) { + ... +``` + +- Treat parameter declaration as a separate sentence/paragraph: + +``` +/// DO: +/// - parameters: +/// - foo: A foo for the function. +/// ... +/// DON'T: +/// - parameters: +/// - foo: foo for the function; +``` + +- Add one line between markup delimiters and no whitespace lines between a function's `parameters`: + +``` +/// DO: +/// - note: This is an amazing function. +/// +/// - parameters: +/// - foo: Instance of `Foo`. +/// - bar: Instance of `Bar`. +/// +/// - returns: Something magical. +/// ... +/// DON'T: +/// - note: Don't forget to breathe, it's important! 😎 +/// - parameters: +/// - foo: Instance of `Foo`. +/// - bar: Instance of `Bar`. +/// - returns: Something claustrophobic. +``` + +- Use code voice to highlight symbols in descriptions, parameter definitions, return statments and elsewhere. + +``` +/// DO: +/// Create instance of `Foo` by passing it `Bar`. +/// +/// - parameters: +/// - bar: Instance of `Bar`. +/// ... +/// DON'T: +/// Create instance of Foo by passing it Bar. +/// +/// - parameters: +/// - bar: Instance of Bar. +``` + +- The `precondition`, `parameters` and `return` delimiters should come last in that order in the markup block before the method's signature. + +``` +/// DO: +/// Create instance of `Foo` by passing it `Bar`. +/// +/// - note: The `foo` is not retained by the receiver. +/// +/// - parameters: +/// - foo: Instance of `Foo`. +init(foo: Foo) { +/* ... */ +/// DON'T +/// Create counter that will count down from `number`. +/// +/// - parameters: +/// - number: Number to count down from. +/// +/// - precondition: `number` must be non-negative. +init(count: Int) +``` + +- Use first person's active voice in present simple tense. + +``` +/// DO: +/// Do something magical and return pixie dust from `self`. +/// +/// DON'T: +/// Does something magical and returns pixie dust from `self`. +``` + diff --git a/Carthage/Checkouts/ReactiveSwift/Cartfile b/Carthage/Checkouts/ReactiveSwift/Cartfile new file mode 100644 index 0000000..3081345 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Cartfile @@ -0,0 +1 @@ +github "antitypical/Result" ~> 3.2.1 diff --git a/Carthage/Checkouts/ReactiveSwift/Cartfile.private b/Carthage/Checkouts/ReactiveSwift/Cartfile.private new file mode 100644 index 0000000..0246f30 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Cartfile.private @@ -0,0 +1,3 @@ +github "jspahrsummers/xcconfigs" "3d9d996" +github "Quick/Quick" ~> 1.1 +github "Quick/Nimble" ~> 7.0.1 diff --git a/Carthage/Checkouts/ReactiveSwift/Cartfile.resolved b/Carthage/Checkouts/ReactiveSwift/Cartfile.resolved new file mode 100644 index 0000000..465f0b6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Cartfile.resolved @@ -0,0 +1,4 @@ +github "Quick/Nimble" "v7.0.1" +github "Quick/Quick" "v1.1.0" +github "antitypical/Result" "3.2.1" +github "jspahrsummers/xcconfigs" "3d9d99634cae6d586e272543d527681283b33eb0" diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.github/ISSUE_TEMPLATE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..85e591e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/.github/PULL_REQUEST_TEMPLATE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..20e40c8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/.gitignore b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.gitignore new file mode 100644 index 0000000..e50906d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.gitignore @@ -0,0 +1,21 @@ +.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/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/ReactiveSwift/Carthage/Checkouts/Nimble/.hound.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.hound.yml new file mode 100644 index 0000000..b867fd9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.swift-version b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.swiftlint.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.swiftlint.yml new file mode 100644 index 0000000..973705d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.swiftlint.yml @@ -0,0 +1,19 @@ +disabled_rules: + - line_length + - todo + - variable_name + - force_try + - function_parameter_count + - force_cast + - type_name + - large_tuple + +included: + - Sources + - Tests + +excluded: + - Sources/Lib + +trailing_comma: + mandatory_comma: true diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.travis.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.travis.yml new file mode 100644 index 0000000..d7be783 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/.travis.yml @@ -0,0 +1,25 @@ +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=swiftpm + - os: linux + dist: trusty + sudo: required + env: TYPE=swiftpm + 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/ReactiveSwift/Carthage/Checkouts/Nimble/CONTRIBUTING.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/CONTRIBUTING.md new file mode 100644 index 0000000..d9c4ba6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Dockerfile.test b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Dockerfile.test new file mode 100644 index 0000000..a995ae2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Dockerfile.test @@ -0,0 +1,3 @@ +FROM swift:latest +COPY . . +CMD ./test swiftpm diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Gemfile b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Gemfile new file mode 100644 index 0000000..0211a92 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Gemfile @@ -0,0 +1,4 @@ +# A sample Gemfile +source "https://rubygems.org" + +gem 'cocoapods', '1.2.0' diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Gemfile.lock b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Gemfile.lock new file mode 100644 index 0000000..edde6bb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Gemfile.lock @@ -0,0 +1,73 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (2.3.5) + activesupport (4.2.8) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + claide (1.0.1) + cocoapods (1.2.0) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.1, < 2.0) + cocoapods-core (= 1.2.0) + cocoapods-deintegrate (>= 1.0.1, < 2.0) + cocoapods-downloader (>= 1.1.3, < 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.1.2, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored (~> 1.2) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.5.5) + nap (~> 1.0) + ruby-macho (~> 0.2.5) + xcodeproj (>= 1.4.1, < 2.0) + cocoapods-core (1.2.0) + activesupport (>= 4.0.2, < 5) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.1) + cocoapods-downloader (1.1.3) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.1.2) + nap (>= 0.8, < 2.0) + netrc (= 0.7.8) + cocoapods-try (1.1.0) + colored (1.2) + escape (0.0.4) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.0.3) + i18n (0.8.1) + minitest (5.10.1) + molinillo (0.5.6) + nanaimo (0.2.3) + nap (1.1.0) + netrc (0.7.8) + ruby-macho (0.2.6) + thread_safe (0.3.6) + tzinfo (1.2.2) + thread_safe (~> 0.1) + xcodeproj (1.4.2) + CFPropertyList (~> 2.3.3) + activesupport (>= 3) + claide (>= 1.0.1, < 2.0) + colored (~> 1.2) + nanaimo (~> 0.2.3) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (= 1.2.0) + +BUNDLED WITH + 1.14.5 diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/LICENSE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/LICENSE new file mode 100644 index 0000000..82b84bf --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.podspec b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.podspec new file mode 100644 index 0000000..aee9872 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.podspec @@ -0,0 +1,49 @@ +Pod::Spec.new do |s| + s.name = "Nimble" + s.version = "7.0.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}" + + s.osx.exclude_files = [ + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPosix.swift", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h", + ] + s.ios.exclude_files = [ + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h", + ] + s.tvos.exclude_files = [ + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift", + "Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException.swift", + "Sources/Lib/CwlPreconditionTesting/CwlCatchExceptionSupport/CwlCatchException.m", + "Sources/Lib/CwlPreconditionTesting/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', + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"', + } +end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj new file mode 100644 index 0000000..c10b82a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.pbxproj @@ -0,0 +1,2293 @@ +// !$*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 */; }; + 1F12BE941E778F70006952EC /* CwlMachBadInstructionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE851E778F70006952EC /* CwlMachBadInstructionHandler.m */; }; + 1F12BE951E778F70006952EC /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F12BE871E778F70006952EC /* CwlMachBadInstructionHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F12BE981E778F70006952EC /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE8B1E778F70006952EC /* CwlBadInstructionException.swift */; }; + 1F12BE991E778F70006952EC /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE8C1E778F70006952EC /* CwlCatchBadInstruction.swift */; }; + 1F12BE9B1E778F70006952EC /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE8E1E778F70006952EC /* CwlDarwinDefinitions.swift */; }; + 1F12BE9D1E778F70006952EC /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F12BE911E778F70006952EC /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F12BE9F1E778F8F006952EC /* CwlMachBadInstructionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE851E778F70006952EC /* CwlMachBadInstructionHandler.m */; }; + 1F12BEA01E778F90006952EC /* CwlMachBadInstructionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE851E778F70006952EC /* CwlMachBadInstructionHandler.m */; }; + 1F12BEA11E778FA9006952EC /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F12BE871E778F70006952EC /* CwlMachBadInstructionHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F12BEA21E778FBA006952EC /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE881E778F70006952EC /* mach_excServer.c */; }; + 1F12BEA31E778FFA006952EC /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F12BE911E778F70006952EC /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F12BEA41E77900A006952EC /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE8B1E778F70006952EC /* CwlBadInstructionException.swift */; }; + 1F12BEA51E77900A006952EC /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE8C1E778F70006952EC /* CwlCatchBadInstruction.swift */; }; + 1F12BEA61E779012006952EC /* CwlCatchBadInstructionPOSIX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE8D1E778F70006952EC /* CwlCatchBadInstructionPOSIX.swift */; }; + 1F12BEA71E779018006952EC /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE8E1E778F70006952EC /* CwlDarwinDefinitions.swift */; }; + 1F12BEA81E77902A006952EC /* CwlPreconditionTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F12BE931E778F70006952EC /* CwlPreconditionTesting.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F12BEDC1E7791B9006952EC /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BED71E7791B9006952EC /* CwlCatchException.swift */; }; + 1F12BEDD1E7791B9006952EC /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BED71E7791B9006952EC /* CwlCatchException.swift */; }; + 1F12BEDF1E7791B9006952EC /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BED91E7791B9006952EC /* CwlCatchException.m */; }; + 1F12BEE01E7791B9006952EC /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BED91E7791B9006952EC /* CwlCatchException.m */; }; + 1F12BEE21E7791B9006952EC /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F12BEDB1E7791B9006952EC /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F12BEE31E7791B9006952EC /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F12BEDB1E7791B9006952EC /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F12BEE91E779784006952EC /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 1F12BE881E778F70006952EC /* mach_excServer.c */; }; + 1F12BEEA1E77ABE3006952EC /* CwlMachBadInstructionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F12BE871E778F70006952EC /* CwlMachBadInstructionHandler.h */; }; + 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 */; }; + 1F5DF1881BDCA0F500C3A531 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.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 */; }; + 1FD8CD5C1968AB07008ED995 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; }; + 1FD8CD5D1968AB07008ED995 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.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 /* ObjCHaveCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCount.m */; }; + 4793854E1BA0BB2500296F85 /* ObjCHaveCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCount.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 /* ObjCContainElementSatisfying.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfying.m */; }; + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfying.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfying.m */; }; + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfying.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfying.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 */; }; + 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 /* ObjCHaveCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCount.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 */; }; + 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 = ""; }; + 1F12BE851E778F70006952EC /* CwlMachBadInstructionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlMachBadInstructionHandler.m; sourceTree = ""; }; + 1F12BE871E778F70006952EC /* CwlMachBadInstructionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlMachBadInstructionHandler.h; sourceTree = ""; }; + 1F12BE881E778F70006952EC /* mach_excServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mach_excServer.c; sourceTree = ""; }; + 1F12BE891E778F70006952EC /* mach_excServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_excServer.h; sourceTree = ""; }; + 1F12BE8B1E778F70006952EC /* CwlBadInstructionException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlBadInstructionException.swift; sourceTree = ""; }; + 1F12BE8C1E778F70006952EC /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstruction.swift; sourceTree = ""; }; + 1F12BE8D1E778F70006952EC /* CwlCatchBadInstructionPOSIX.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchBadInstructionPOSIX.swift; sourceTree = ""; }; + 1F12BE8E1E778F70006952EC /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlDarwinDefinitions.swift; sourceTree = ""; }; + 1F12BE911E778F70006952EC /* CwlPreconditionTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting.h; sourceTree = ""; }; + 1F12BE931E778F70006952EC /* CwlPreconditionTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlPreconditionTesting.h; sourceTree = ""; }; + 1F12BED71E7791B9006952EC /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlCatchException.swift; sourceTree = ""; }; + 1F12BED91E7791B9006952EC /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CwlCatchException.m; sourceTree = ""; }; + 1F12BEDB1E7791B9006952EC /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CwlCatchException.h; 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 /* ObjCHaveCount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCHaveCount.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 /* ObjCContainElementSatisfying.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainElementSatisfying.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 = ""; }; + 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 = ""; }; + 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 */ + 1F12BE841E778F70006952EC /* CwlMachBadInstructionHandler */ = { + isa = PBXGroup; + children = ( + 1F12BE851E778F70006952EC /* CwlMachBadInstructionHandler.m */, + 1F12BE861E778F70006952EC /* include */, + 1F12BE881E778F70006952EC /* mach_excServer.c */, + 1F12BE891E778F70006952EC /* mach_excServer.h */, + ); + path = CwlMachBadInstructionHandler; + sourceTree = ""; + }; + 1F12BE861E778F70006952EC /* include */ = { + isa = PBXGroup; + children = ( + 1F12BE871E778F70006952EC /* CwlMachBadInstructionHandler.h */, + ); + path = include; + sourceTree = ""; + }; + 1F12BE8A1E778F70006952EC /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + 1F12BE8B1E778F70006952EC /* CwlBadInstructionException.swift */, + 1F12BE8C1E778F70006952EC /* CwlCatchBadInstruction.swift */, + 1F12BE8D1E778F70006952EC /* CwlCatchBadInstructionPOSIX.swift */, + 1F12BE8E1E778F70006952EC /* CwlDarwinDefinitions.swift */, + 1F12BE901E778F70006952EC /* Mach */, + 1F12BE921E778F70006952EC /* Posix */, + ); + path = CwlPreconditionTesting; + sourceTree = ""; + }; + 1F12BE901E778F70006952EC /* Mach */ = { + isa = PBXGroup; + children = ( + 1F12BE911E778F70006952EC /* CwlPreconditionTesting.h */, + ); + path = Mach; + sourceTree = ""; + }; + 1F12BE921E778F70006952EC /* Posix */ = { + isa = PBXGroup; + children = ( + 1F12BE931E778F70006952EC /* CwlPreconditionTesting.h */, + ); + path = Posix; + sourceTree = ""; + }; + 1F12BED61E7791B9006952EC /* CwlCatchException */ = { + isa = PBXGroup; + children = ( + 1F12BED71E7791B9006952EC /* CwlCatchException.swift */, + ); + path = CwlCatchException; + sourceTree = ""; + }; + 1F12BED81E7791B9006952EC /* CwlCatchExceptionSupport */ = { + isa = PBXGroup; + children = ( + 1F12BED91E7791B9006952EC /* CwlCatchException.m */, + 1F12BEDA1E7791B9006952EC /* include */, + ); + path = CwlCatchExceptionSupport; + sourceTree = ""; + }; + 1F12BEDA1E7791B9006952EC /* include */ = { + isa = PBXGroup; + children = ( + 1F12BEDB1E7791B9006952EC /* CwlCatchException.h */, + ); + path = include; + sourceTree = ""; + }; + 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 */, + 9630C0081C6D0AB3000693EE /* Lib */, + 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 */, + 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 */, + 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 /* ObjCContainElementSatisfying.m */, + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */, + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */, + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */, + 4793854C1BA0BB2500296F85 /* ObjCHaveCount.m */, + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */, + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */, + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */, + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */, + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */, + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */, + ); + path = objc; + sourceTree = ""; + }; + 9630C0081C6D0AB3000693EE /* Lib */ = { + isa = PBXGroup; + children = ( + 9630C0091C6D0ABA000693EE /* CwlPreconditionTesting */, + ); + name = Lib; + path = Sources/Lib; + sourceTree = ""; + }; + 9630C0091C6D0ABA000693EE /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + 1F12BED61E7791B9006952EC /* CwlCatchException */, + 1F12BED81E7791B9006952EC /* CwlCatchExceptionSupport */, + 1F12BE841E778F70006952EC /* CwlMachBadInstructionHandler */, + 1F12BE8A1E778F70006952EC /* CwlPreconditionTesting */, + ); + path = CwlPreconditionTesting; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1F1A74261940169200FFFC47 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F12BEA31E778FFA006952EC /* CwlPreconditionTesting.h in Headers */, + 1F12BEA11E778FA9006952EC /* CwlMachBadInstructionHandler.h in Headers */, + 1F1871C91CA89EDB00A34BF2 /* NMBStringify.h in Headers */, + 1F1871C51CA89EDB00A34BF2 /* DSL.h in Headers */, + 1F1871C71CA89EDB00A34BF2 /* NMBExceptionCapture.h in Headers */, + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */, + 1F12BEE31E7791B9006952EC /* CwlCatchException.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1521BDCA0CE00C3A531 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F1871E21CA89EF600A34BF2 /* NMBStringify.h in Headers */, + 1F1871E01CA89EF600A34BF2 /* DSL.h in Headers */, + 1F1871E11CA89EF600A34BF2 /* NMBExceptionCapture.h in Headers */, + 1F12BEA81E77902A006952EC /* CwlPreconditionTesting.h in Headers */, + 1F12BEEA1E77ABE3006952EC /* CwlMachBadInstructionHandler.h in Headers */, + 1F4999A61DBF2DD100BF8877 /* Nimble.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EAA195C0D6300ED456B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F12BE951E778F70006952EC /* CwlMachBadInstructionHandler.h in Headers */, + 1F1871DF1CA89EF500A34BF2 /* NMBStringify.h in Headers */, + 1F12BE9D1E778F70006952EC /* CwlPreconditionTesting.h in Headers */, + 1F1871DD1CA89EF500A34BF2 /* DSL.h in Headers */, + 1F1871DE1CA89EF500A34BF2 /* NMBExceptionCapture.h in Headers */, + 1F925EC7195C0DD100ED456B /* Nimble.h in Headers */, + 1F12BEE21E7791B9006952EC /* CwlCatchException.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 = 0820; + ORGANIZATIONNAME = "Jeff Hui"; + TargetAttributes = { + 1F1A74281940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + }; + 1F1A74331940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + TestTargetID = 1F1A74281940169200FFFC47; + }; + 1F5DF1541BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 1F5DF15D1BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 1F925EAC195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + }; + 1F925EB6195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + 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 = ( + 1FD8CD401968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F12BEA51E77900A006952EC /* CwlCatchBadInstruction.swift in Sources */, + 1F1871C81CA89EDB00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD361968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD321968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728F1A1B344000EB80F8 /* Stringers.swift in Sources */, + 1F12BEA41E77900A006952EC /* CwlBadInstructionException.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 */, + 1F12BE9F1E778F8F006952EC /* CwlMachBadInstructionHandler.m 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 */, + 1F12BEA21E778FBA006952EC /* mach_excServer.c in Sources */, + 1F1871C61CA89EDB00A34BF2 /* DSL.m in Sources */, + 1FD8CD301968AB07008ED995 /* AdapterProtocols.swift in Sources */, + 1F12BEA71E779018006952EC /* CwlDarwinDefinitions.swift in Sources */, + 1F12BEE01E7791B9006952EC /* CwlCatchException.m in Sources */, + AE7ADE451C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */, + 1FD8CD561968AB07008ED995 /* Contain.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 */, + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */, + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD5C1968AB07008ED995 /* MatcherProtocols.swift in Sources */, + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */, + 1F12BEDD1E7791B9006952EC /* CwlCatchException.swift in Sources */, + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */, + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift 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 */, + 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 */, + 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 */, + 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 /* ObjCContainElementSatisfying.m in Sources */, + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m 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 /* ObjCHaveCount.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 */, + 1F5DF1881BDCA0F500C3A531 /* MatcherProtocols.swift in Sources */, + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */, + 7A6AB2C61E7F628A00A2F694 /* ToSucceed.swift in Sources */, + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.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 */, + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */, + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */, + 1F12BEA01E778F90006952EC /* CwlMachBadInstructionHandler.m 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 */, + 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 */, + 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 */, + 1F12BEA61E779012006952EC /* CwlCatchBadInstructionPOSIX.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 /* ObjCHaveCount.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 */, + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */, + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */, + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfying.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 */, + 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 */, + 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 = ( + 1FD8CD411968AB07008ED995 /* BeCloseTo.swift in Sources */, + 1F12BE991E778F70006952EC /* CwlCatchBadInstruction.swift in Sources */, + 1F1871D31CA89EEE00A34BF2 /* NMBExceptionCapture.m in Sources */, + 1FD8CD371968AB07008ED995 /* Expectation.swift in Sources */, + 1FD8CD331968AB07008ED995 /* NimbleXCTestHandler.swift in Sources */, + 1F43728E1A1B343F00EB80F8 /* Stringers.swift in Sources */, + 1F12BE981E778F70006952EC /* CwlBadInstructionException.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 */, + 1F12BEDF1E7791B9006952EC /* CwlCatchException.m 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 */, + 1F12BE941E778F70006952EC /* CwlMachBadInstructionHandler.m 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 */, + 1F12BEE91E779784006952EC /* mach_excServer.c 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 */, + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */, + 7A0A26231E7F52360092A34E /* ToSucceed.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 */, + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */, + 1F12BEDC1E7791B9006952EC /* CwlCatchException.swift in Sources */, + 1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */, + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD5D1968AB07008ED995 /* MatcherProtocols.swift in Sources */, + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */, + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + 1F12BE9B1E778F70006952EC /* CwlDarwinDefinitions.swift in Sources */, + 1FD8CD391968AB07008ED995 /* Expression.swift 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 */, + 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 */, + 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 */, + 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 /* ObjCContainElementSatisfying.m in Sources */, + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m 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 /* ObjCHaveCount.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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + 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; + OTHER_SWIFT_FLAGS = "$(inherited) -swift-version 3"; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + 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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + 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; + OTHER_SWIFT_FLAGS = "$(inherited) -swift-version 3"; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a822b74 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme new file mode 100644 index 0000000..ef8ccf6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme new file mode 100644 index 0000000..9ff8f0d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme new file mode 100644 index 0000000..9f5340b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Package.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Package.swift new file mode 100644 index 0000000..2ef4037 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Package.swift @@ -0,0 +1,12 @@ +// swift-tools-version:3.0 + +import PackageDescription + +let package = Package( + name: "Nimble", + exclude: [ + "Sources/Lib", + "Sources/NimbleObjectiveC", + "Tests/NimbleTests/objc", + ] +) diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/README.md new file mode 100644 index 0000000..2be02f4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/README.md @@ -0,0 +1,1760 @@ +# 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 + // do some stuff that takes a while... + NSThread.sleepForTimeInterval(0.5) + done() +} +``` + +```objc +// Objective-C + +waitUntil(^(void (^done)(void)){ + // do some stuff that takes a while... + [NSThread sleepForTimeInterval:0.5]; + done(); +}); +``` + +`waitUntil` also optionally takes a timeout parameter: + +```swift +// Swift + +waitUntil(timeout: 10) { done in + // do some stuff that takes a while... + NSThread.sleepForTimeInterval(1) + done() +} +``` + +```objc +// Objective-C + +waitUntilTimeout(10, ^(void (^done)(void)){ + // do some stuff that takes a while... + [NSThread sleepForTimeInterval:1]; + 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 .succeed is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed("wrong enum case") + } + + return .succeeded +}).to(succeed()) + +// passes if .failed is returned from the closure +expect({ + guard case .enumCaseWithAssociatedValueThatIDontCareAbout = actual else { + return .failed("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, /* actual: */ 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException.swift new file mode 100644 index 0000000..196ee9a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException.swift @@ -0,0 +1,37 @@ +// +// 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(_ instance: T, block: () -> Void) -> T? { + // Get the type from an *instance*, instead of a receiving the type directly + return catchExceptionOfKind(T.self, block) as? T +} + +extension NSException { + public static func catchException(in block: () -> Void) -> Self? { + // Use a dummy instance of Self to provide the type + return catchReturnTypeConverter(self.init(), block: block) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchExceptionSupport/CwlCatchException.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchExceptionSupport/CwlCatchException.m new file mode 100644 index 0000000..738d43c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/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)()) { + @try { + inBlock(); + } @catch (NSException *exception) { + if ([exception isKindOfClass:type]) { + return exception; + } else { + @throw; + } + } + return nil; +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchExceptionSupport/include/CwlCatchException.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchExceptionSupport/include/CwlCatchException.h new file mode 100644 index 0000000..cc4c4fb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/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)()); diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/CwlMachBadInstructionHandler.m new file mode 100644 index 0000000..8183196 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h new file mode 100644 index 0000000..5755bfc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/include/CwlMachBadInstructionHandler.h @@ -0,0 +1,70 @@ +// +// CwlMachBadExceptionHandler.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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/mach_excServer.c b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/mach_excServer.c new file mode 100644 index 0000000..733c564 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/mach_excServer.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlMachBadInstructionHandler/mach_excServer.h new file mode 100644 index 0000000..52e53ae --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift new file mode 100644 index 0000000..91e5d4d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift new file mode 100644 index 0000000..6e84115 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift @@ -0,0 +1,199 @@ +// +// 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 CwlCatchException + 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 execTypesCountTuple { + mutating func pointer(in block: (UnsafeMutablePointer) -> R) -> R { + return withUnsafeMutablePointer(to: &self) { p -> R in + return p.withMemoryRebound(to: T.self, capacity: EXC_TYPES_COUNT) { ptr -> R in + return block(ptr) + } + } + } + } + + 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 + + mutating func withUnsafeMutablePointers(in block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> R) -> R { + return masks.pointer { masksPtr in + return ports.pointer { portsPtr in + return behaviors.pointer { behaviorsPtr in + return flavors.pointer { flavorsPtr in + return block(masksPtr, portsPtr, behaviorsPtr, flavorsPtr) + } + } + } + } + } + } + + /// 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) + try kernCheck { request.withMsgHeaderPointer { requestPtr in + mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, request.Head.msgh_size, 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 subsequent errors (let the program crash) + reply.RetCode = KERN_FAILURE + } + + // Send the reply + try kernCheck { reply.withMsgHeaderPointer { replyPtr in + mach_msg(replyPtr, MACH_SEND_MSG, reply.Head.msgh_size, 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) + } + + try kernCheck { context.withUnsafeMutablePointers { masksPtr, 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, context.currentExceptionPort, Int32(bitPattern: UInt32(EXCEPTION_STATE) | MACH_EXCEPTION_CODES), x86_THREAD_STATE64, masksPtr, &context.count, portsPtr, behaviorsPtr, flavorsPtr) + } } + + defer { context.withUnsafeMutablePointers { masksPtr, 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, &context.count, 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift new file mode 100644 index 0000000..eb9bc19 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift new file mode 100644 index 0000000..8d99d5e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Mach/CwlPreconditionTesting.h new file mode 100644 index 0000000..f9dbedd --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Posix/CwlPreconditionTesting.h new file mode 100644 index 0000000..710afae --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Posix/CwlPreconditionTesting.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 CwlPreconditionTestingVersionNumber; + +//! Project version string for CwlUtils. +FOUNDATION_EXPORT const unsigned char CwlAssertingTestingVersionString[]; diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/README.md new file mode 100644 index 0000000..a1a9a70 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Lib/CwlPreconditionTesting/README.md @@ -0,0 +1,80 @@ +# 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. + +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) + +## Usage + +The short version is: + +1. `git clone https://github.com/mattgallagher/CwlPreconditionTesting.git` +2. drag the "CwlPreconditionTesting.xcodeproj" file into your project's file tree in Xcode +3. go to your testing target's Build Phase settings and under "Target Dependencies" press the "+" button and select the relevant "CwlPreconditionTesting" target ("_iOS" or "_OSX", depending on your testing target's SDK) +4. write `import CwlPreconditionTesting` at the top of any test file where you want to use `catchBadInstruction` (Swift should handle the linkage automatically when you do this) +5. use the `catchBadInstruction` function as shown in the [CwlCatchBadInstructionTests.swift tests file](https://github.com/mattgallagher/CwlPreconditionTesting/blob/master/CwlPreconditionTestingTests/CwlCatchBadInstructionTests.swift?ts=4) + +### Project details + +The "CwlPreconditionTesting.xcodeproj" contains two targets: + +* CwlPreconditionTesting_OSX +* CwlPreconditionTesting_iOS + +both build a framework named "CwlPreconditionTesting.framework". If you're linking manually, be certain to select the "CwlPreconditionTesting.framework" from the appropriate target. + +Remember: the iOS build is useful only in the simulator. All Mach exception handling code will be conditionally excluded in any device build. + +### Static inclusion + +Due to the complications associated with needing to call into and out of Objective-C, static inclusion in other projects is not a single file nor a quick drag and drop. There's at least 7 files and you'll need to add some project settings. + +All of the following files: + +* CwlCatchBadInstruction.swift +* CwlCatchBadInstruction.h +* CwlCatchBadInstruction.m +* CwlCatchException.swift +* CwlCatchException.h +* CwlCatchException.m + +and either: + +* $(SDKROOT)/usr/include/mach/mach_exc.defs +* mach_excServer.c + +need to be added to the testing target for OS X projects or iOS projects, respectively. + +Your target will also need to have the following macros defined in the "Apple LLVM - Preprocessing" → "Preprocessor Macros" build setting: + + PRODUCT_NAME=$(PRODUCT_NAME) + +This lets the Objective-C file generate the include directive for the autogenerated Swift header so it can call back into Swift during the Mach exception handler callbacks. This macro should stay in sync if you change the target name but if you do anything else in your project that changes the name of the autogenerated Swift header independent of the target name (or you want to add spaces or other command-line complications to the target name), you'll want to update "CwlCatchBadInstruction.m" directly with the correct include directive. + +Additionally, you'll need a standard Objective-C "Bridging header" for your testing target and it will need to include the following import statements: + +``` +#if defined(__x86_64__) +#import +#endif + +#import +``` + +### 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift new file mode 100644 index 0000000..2e58fdf --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift new file mode 100644 index 0000000..94a9030 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift new file mode 100644 index 0000000..740c392 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift new file mode 100644 index 0000000..93f97d2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift @@ -0,0 +1,183 @@ +import Foundation + +#if _runtime(_ObjC) + +fileprivate 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 + + 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? + } + } + + public var withTimeout: (TimeInterval) -> NMBExpectation { + return ({ timeout in self._timeout = timeout + return self + }) + } + + 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)) + } + }) + } + + 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) + } + }) + } + + 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)) + } + }) + } + + 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) + } + }) + } + + public var notTo: (NMBMatcher) -> Void { return toNot } + + public var notToWithDescription: (NMBMatcher, String) -> Void { return toNotWithDescription } + + 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 + ) + } + }) + } + + 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 + ) + } + }) + } + + 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 + ) + } + }) + } + + 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 + ) + } + }) + } + + public var toNotEventually: (NMBMatcher) -> Void { return toEventuallyNot } + + public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void { return toEventuallyNotWithDescription } + + public class func failWithMessage(_ message: String, file: FileString, line: UInt) { + fail(message, location: SourceLocation(file: file, line: line)) + } +} + +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift new file mode 100644 index 0000000..19a4567 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift @@ -0,0 +1,81 @@ +import Foundation + +#if _runtime(_ObjC) + +public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) -> Bool +public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) -> Bool + +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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift new file mode 100644 index 0000000..e1b5432 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift new file mode 100644 index 0000000..78e6dd9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift @@ -0,0 +1,76 @@ +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 _runtime(_ObjC) + // 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 { + testCase.recordFailure(withDescription: message, inFile: location.file, atLine: location.line, expected: true) + } else { + let msg = "Attempted to report a test failure to XCTest while no test case was running. " + + "The failure was:\n\"\(message)\"\nIt occurred at: \(location.file):\(location.line)" + NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise() + } +#endif +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift new file mode 100644 index 0000000..dd02aa4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift @@ -0,0 +1,31 @@ +import Foundation + +#if !_runtime(_ObjC) +// 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift new file mode 100644 index 0000000..fdf4508 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/DSL+Wait.swift @@ -0,0 +1,98 @@ +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 { + 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) + } + } + + // 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 + 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 SWIFT_PACKAGE + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) { + until(timeout: 1, file: file, line: line, action: action) + } + #else + @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) + } + #endif +} + +internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> String { + 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 = 1, 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/DSL.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/DSL.swift new file mode 100644 index 0000000..7ebd684 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift new file mode 100644 index 0000000..5f8ebe1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Expectation.swift @@ -0,0 +1,131 @@ +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 { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift new file mode 100644 index 0000000..0d3d6af --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/ExpectationMessage.swift @@ -0,0 +1,261 @@ +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) + 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 _runtime(_ObjC) + +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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift new file mode 100644 index 0000000..f7afffe --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Expression.swift @@ -0,0 +1,90 @@ +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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/FailureMessage.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/FailureMessage.swift new file mode 100644 index 0000000..2bc57eb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Info.plist new file mode 100644 index 0000000..6ac80b8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift new file mode 100644 index 0000000..0250add --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AllPass.swift @@ -0,0 +1,120 @@ +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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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( + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift new file mode 100644 index 0000000..d2196f8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift @@ -0,0 +1,226 @@ +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 +} + +fileprivate 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: + 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(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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift new file mode 100644 index 0000000..4ae4d11 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + +/// 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 { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift new file mode 100644 index 0000000..24fd5fa --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift new file mode 100644 index 0000000..2b0ccd6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift @@ -0,0 +1,126 @@ +import Foundation + +internal 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 _runtime(_ObjC) +public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher { + var _expected: NSNumber + var _delta: CDouble + init(expected: NSNumber, within: CDouble) { + _expected = expected + _delta = within + } + + 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) + } + + 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) + } + + public var within: (CDouble) -> NMBObjCBeCloseToMatcher { + return ({ delta in + return NMBObjCBeCloseToMatcher(expected: self._expected, within: delta) + }) + } +} + +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift new file mode 100644 index 0000000..4a4dd82 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeEmpty.swift @@ -0,0 +1,92 @@ +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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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 { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift new file mode 100644 index 0000000..98c6f2e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift @@ -0,0 +1,41 @@ +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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift new file mode 100644 index 0000000..8f370d4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift new file mode 100644 index 0000000..250bed7 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThan.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThan.swift new file mode 100644 index 0000000..66c01d3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift new file mode 100644 index 0000000..28b36c1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLogical.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeLogical.swift new file mode 100644 index 0000000..4086da9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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) + } + } + + 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) + } + } + + 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) + } + } + + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeNil.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeNil.swift new file mode 100644 index 0000000..de79938 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beNilMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + return try! beNil().matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeVoid.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeVoid.swift new file mode 100644 index 0000000..f5bf22a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeginWith.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/BeginWith.swift new file mode 100644 index 0000000..e6cc9d8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift new file mode 100644 index 0000000..d2f8cd2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Contain.swift @@ -0,0 +1,94 @@ +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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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 { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift new file mode 100644 index 0000000..e71c97e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift @@ -0,0 +1,59 @@ +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 _runtime(_ObjC) + extension NMBObjCMatcher { + 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 { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/EndWith.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/EndWith.swift new file mode 100644 index 0000000..ebb87e0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Equal.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Equal.swift new file mode 100644 index 0000000..d9f68fa --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift new file mode 100644 index 0000000..379616d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/HaveCount.swift @@ -0,0 +1,57 @@ +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() { + 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() { + 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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Match.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Match.swift new file mode 100644 index 0000000..165600f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift new file mode 100644 index 0000000..2fdfb25 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatchError.swift @@ -0,0 +1,53 @@ +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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift new file mode 100644 index 0000000..abcafa9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift new file mode 100644 index 0000000..3528e3f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift @@ -0,0 +1,170 @@ +import Foundation +// `CGFloat` is in Foundation (swift-corelibs-foundation) on Linux. +#if _runtime(_ObjC) + import CoreGraphics +#endif + +/// Implement this protocol to implement a custom matcher for Swift +@available(*, deprecated, message: "Use to 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 _runtime(_ObjC) +/// 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 + +#if _runtime(_ObjC) +/// Protocol for types that support contain() matcher. +@objc public protocol NMBContainer { + @objc(containsObject:) + func contains(_ anObject: Any) -> Bool +} + +// 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 +#else +public protocol NMBContainer { + func contains(_ anObject: Any) -> Bool +} +#endif + +extension NSArray : NMBContainer {} +extension NSSet : NMBContainer {} + +#if _runtime(_ObjC) +/// Protocol for types that support only beEmpty(), haveCount() matchers +@objc public protocol NMBCollection { + var count: Int { get } +} + +extension NSHashTable : NMBCollection {} // Corelibs Foundation does not include these classes yet +extension NSMapTable : NMBCollection {} +#else +public protocol NMBCollection { + var count: Int { get } +} +#endif + +extension NSSet : NMBCollection {} +extension NSIndexSet : NMBCollection {} +extension NSDictionary : NMBCollection {} + +#if _runtime(_ObjC) +/// Protocol for types that support beginWith(), endWith(), beEmpty() matchers +@objc public protocol NMBOrderedCollection: NMBCollection { + @objc(objectAtIndex:) + func object(at index: Int) -> Any +} +#else +public protocol NMBOrderedCollection: NMBCollection { + func object(at index: Int) -> Any +} +#endif + +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 _runtime(_ObjC) +@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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift new file mode 100644 index 0000000..dcd7676 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/PostNotification.swift @@ -0,0 +1,70 @@ +import Foundation + +internal class NotificationCollector { + private(set) var observedNotifications: [Notification] + private let notificationCenter: NotificationCenter + #if _runtime(_ObjC) + private var token: AnyObject? + #else + private var token: NSObjectProtocol? + #endif + + required init(notificationCenter: NotificationCenter) { + self.notificationCenter = notificationCenter + self.observedNotifications = [] + } + + func startObserving() { + self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil) { [weak self] n in + // linux-swift gets confused by .append(n) + self?.observedNotifications.append(n) + } + } + + deinit { + #if _runtime(_ObjC) + 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() + +let notificationCenterDefault = NotificationCenter.default + +public func postNotifications( + _ notificationsMatcher: T, + fromNotificationCenter center: NotificationCenter = notificationCenterDefault) + -> 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/Predicate.swift new file mode 100644 index 0000000..8080f6c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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)) + } + } +} + +// Question: Should this be exposed? It's safer to not for now and decide later. +internal 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. + var status: PredicateStatus + /// The error message that can be displayed if it does not match + 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 + internal 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 _runtime(_ObjC) +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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift new file mode 100644 index 0000000..a4599cb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/RaisesException.swift @@ -0,0 +1,183 @@ +import Foundation + +// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager +#if _runtime(_ObjC) && !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) + } +} + +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 { + 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 + } + + 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) + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + return !matches(actualBlock, failureMessage: failureMessage, location: location) + } + + public var named: (_ name: String) -> NMBObjCRaiseExceptionMatcher { + return ({ name in + return NMBObjCRaiseExceptionMatcher( + name: name, + reason: self._reason, + userInfo: self._userInfo, + block: self._block + ) + }) + } + + public var reason: (_ reason: String?) -> NMBObjCRaiseExceptionMatcher { + return ({ reason in + return NMBObjCRaiseExceptionMatcher( + name: self._name, + reason: reason, + userInfo: self._userInfo, + block: self._block + ) + }) + } + + public var userInfo: (_ userInfo: NSDictionary?) -> NMBObjCRaiseExceptionMatcher { + return ({ userInfo in + return NMBObjCRaiseExceptionMatcher( + name: self._name, + reason: self._reason, + userInfo: userInfo, + block: self._block + ) + }) + } + + 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 { + public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher { + return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil, block: nil) + } +} +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift new file mode 100644 index 0000000..9d19b10 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift @@ -0,0 +1,107 @@ +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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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 { + return predicate.satisfies({ try! expression.evaluate() }, location: actualExpression.location).toSwift() + } else { + let failureMessage = FailureMessage() + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift new file mode 100644 index 0000000..cad53f4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift @@ -0,0 +1,55 @@ +import Foundation + +public func throwAssertion() -> Predicate { + return Predicate.fromDeprecatedClosure { actualExpression, failureMessage in + #if arch(x86_64) && _runtime(_ObjC) && !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 _runtime(_ObjC) conditional statement") + #endif + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift new file mode 100644 index 0000000..923f52e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ThrowError.swift @@ -0,0 +1,240 @@ +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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ToSucceed.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Matchers/ToSucceed.swift new file mode 100644 index 0000000..01369bb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h new file mode 100644 index 0000000..bd45c5d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Nimble.h @@ -0,0 +1,9 @@ +#import +#import "NMBExceptionCapture.h" +#import "NMBStringify.h" +#import "DSL.h" + +#import "CwlPreconditionTesting.h" + +FOUNDATION_EXPORT double NimbleVersionNumber; +FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Async.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Async.swift new file mode 100644 index 0000000..776b861 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Async.swift @@ -0,0 +1,360 @@ +import CoreFoundation +import Dispatch +import Foundation + +#if !_runtime(_ObjC) + 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 _runtime(_ObjC) + 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) + } + + /// 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. + trigger.timeoutSource.scheduleOneshot( + deadline: DispatchTime.now() + timeoutInterval, + leeway: timeoutLeeway) + 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 _runtime(_ObjC) + 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.suspend() + 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))) + asyncSource.scheduleRepeating(deadline: .now(), interval: interval, leeway: pollLeeway) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Errors.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Errors.swift new file mode 100644 index 0000000..074cb20 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Functional.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Functional.swift new file mode 100644 index 0000000..6c5126a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/SourceLocation.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/SourceLocation.swift new file mode 100644 index 0000000..4e37aef --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Stringers.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/Nimble/Utils/Stringers.swift new file mode 100644 index 0000000..8a15c4c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/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 _runtime(_ObjC) +@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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h new file mode 100644 index 0000000..5d416e4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h @@ -0,0 +1,9 @@ +#import +#import + +SWIFT_CLASS("_TtC6Nimble22CurrentTestCaseTracker") +@interface CurrentTestCaseTracker : NSObject ++ (CurrentTestCaseTracker *)sharedInstance; +@end + +@interface CurrentTestCaseTracker (Register) @end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h new file mode 100644 index 0000000..4538fb4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.h @@ -0,0 +1,383 @@ +#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)(), NSString *file, NSUInteger line) { \ + return NMB_expect(^id { return EXPR; }, file, line); \ + } + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + NMBExpectation *NMB_expect(id(^actualBlock)(), 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)(), 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 + +// 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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m new file mode 100644 index 0000000..31ff810 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/DSL.m @@ -0,0 +1,160 @@ +#import +#import + +SWIFT_CLASS("_TtC6Nimble7NMBWait") +@interface NMBWait : NSObject + ++ (void)untilTimeout:(NSTimeInterval)timeout file:(NSString *)file line:(NSUInteger)line action:(void(^)())action; ++ (void)untilFile:(NSString *)file line:(NSUInteger)line action:(void(^)())action; + +@end + + +NS_ASSUME_NONNULL_BEGIN + + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBExpectation *__nonnull NMB_expect(id __nullable(^actualBlock)(), NSString *__nonnull file, NSUInteger line) { + return [[NMBExpectation alloc] initWithActualBlock:actualBlock + negative:NO + file:file + line:line]; +} + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(), 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 NMBObjCRaiseExceptionMatcher *NMB_raiseException() { + return [NMBObjCMatcher raiseExceptionMatcher]; +} + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line) { + return ^(NSTimeInterval timeout, void (^action)(void (^)(void))) { + [NMBWait untilTimeout:timeout file:file line:line action:action]; + }; +} + +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line) { + return ^(void (^action)(void (^)(void))) { + [NMBWait untilFile:file line:line action:action]; + }; +} + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h new file mode 100644 index 0000000..d2a54d2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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)())finally; +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)())unsafeBlock NS_SWIFT_NAME(tryBlock(_:)); + +@end + +typedef void(^NMBSourceCallbackBlock)(BOOL successful); diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m new file mode 100644 index 0000000..0a882b7 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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)(); +@end + +@implementation NMBExceptionCapture + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)())finally { + self = [super init]; + if (self) { + self.handler = handler; + self.finally = finally; + } + return self; +} + +- (void)tryBlock:(void(^ _Nonnull)())unsafeBlock { + @try { + unsafeBlock(); + } + @catch (NSException *exception) { + if (self.handler) { + self.handler(exception); + } + } + @finally { + if (self.finally) { + self.finally(); + } + } +} + +@end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.h new file mode 100644 index 0000000..7938bca --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m new file mode 100644 index 0000000..329d39a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/NMBStringify.m @@ -0,0 +1,6 @@ +#import "NMBStringify.h" +#import + +NSString *_Nonnull NMBStringify(id _Nullable anyObject) { + return [NMBStringer stringify:anyObject]; +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m new file mode 100644 index 0000000..35f26fd --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/LinuxMain.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/LinuxMain.swift new file mode 100644 index 0000000..16c6953 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift new file mode 100644 index 0000000..47db724 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/AsynchronousTest.swift @@ -0,0 +1,220 @@ +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), + ("testWaitUntilPositiveMatches", testWaitUntilPositiveMatches), + ("testToEventuallyWithCustomDefaultTimeout", testToEventuallyWithCustomDefaultTimeout), + ("testWaitUntilTimesOutIfNotCalled", testWaitUntilTimesOutIfNotCalled), + ("testWaitUntilTimesOutWhenExceedingItsTime", testWaitUntilTimesOutWhenExceedingItsTime), + ("testWaitUntilNegativeMatches", testWaitUntilNegativeMatches), + ("testWaitUntilDetectsStalledMainThreadActivity", testWaitUntilDetectsStalledMainThreadActivity), + ("testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed", testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed), + ("testWaitUntilErrorsIfDoneIsCalledMultipleTimes", testWaitUntilErrorsIfDoneIsCalledMultipleTimes), + ("testWaitUntilMustBeInMainThread", testWaitUntilMustBeInMainThread), + ("testToEventuallyMustBeInMainThread", testToEventuallyMustBeInMainThread), + ] + } + + 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 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 + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift new file mode 100644 index 0000000..26e5a98 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift new file mode 100644 index 0000000..40d9760 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 where Self: XCTestCaseProviderStatic { + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift new file mode 100644 index 0000000..976b2fb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Helpers/utils.swift @@ -0,0 +1,98 @@ +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() + } +} + +public class NimbleHelper: NSObject { + 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) + } + + 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) + } + + 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) + } +} + +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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Info.plist new file mode 100644 index 0000000..6d32c15 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/LinuxSupport.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/LinuxSupport.swift new file mode 100644 index 0000000..03ff8e1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift new file mode 100644 index 0000000..2050881 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift new file mode 100644 index 0000000..ea16913 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift @@ -0,0 +1,89 @@ +import Foundation +import XCTest +import Nimble + +fileprivate class TestNull: NSNull {} +fileprivate protocol TestProtocol {} +fileprivate class TestClassConformingToProtocol: TestProtocol {} +fileprivate 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 _runtime(_ObjC) + +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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift new file mode 100644 index 0000000..2c362e5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift @@ -0,0 +1,79 @@ +import Foundation +import XCTest +import Nimble + +fileprivate protocol TestProtocol {} +fileprivate class TestClassConformingToProtocol: TestProtocol {} +fileprivate 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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift new file mode 100644 index 0000000..81530f3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift new file mode 100644 index 0000000..7c4abf3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift new file mode 100644 index 0000000..ea524ce --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift new file mode 100644 index 0000000..ea024a3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift new file mode 100644 index 0000000..923fa76 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift new file mode 100644 index 0000000..393810e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift new file mode 100644 index 0000000..61cfec1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift new file mode 100644 index 0000000..f1c3317 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift new file mode 100644 index 0000000..947a1b4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift new file mode 100644 index 0000000..69f4185 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift new file mode 100644 index 0000000..a8eefc1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift new file mode 100644 index 0000000..a05707c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift new file mode 100644 index 0000000..a9fe80e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift new file mode 100644 index 0000000..9b01de9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift new file mode 100644 index 0000000..3e19426 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift new file mode 100644 index 0000000..e54b535 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift new file mode 100644 index 0000000..a0294c3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift new file mode 100644 index 0000000..2d626f2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift new file mode 100644 index 0000000..a95ba56 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift new file mode 100644 index 0000000..33b2ff0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift new file mode 100644 index 0000000..20461d9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift @@ -0,0 +1,166 @@ +import XCTest +import Nimble + +#if _runtime(_ObjC) && !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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift new file mode 100644 index 0000000..0bd9495 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift new file mode 100644 index 0000000..9c66fe6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift @@ -0,0 +1,62 @@ +import Foundation +import XCTest +import Nimble + +#if _runtime(_ObjC) && !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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift new file mode 100644 index 0000000..f0e0f94 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/Matchers/ToSucceedTest.swift new file mode 100644 index 0000000..dde999a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/SynchronousTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/SynchronousTests.swift new file mode 100644 index 0000000..ce8181b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/UserDescriptionTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/UserDescriptionTest.swift new file mode 100644 index 0000000..9bb64b6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h new file mode 100644 index 0000000..282993d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m new file mode 100644 index 0000000..4bdc021 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m new file mode 100644 index 0000000..f052e74 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m new file mode 100644 index 0000000..f5fca2d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m new file mode 100644 index 0000000..c33d643 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m new file mode 100644 index 0000000..5e803cb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m new file mode 100644 index 0000000..5a5bce8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m new file mode 100644 index 0000000..f3f5c98 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m new file mode 100644 index 0000000..28862ba --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m new file mode 100644 index 0000000..5a57d54 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m new file mode 100644 index 0000000..a9d9d51 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m new file mode 100644 index 0000000..7eee261 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m new file mode 100644 index 0000000..4a738ec --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m new file mode 100644 index 0000000..9750641 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m new file mode 100644 index 0000000..a43ee50 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m new file mode 100644 index 0000000..c669475 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m new file mode 100644 index 0000000..1ad7913 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m new file mode 100644 index 0000000..5ca7be4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfying.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfying.m new file mode 100644 index 0000000..b15d6c3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfying.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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m new file mode 100644 index 0000000..8b954fe --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m new file mode 100644 index 0000000..b960f01 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m new file mode 100644 index 0000000..9d1361e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCount.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCount.m new file mode 100644 index 0000000..31053c8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCHaveCount.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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m new file mode 100644 index 0000000..2342ae4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m new file mode 100644 index 0000000..9b5a378 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m new file mode 100644 index 0000000..4c80abc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m new file mode 100644 index 0000000..2aae816 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m new file mode 100644 index 0000000..ffb5407 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m new file mode 100644 index 0000000..4ba2eae --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/script/release b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/script/release new file mode 100755 index 0000000..f61c0dc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Nimble/test b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Nimble/test new file mode 100755 index 0000000..0766351 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/.Package.test.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.Package.test.swift new file mode 100644 index 0000000..7058701 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.Package.test.swift @@ -0,0 +1,39 @@ +import PackageDescription + +let package = Package( + name: "Quick", + targets: { +#if _runtime(_ObjC) + 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 + }(), + // TODO: Once the `test` command has been implemented in the Swift Package Manager, this should be changed to + // be `testDependencies:` instead. For now it has to be done like this for the library to get linked with the test targets. + // See: https://github.com/apple/swift-evolution/blob/master/proposals/0019-package-manager-testing.md + dependencies: [ + .Package(url: "https://github.com/Quick/Nimble", majorVersion: 6) + ], + 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 !_runtime(_ObjC) + excludes.append("Sources/QuickSpecBase") +#endif + return excludes + }() +) diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.github/ISSUE_TEMPLATE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..ebe5a2b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/.github/PULL_REQUEST_TEMPLATE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..20e40c8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/.gitignore b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.gitignore new file mode 100644 index 0000000..33d3dc9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.gitignore @@ -0,0 +1,65 @@ +# 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. +Packages/ +.build/ + +# 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/ReactiveSwift/Carthage/Checkouts/Quick/.gitmodules b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.gitmodules new file mode 100644 index 0000000..cffbed0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/.hound.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.hound.yml new file mode 100644 index 0000000..b867fd9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.swift-version b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.swiftlint.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.swiftlint.yml new file mode 100644 index 0000000..7355ecc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.swiftlint.yml @@ -0,0 +1,9 @@ +disabled_rules: + - line_length + - type_name + - valid_docs + - function_body_length + - variable_name +included: + - Sources + - Tests diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.travis.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.travis.yml new file mode 100644 index 0000000..c22030e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/.travis.yml @@ -0,0 +1,34 @@ +osx_image: xcode8 +language: generic +matrix: + include: + - os: osx + 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 + sudo: required + env: + - PODSPEC=1 + - os: linux + sudo: required + dist: trusty +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 rvm system; sudo 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/ReactiveSwift/Carthage/Checkouts/Quick/CODE_OF_CONDUCT.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..f82f39a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/CONTRIBUTING.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/CONTRIBUTING.md new file mode 100644 index 0000000..e8e32c1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Dangerfile b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Dangerfile new file mode 100644 index 0000000..719de60 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/README.md new file mode 100644 index 0000000..08fb556 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/README.md @@ -0,0 +1,6 @@ +# Documentation + +- [English](en-us/README.md) +- [日本語](ja/README.md) +- [中文](zh-cn/README.md) +- [pt-br](pt-br/README.md) diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/ArrangeActAssert.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/ArrangeActAssert.md new file mode 100644 index 0000000..fc7915b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/BehavioralTesting.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/BehavioralTesting.md new file mode 100644 index 0000000..02ae0c0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/ConfiguringQuick.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/ConfiguringQuick.md new file mode 100644 index 0000000..919d4de --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/InstallingFileTemplates.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/InstallingFileTemplates.md new file mode 100644 index 0000000..3de82c5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/InstallingQuick.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/InstallingQuick.md new file mode 100644 index 0000000..258956f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/MoreResources.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/MoreResources.md new file mode 100644 index 0000000..65d7eba --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/NimbleAssertions.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/NimbleAssertions.md new file mode 100644 index 0000000..3b31ac3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/QuickExamplesAndGroups.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/QuickExamplesAndGroups.md new file mode 100644 index 0000000..e9f0550 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/QuickInObjectiveC.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/QuickInObjectiveC.md new file mode 100644 index 0000000..3fb6bdc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/README.md new file mode 100644 index 0000000..d03f633 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/SettingUpYourXcodeProject.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..76e9d3e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/SharedExamples.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/SharedExamples.md new file mode 100644 index 0000000..339bf34 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/TestUsingTestDoubles.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/TestUsingTestDoubles.md new file mode 100644 index 0000000..fc4f3f9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md new file mode 100644 index 0000000..4f5ce1d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/TestingApps.md @@ -0,0 +1,179 @@ +# 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")); + }); +}); +``` diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/Troubleshooting.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/en-us/Troubleshooting.md new file mode 100644 index 0000000..c39403c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/ArrangeActAssert.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/ArrangeActAssert.md new file mode 100644 index 0000000..2f0a138 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/BehavioralTesting.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/BehavioralTesting.md new file mode 100644 index 0000000..af78e50 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/ConfiguringQuick.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/ConfiguringQuick.md new file mode 100644 index 0000000..4226564 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/InstallingFileTemplates.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/InstallingFileTemplates.md new file mode 100644 index 0000000..1c87e52 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/InstallingQuick.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/InstallingQuick.md new file mode 100644 index 0000000..884b8a5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/MoreResources.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/MoreResources.md new file mode 100644 index 0000000..996f2df --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/NimbleAssertions.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/NimbleAssertions.md new file mode 100644 index 0000000..8534a71 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/QuickExamplesAndGroups.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/QuickExamplesAndGroups.md new file mode 100644 index 0000000..2ddad20 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/QuickInObjectiveC.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/QuickInObjectiveC.md new file mode 100644 index 0000000..6d67044 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/README.md new file mode 100644 index 0000000..0c4f0d5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/SettingUpYourXcodeProject.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..9258217 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/SharedExamples.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/SharedExamples.md new file mode 100644 index 0000000..a1670d2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/TestUsingTestDoubles.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/TestUsingTestDoubles.md new file mode 100644 index 0000000..7251e2e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/TestingApps.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/TestingApps.md new file mode 100644 index 0000000..db389ee --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/Troubleshooting.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/ja/Troubleshooting.md new file mode 100644 index 0000000..095dad3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/pt-br/BehavioralTesting.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/pt-br/BehavioralTesting.md new file mode 100644 index 0000000..4e41676 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/pt-br/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/pt-br/README.md new file mode 100644 index 0000000..c170942 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/pt-br/SharedExamples.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/pt-br/SharedExamples.md new file mode 100644 index 0000000..eabde35 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/ArrangeActAssert.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/ArrangeActAssert.md new file mode 100644 index 0000000..fda4f8a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/BehavioralTesting.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/BehavioralTesting.md new file mode 100644 index 0000000..70a0b51 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/ConfiguringQuick.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/ConfiguringQuick.md new file mode 100644 index 0000000..fc5ba90 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingFileTemplates.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingFileTemplates.md new file mode 100644 index 0000000..7e35365 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingQuick.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/InstallingQuick.md new file mode 100644 index 0000000..2f54b0a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/MoreResources.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/MoreResources.md new file mode 100644 index 0000000..0a9ed84 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/NimbleAssertions.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/NimbleAssertions.md new file mode 100644 index 0000000..b64919c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickExamplesAndGroups.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickExamplesAndGroups.md new file mode 100644 index 0000000..f17281d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickInObjectiveC.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/QuickInObjectiveC.md new file mode 100644 index 0000000..22318a0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/README.md new file mode 100644 index 0000000..2c48f4c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/SettingUpYourXcodeProject.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/SettingUpYourXcodeProject.md new file mode 100644 index 0000000..e902c6f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/SharedExamples.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/SharedExamples.md new file mode 100644 index 0000000..ec87138 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/TestUsingTestDoubles.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/TestUsingTestDoubles.md new file mode 100644 index 0000000..9e83ead --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/TestingApps.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/TestingApps.md new file mode 100644 index 0000000..59f68d8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/Troubleshooting.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Documentation/zh-cn/Troubleshooting.md new file mode 100644 index 0000000..c89e25e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.github/ISSUE_TEMPLATE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..85e591e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.github/PULL_REQUEST_TEMPLATE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.github/PULL_REQUEST_TEMPLATE new file mode 100644 index 0000000..20e40c8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore new file mode 100644 index 0000000..e50906d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.gitignore @@ -0,0 +1,21 @@ +.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/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml new file mode 100644 index 0000000..b867fd9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.hound.yml @@ -0,0 +1,2 @@ +swift: + config_file: .swiftlint.yml diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml new file mode 100644 index 0000000..d412589 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.swiftlint.yml @@ -0,0 +1,16 @@ +disabled_rules: + - line_length + - todo + - variable_name + - force_try + - function_parameter_count + - force_cast + - type_name + - large_tuple + +included: + - Sources + - Tests + +trailing_comma: + mandatory_comma: true diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml new file mode 100644 index 0000000..3e2f896 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/.travis.yml @@ -0,0 +1,25 @@ +osx_image: xcode8 +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=swiftpm + - os: linux + dist: trusty + sudo: required + env: TYPE=swiftpm + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/CONTRIBUTING.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/CONTRIBUTING.md new file mode 100644 index 0000000..d9c4ba6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile new file mode 100644 index 0000000..a6dc312 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile @@ -0,0 +1,4 @@ +# A sample Gemfile +source "https://rubygems.org" + +gem 'cocoapods', '1.1.0.rc.3' diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock new file mode 100644 index 0000000..87dc02b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Gemfile.lock @@ -0,0 +1,69 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (4.2.7.1) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + claide (1.0.1) + cocoapods (1.1.0.rc.3) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.1, < 2.0) + cocoapods-core (= 1.1.0.rc.3) + cocoapods-deintegrate (>= 1.0.1, < 2.0) + cocoapods-downloader (>= 1.1.1, < 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.1.0.beta.1) + cocoapods-try (>= 1.1.0, < 2.0) + colored (~> 1.2) + escape (~> 0.0.4) + fourflusher (~> 2.0) + gh_inspector (~> 1.0) + molinillo (~> 0.5.1) + nap (~> 1.0) + xcodeproj (>= 1.3.2, < 2.0) + cocoapods-core (1.1.0.rc.3) + activesupport (>= 4.0.2, < 5) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.1) + cocoapods-downloader (1.1.1) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.1.0.beta.1) + nap (>= 0.8, < 2.0) + netrc (= 0.7.8) + cocoapods-try (1.1.0) + colored (1.2) + escape (0.0.4) + fourflusher (2.0.1) + fuzzy_match (2.0.4) + gh_inspector (1.0.2) + i18n (0.7.0) + json (1.8.3) + minitest (5.9.1) + molinillo (0.5.1) + nap (1.1.0) + netrc (0.7.8) + thread_safe (0.3.5) + tzinfo (1.2.2) + thread_safe (~> 0.1) + xcodeproj (1.3.2) + activesupport (>= 3) + claide (>= 1.0.1, < 2.0) + colored (~> 1.2) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (= 1.1.0.rc.3) + +BUNDLED WITH + 1.13.1 diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/LICENSE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/LICENSE new file mode 100644 index 0000000..82b84bf --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec new file mode 100644 index 0000000..d9ad8a0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.podspec @@ -0,0 +1,47 @@ +Pod::Spec.new do |s| + s.name = "Nimble" + s.version = "6.0.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}" + + s.osx.exclude_files = [ + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift", + ] + s.ios.exclude_files = [ + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift", + ] + s.tvos.exclude_files = [ + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift", + "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.{h,c}", + "Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException.swift", + "Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException.m", + ] + + s.private_header_files = "Sources/NimbleObjectiveC/CurrentTestCaseTracker.h" + s.tvos.private_header_files = "Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.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', + 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"', + } +end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj new file mode 100644 index 0000000..54f1cce --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.pbxproj @@ -0,0 +1,2171 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* 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 */; }; + 1F2D175B1DB618ED00EE9C7A /* mach_excServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9630C0261C6D0BB0000693EE /* mach_excServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F2D175C1DB618F000EE9C7A /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 9630C0221C6D0B82000693EE /* mach_excServer.c */; }; + 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 */; }; + 1F4BB8A41DAC9DC90048464B /* CwlCatchBadInstructionPOSIX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F4BB89D1DAC9D930048464B /* CwlCatchBadInstructionPOSIX.swift */; }; + 1F4BB8AB1DAC9DE50048464B /* CwlCatchBadInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9630C00A1C6D0B18000693EE /* CwlCatchBadInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1F4BB8AE1DAC9DED0048464B /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = 9630C0161C6D0B2F000693EE /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 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 */; }; + 1F4BB8BA1DACBFCF0048464B /* CwlCatchBadInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = 9630C00B1C6D0B18000693EE /* CwlCatchBadInstruction.m */; }; + 1F4BB8BB1DACBFD00048464B /* CwlCatchBadInstruction.m in Sources */ = {isa = PBXBuildFile; fileRef = 9630C00B1C6D0B18000693EE /* CwlCatchBadInstruction.m */; }; + 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 */; }; + 1F5DF1881BDCA0F500C3A531 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.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 */; }; + 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 */; }; + 1FD8CD5C1968AB07008ED995 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.swift */; }; + 1FD8CD5D1968AB07008ED995 /* MatcherProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD8CD1D1968AB07008ED995 /* MatcherProtocols.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 */; }; + 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 /* ObjCHaveCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCount.m */; }; + 4793854E1BA0BB2500296F85 /* ObjCHaveCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCount.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 */; }; + 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 /* ObjCContainElementSatisfying.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfying.m */; }; + 7B13BA111DD361EB00C9098C /* ObjCContainElementSatisfying.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfying.m */; }; + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfying.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfying.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 */; }; + 9630C00D1C6D0B18000693EE /* CwlCatchBadInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9630C00A1C6D0B18000693EE /* CwlCatchBadInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9630C00E1C6D0B18000693EE /* CwlCatchBadInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9630C00A1C6D0B18000693EE /* CwlCatchBadInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9630C0131C6D0B18000693EE /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9630C00C1C6D0B18000693EE /* CwlCatchBadInstruction.swift */; }; + 9630C0141C6D0B18000693EE /* CwlCatchBadInstruction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9630C00C1C6D0B18000693EE /* CwlCatchBadInstruction.swift */; }; + 9630C0191C6D0B2F000693EE /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = 9630C0161C6D0B2F000693EE /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9630C01A1C6D0B2F000693EE /* CwlCatchException.h in Headers */ = {isa = PBXBuildFile; fileRef = 9630C0161C6D0B2F000693EE /* CwlCatchException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9630C01C1C6D0B2F000693EE /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = 9630C0171C6D0B2F000693EE /* CwlCatchException.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + 9630C01D1C6D0B2F000693EE /* CwlCatchException.m in Sources */ = {isa = PBXBuildFile; fileRef = 9630C0171C6D0B2F000693EE /* CwlCatchException.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; + 9630C01F1C6D0B2F000693EE /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9630C0181C6D0B2F000693EE /* CwlCatchException.swift */; }; + 9630C0201C6D0B2F000693EE /* CwlCatchException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9630C0181C6D0B2F000693EE /* CwlCatchException.swift */; }; + 9630C0231C6D0B82000693EE /* mach_excServer.c in Sources */ = {isa = PBXBuildFile; fileRef = 9630C0221C6D0B82000693EE /* mach_excServer.c */; }; + 9630C0271C6D0BB0000693EE /* mach_excServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9630C0261C6D0BB0000693EE /* mach_excServer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9630C02C1C6D125F000693EE /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9630C02B1C6D125F000693EE /* CwlBadInstructionException.swift */; }; + 9630C02D1C6D125F000693EE /* CwlBadInstructionException.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9630C02B1C6D125F000693EE /* CwlBadInstructionException.swift */; }; + 9630C0301C6D139F000693EE /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9630C02F1C6D139F000693EE /* CwlDarwinDefinitions.swift */; }; + 9630C0311C6D139F000693EE /* CwlDarwinDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9630C02F1C6D139F000693EE /* CwlDarwinDefinitions.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 */; }; + 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 /* ObjCHaveCount.m in Sources */ = {isa = PBXBuildFile; fileRef = 4793854C1BA0BB2500296F85 /* ObjCHaveCount.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 */; }; + 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 = ""; }; + 1F4BB89D1DAC9D930048464B /* CwlCatchBadInstructionPOSIX.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CwlCatchBadInstructionPOSIX.swift; path = CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift; 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 = ""; }; + 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 = ""; }; + 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 /* ObjCHaveCount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCHaveCount.m; sourceTree = ""; }; + 6CAEDD091CAEA86F003F1584 /* LinuxSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinuxSupport.swift; sourceTree = ""; }; + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainElementSatisfying.swift; sourceTree = ""; }; + 7B13BA071DD360C300C9098C /* ObjCContainElementSatisfying.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjCContainElementSatisfying.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 = ""; }; + 9630C00A1C6D0B18000693EE /* CwlCatchBadInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CwlCatchBadInstruction.h; path = CwlPreconditionTesting/CwlCatchBadInstruction.h; sourceTree = ""; }; + 9630C00B1C6D0B18000693EE /* CwlCatchBadInstruction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CwlCatchBadInstruction.m; path = CwlPreconditionTesting/CwlCatchBadInstruction.m; sourceTree = ""; }; + 9630C00C1C6D0B18000693EE /* CwlCatchBadInstruction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CwlCatchBadInstruction.swift; path = CwlPreconditionTesting/CwlCatchBadInstruction.swift; sourceTree = ""; }; + 9630C0161C6D0B2F000693EE /* CwlCatchException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CwlCatchException.h; path = CwlCatchException/CwlCatchException/CwlCatchException.h; sourceTree = ""; }; + 9630C0171C6D0B2F000693EE /* CwlCatchException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CwlCatchException.m; path = CwlCatchException/CwlCatchException/CwlCatchException.m; sourceTree = ""; }; + 9630C0181C6D0B2F000693EE /* CwlCatchException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CwlCatchException.swift; path = CwlCatchException/CwlCatchException/CwlCatchException.swift; sourceTree = ""; }; + 9630C0221C6D0B82000693EE /* mach_excServer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mach_excServer.c; path = CwlPreconditionTesting/mach_excServer.c; sourceTree = ""; }; + 9630C0261C6D0BB0000693EE /* mach_excServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mach_excServer.h; path = CwlPreconditionTesting/mach_excServer.h; sourceTree = ""; }; + 9630C02B1C6D125F000693EE /* CwlBadInstructionException.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CwlBadInstructionException.swift; path = CwlPreconditionTesting/CwlBadInstructionException.swift; sourceTree = ""; }; + 9630C02F1C6D139F000693EE /* CwlDarwinDefinitions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CwlDarwinDefinitions.swift; path = CwlPreconditionTesting/CwlDarwinDefinitions.swift; 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 = ""; }; + 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 = ""; }; + 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 */, + 9630C0081C6D0AB3000693EE /* Lib */, + 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 */, + 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 */, + 1FCF914E1C61C85A00B15DCB /* PostNotificationTest.swift */, + AE7ADE481C80C00D00B94CD3 /* MatchErrorTest.swift */, + 1F4BB8B31DACA0D00048464B /* ThrowAssertionTest.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 */, + 7B13BA051DD360AA00C9098C /* ContainElementSatisfying.swift */, + 1FD8CD1A1968AB07008ED995 /* Contain.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 */, + 1FD8CD1E1968AB07008ED995 /* RaisesException.swift */, + 964CFEFC1C4FF48900513336 /* ThrowAssertion.swift */, + 7B5358BD1C38479700A23FAA /* SatisfyAnyOf.swift */, + 29EA59651B551EE6002D767E /* ThrowError.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 /* ObjCContainElementSatisfying.m */, + 1F4A56931A3B346F009E1637 /* ObjCContainTest.m */, + 1F4A56961A3B34AA009E1637 /* ObjCEndWithTest.m */, + 1F4A56991A3B3539009E1637 /* ObjCEqualTest.m */, + 4793854C1BA0BB2500296F85 /* ObjCHaveCount.m */, + 1F4A569C1A3B3565009E1637 /* ObjCMatchTest.m */, + 1F4A569F1A3B359E009E1637 /* ObjCRaiseExceptionTest.m */, + 965B0D081B62B8ED0005AE66 /* ObjCUserDescriptionTest.m */, + DDEFAEB31A93CBE6005CA37A /* ObjCAllPassTest.m */, + 7B5358C11C39155600A23FAA /* ObjCSatisfyAnyOfTest.m */, + 8DF1C3F61C94FC75004B2D36 /* ObjcStringersTest.m */, + ); + path = objc; + sourceTree = ""; + }; + 9630C0081C6D0AB3000693EE /* Lib */ = { + isa = PBXGroup; + children = ( + 9630C0091C6D0ABA000693EE /* CwlPreconditionTesting */, + ); + name = Lib; + path = Sources/Lib; + sourceTree = ""; + }; + 9630C0091C6D0ABA000693EE /* CwlPreconditionTesting */ = { + isa = PBXGroup; + children = ( + 1F4BB89D1DAC9D930048464B /* CwlCatchBadInstructionPOSIX.swift */, + 9630C02B1C6D125F000693EE /* CwlBadInstructionException.swift */, + 9630C00C1C6D0B18000693EE /* CwlCatchBadInstruction.swift */, + 9630C00A1C6D0B18000693EE /* CwlCatchBadInstruction.h */, + 9630C00B1C6D0B18000693EE /* CwlCatchBadInstruction.m */, + 9630C0181C6D0B2F000693EE /* CwlCatchException.swift */, + 9630C0161C6D0B2F000693EE /* CwlCatchException.h */, + 9630C0171C6D0B2F000693EE /* CwlCatchException.m */, + 9630C02F1C6D139F000693EE /* CwlDarwinDefinitions.swift */, + 9630C0261C6D0BB0000693EE /* mach_excServer.h */, + 9630C0221C6D0B82000693EE /* mach_excServer.c */, + ); + path = CwlPreconditionTesting; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 1F1A74261940169200FFFC47 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 9630C00D1C6D0B18000693EE /* CwlCatchBadInstruction.h in Headers */, + 9630C0191C6D0B2F000693EE /* CwlCatchException.h in Headers */, + 1F1871C91CA89EDB00A34BF2 /* NMBStringify.h in Headers */, + 1F1871C51CA89EDB00A34BF2 /* DSL.h in Headers */, + 1F1871C71CA89EDB00A34BF2 /* NMBExceptionCapture.h in Headers */, + 1F1A742F1940169200FFFC47 /* Nimble.h in Headers */, + 9630C0271C6D0BB0000693EE /* mach_excServer.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F5DF1521BDCA0CE00C3A531 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F4BB8AE1DAC9DED0048464B /* CwlCatchException.h in Headers */, + 1F1871E21CA89EF600A34BF2 /* NMBStringify.h in Headers */, + 1F1871E01CA89EF600A34BF2 /* DSL.h in Headers */, + 1F1871E11CA89EF600A34BF2 /* NMBExceptionCapture.h in Headers */, + 1F4BB8AB1DAC9DE50048464B /* CwlCatchBadInstruction.h in Headers */, + 1F4999A61DBF2DD100BF8877 /* Nimble.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 1F925EAA195C0D6300ED456B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 9630C00E1C6D0B18000693EE /* CwlCatchBadInstruction.h in Headers */, + 9630C01A1C6D0B2F000693EE /* CwlCatchException.h in Headers */, + 1F2D175B1DB618ED00EE9C7A /* mach_excServer.h in Headers */, + 1F1871DF1CA89EF500A34BF2 /* NMBStringify.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 */, + 36D948361E0C6F4E0088F9E9 /* ShellScript */, + ); + 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 */, + 36D948371E0C6F590088F9E9 /* ShellScript */, + ); + 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 */, + 36D948351E0C6F420088F9E9 /* ShellScript */, + ); + 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 = 0800; + ORGANIZATIONNAME = "Jeff Hui"; + TargetAttributes = { + 1F1A74281940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + }; + 1F1A74331940169200FFFC47 = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + TestTargetID = 1F1A74281940169200FFFC47; + }; + 1F5DF1541BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 1F5DF15D1BDCA0CE00C3A531 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + }; + 1F925EAC195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + }; + 1F925EB6195C0D6300ED456B = { + CreatedOnToolsVersion = 6.0; + LastSwiftMigration = 0800; + TestTargetID = 1F925EAC195C0D6300ED456B; + }; + }; + }; + 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 */, + ); + }; +/* 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 */ + 36D948351E0C6F420088F9E9 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nfi"; + }; + 36D948361E0C6F4E0088F9E9 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nfi"; + }; + 36D948371E0C6F590088F9E9 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nfi"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1F1A74241940169200FFFC47 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 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 */, + 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 */, + 1F4BB8BA1DACBFCF0048464B /* CwlCatchBadInstruction.m in Sources */, + 1FC494AA1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1FD8CD5E1968AB07008ED995 /* RaisesException.swift in Sources */, + 1FD8CD561968AB07008ED995 /* Contain.swift in Sources */, + 1FD8CD481968AB07008ED995 /* BeGreaterThanOrEqualTo.swift in Sources */, + 1FD8CD441968AB07008ED995 /* BeginWith.swift in Sources */, + 1FD8CD4A1968AB07008ED995 /* BeIdenticalTo.swift in Sources */, + 1F1871E61CA89FCD00A34BF2 /* MatcherFunc.swift in Sources */, + 1FD8CD421968AB07008ED995 /* BeEmpty.swift in Sources */, + 1F1871E41CA89FB600A34BF2 /* AsyncMatcherWrapper.swift in Sources */, + 1F1871CA1CA89EDB00A34BF2 /* NMBStringify.m in Sources */, + 1FD8CD521968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6A1968AB07008ED995 /* Async.swift in Sources */, + 1FD8CD581968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD5C1968AB07008ED995 /* MatcherProtocols.swift in Sources */, + 1FD8CD341968AB07008ED995 /* DSL.swift in Sources */, + 7B5358BE1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + 1FD8CD381968AB07008ED995 /* Expression.swift in Sources */, + 1FD8CD3A1968AB07008ED995 /* FailureMessage.swift in Sources */, + 472FD1351B9E085700C7B8DA /* HaveCount.swift in Sources */, + 9630C0301C6D139F000693EE /* CwlDarwinDefinitions.swift in Sources */, + 9630C0231C6D0B82000693EE /* mach_excServer.c in Sources */, + 9630C01F1C6D0B2F000693EE /* CwlCatchException.swift in Sources */, + 9630C0131C6D0B18000693EE /* CwlCatchBadInstruction.swift in Sources */, + 9630C01C1C6D0B2F000693EE /* CwlCatchException.m in Sources */, + 9630C02C1C6D125F000693EE /* CwlBadInstructionException.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 */, + 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 */, + 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 */, + 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 /* ObjCContainElementSatisfying.m in Sources */, + 1F925EF6195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A56791A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m 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 /* ObjCHaveCount.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 */, + 1F5DF1881BDCA0F500C3A531 /* MatcherProtocols.swift in Sources */, + 1F5DF16E1BDCA0F500C3A531 /* NimbleXCTestHandler.swift in Sources */, + 1F5DF1751BDCA0F500C3A531 /* FailureMessage.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 */, + 1F5DF1741BDCA0F500C3A531 /* Expression.swift in Sources */, + 1F5DF1781BDCA0F500C3A531 /* BeAnInstanceOf.swift in Sources */, + 1F5DF1771BDCA0F500C3A531 /* BeAKindOf.swift in Sources */, + 1F5DF17F1BDCA0F500C3A531 /* BeLessThan.swift in Sources */, + 1F4BB8A41DAC9DC90048464B /* CwlCatchBadInstructionPOSIX.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 */, + 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 */, + 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 */, + 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 /* ObjCHaveCount.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 */, + CD79C9A91D2CC848004B6F9A /* ObjCBeKindOfTest.m in Sources */, + 1F5DF1A51BDCA10200C3A531 /* ContainTest.swift in Sources */, + 7B13BA121DD361EB00C9098C /* ObjCContainElementSatisfying.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 */, + 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 */, + 1F5DF1A41BDCA10200C3A531 /* BeNilTest.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 = ( + 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 */, + 1F2D175C1DB618F000EE9C7A /* mach_excServer.c in Sources */, + 1F1871D21CA89EEE00A34BF2 /* DSL.m in Sources */, + 1F4BB8BB1DACBFD00048464B /* CwlCatchBadInstruction.m in Sources */, + AE7ADE461C80BF8000B94CD3 /* MatchError.swift in Sources */, + 1FC494AB1C29CBA40010975C /* NimbleEnvironment.swift in Sources */, + 1FD8CD5F1968AB07008ED995 /* RaisesException.swift in Sources */, + 1FD8CD571968AB07008ED995 /* Contain.swift in Sources */, + 1FD8CD491968AB07008ED995 /* BeGreaterThanOrEqualTo.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 */, + 1FD8CD531968AB07008ED995 /* BeNil.swift in Sources */, + 1FD8CD6B1968AB07008ED995 /* Async.swift in Sources */, + 964CFEFE1C4FF48900513336 /* ThrowAssertion.swift in Sources */, + 1FD8CD591968AB07008ED995 /* EndWith.swift in Sources */, + 1FD8CD5D1968AB07008ED995 /* MatcherProtocols.swift in Sources */, + 1FD8CD351968AB07008ED995 /* DSL.swift in Sources */, + 7B5358BF1C38479700A23FAA /* SatisfyAnyOf.swift in Sources */, + 1FD8CD391968AB07008ED995 /* Expression.swift in Sources */, + 1FD8CD3B1968AB07008ED995 /* FailureMessage.swift in Sources */, + 472FD1391B9E0A9700C7B8DA /* HaveCount.swift in Sources */, + 9630C0311C6D139F000693EE /* CwlDarwinDefinitions.swift in Sources */, + 9630C0201C6D0B2F000693EE /* CwlCatchException.swift in Sources */, + 9630C0141C6D0B18000693EE /* CwlCatchBadInstruction.swift in Sources */, + 9630C01D1C6D0B2F000693EE /* CwlCatchException.m in Sources */, + 9630C02D1C6D125F000693EE /* CwlBadInstructionException.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 */, + 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 */, + 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 */, + 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 /* ObjCContainElementSatisfying.m in Sources */, + 1F925EF7195C147800ED456B /* BeCloseToTest.swift in Sources */, + 1F4A567A1A3B32E3009E1637 /* ObjCBeGreaterThanOrEqualToTest.m 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 /* ObjCHaveCount.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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + 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_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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + 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_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; + }; +/* 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; + }; +/* End XCConfigurationList section */ + }; + rootObject = 1F1A74201940169200FFFC47 /* Project object */; +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a822b74 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme new file mode 100644 index 0000000..4a6682b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-iOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme new file mode 100644 index 0000000..4aa936e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-macOS.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme new file mode 100644 index 0000000..2309132 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Nimble.xcodeproj/xcshareddata/xcschemes/Nimble-tvOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift new file mode 100644 index 0000000..46d1ff6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Package.swift @@ -0,0 +1,10 @@ +import PackageDescription + +let package = Package( + name: "Nimble", + exclude: [ + "Sources/Lib", + "Sources/NimbleObjectiveC", + "Tests/NimbleTests/objc", + ] +) diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/README.md new file mode 100644 index 0000000..ecf9501 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/README.md @@ -0,0 +1,1443 @@ +# 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) + - [Checking if all elements of a collection pass a condition](#checking-if-all-elements-of-a-collection-pass-a-condition) + - [Verify collection count](#verify-collection-count) + - [Verify a notification was posted](#verifying-a-notification-was-posted) + - [Matching a value to any of a group of matchers](#matching-a-value-to-any-of-a-group-of-matchers) +- [Writing Your Own Matchers](#writing-your-own-matchers) + - [Lazy Evaluation](#lazy-evaluation) + - [Type Checking via Swift Generics](#type-checking-via-swift-generics) + - [Customizing Failure Messages](#customizing-failure-messages) + - [Supporting Objective-C](#supporting-objective-c) + - [Properly Handling `nil` in Objective-C Matchers](#properly-handling-nil-in-objective-c-matchers) +- [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 + +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 + // do some stuff that takes a while... + NSThread.sleepForTimeInterval(0.5) + done() +} +``` + +```objc +// Objective-C + +waitUntil(^(void (^done)(void)){ + // do some stuff that takes a while... + [NSThread sleepForTimeInterval:0.5]; + done(); +}); +``` + +`waitUntil` also optionally takes a timeout parameter: + +```swift +// Swift + +waitUntil(timeout: 10) { done in + // do some stuff that takes a while... + NSThread.sleepForTimeInterval(1) + done() +} +``` + +```objc +// Objective-C + +waitUntilTimeout(10, ^(void (^done)(void)){ + // do some stuff that takes a while... + [NSThread sleepForTimeInterval:1]; + 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(beKindOf(Int.self)) +expect("turtle").to(beKindOf(String.self)) + +let classObject = SomeClassConformingToProtocol() +expect(classObject).to(beKindOf(SomeProtocol.self)) +expect(classObject).to(beKindOf(SomeClassConformingToProtocol.self)) +expect(classObject).toNot(beKindOf(SomeStructConformingToProtocol.self)) + +let structObject = SomeStructConformingToProtocol() +expect(structObject).to(beKindOf(SomeProtocol.self)) +expect(structObject).to(beKindOf(SomeStructConformingToProtocol.self)) +expect(structObject).toNot(beKindOf(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 +``` + +Its important to remember that `beIdenticalTo` only makes sense when comparing types with reference semantics, which have a notion of identity. In Swift, that means a `class`. This matcher will not work with types with value semantics such as `struct` or `enum`. If you need to compare two value types, you can either compare individual properties or if it makes sense to do so, make your type implement `Equatable` and use 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 calling fatalError() or precondition fails: +expect { () -> Void in fatalError() }.to(throwAssertion()) +expect { precondition(false) }.to(throwAssertion()) + +// Passes if throwing a NSError is not equal to throwing an assertion: +expect { throw NSError(domain: "test", code: 0, userInfo: nil) }.toNot(throwAssertion()) + +// Passes if the post assertion code 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+, you can use the `throwError` matcher to check if an error is thrown. + +```swift +// Swift + +// Passes if somethingThatThrows() throws an ErrorProtocol: +expect{ try somethingThatThrows() }.to(throwError()) + +// Passes if somethingThatThrows() throws an error with a given domain: +expect{ try somethingThatThrows() }.to(throwError { (error: ErrorProtocol) in + expect(error._domain).to(equal(NSCocoaErrorDomain)) +}) + +// Passes if somethingThatThrows() throws an error with a given case: +expect{ try somethingThatThrows() }.to(throwError(NSCocoaError.PropertyListReadCorruptError)) + +// Passes if somethingThatThrows() throws an error with a given type: +expect{ try somethingThatThrows() }.to(throwError(errorType: NimbleError.self)) +``` + +If you are working directly with `ErrorProtocol` values, as is sometimes the case when using `Result` or `Promise` types, you can use the `matchError` matcher to check if the error is the same error is is supposed to be, without requiring explicit casting. + +```swift +// Swift + +let actual: ErrorProtocol = … + +// Passes if actual contains any error value from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum)) + +// Passes if actual contains the Timeout value from the NimbleErrorEnum type: +expect(actual).to(matchError(NimbleErrorEnum.Timeout)) + +// Passes if actual contains an NSError equal to the given one: +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 and it passes expectations in the block +// (in this case, if 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 in the 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 an empty collection (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 an empty collection (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 +struct Turtle { + var color: String! +} + +var turtles = functionThatReturnsSomeTurtlesInAnyOrder() + +// This set of matchers passes 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 +@interface Turtle: NSObject +@property(nonatomic) NSString *color; +@end +@implementation Turtle @end + +NSArray *turtles = functionThatReturnsSomeTurtlesInAnyOrder(); + +// This set of matchers passes whether the array is [{color: "blue"}, {color: "green"}] +// or [{color: "green"}, {color: "blue"}] +expect(turtles).to(containElementSatisfying(^BOOL(id object) { + return [turtle.color isEqualToString:@"green"]; +})); +expect(turtles).to(containElementSatisfying(^BOOL(id object) { + return [turtle.color isEqualToString:@"blue"]; +})); +``` + +## Strings + +```swift +// Swift + +// Passes if actual contains substring expected: +expect(actual).to(contain(expected)) + +// Passes if actual begins with substring: +expect(actual).to(beginWith(expected)) + +// Passes if actual ends with substring: +expect(actual).to(endWith(expected)) + +// Passes if actual is an 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 expected: +expect(actual).to(contain(expected)); + +// Passes if actual begins with substring: +expect(actual).to(beginWith(expected)); + +// Passes if actual ends with substring: +expect(actual).to(endWith(expected)); + +// Passes if actual is an empty string, "": +expect(actual).to(beEmpty()); + +// Passes if actual matches the regular expression defined in expected: +expect(actual).to(match(expected)) +``` + +## Checking if all elements of a collection pass a condition + +```swift +// Swift + +// with a custom function: +expect([1,2,3,4]).to(allPass({$0 < 5})) + +// with another matcher: +expect([1,2,3,4]).to(allPass(beLessThan(5))) +``` + +```objc +// Objective-C + +expect(@[@1, @2, @3,@4]).to(allPass(beLessThan(@5))); +``` + +For Swift the actual value has to be a Sequence, e.g. an array, a set or a custom seqence type. + +For Objective-C the actual value has to be a NSFastEnumeration, e.g. NSArray and NSSet, of NSObjects and only the variant which +uses another matcher is available here. + +## Verify collection count + +```swift +// Swift + +// passes if actual collection's count is equal to expected +expect(actual).to(haveCount(expected)) + +// passes if actual collection's count is not equal to expected +expect(actual).notTo(haveCount(expected)) +``` + +```objc +// Objective-C + +// passes if actual collection's count is equal to expected +expect(actual).to(haveCount(expected)) + +// passes if actual collection's count is not equal to expected +expect(actual).notTo(haveCount(expected)) +``` + +For Swift the actual value must be a `Collection` such as array, dictionary or set. + +For Objective-C the actual value has to be one of the following classes `NSArray`, `NSDictionary`, `NSSet`, `NSHashTable` or one of their subclasses. + +## Foundation + +### Verifying a Notification was posted + +```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 +// 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 +// 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. + +# Writing Your Own Matchers + +In Nimble, matchers are Swift functions that take an expected +value and return a `MatcherFunc` closure. Take `equal`, for example: + +```swift +// Swift + +public func equal(expectedValue: T?) -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(expectedValue)>" + if let actualValue = try actualExpression.evaluate() { + return actualValue == expectedValue + } else { + return false + } + } +} +``` + +The return value of a `MatcherFunc` closure is a `Bool` that indicates +whether the actual value matches the expectation: `true` if it does, or +`false` if it doesn't. + +> The actual `equal` matcher function does not match when either + `actual` or `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. + +## 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() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be nil" + return actualExpression.evaluate() == 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. + +Use `expression.isClosure` to determine if the expression will be invoking +a closure to produce its value. + +## 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) -> MatcherFunc { + return MatcherFunc { actual, failureMessage in + return actual.evaluate().description == description + } +} +``` + +## Customizing Failure Messages + +By default, Nimble outputs the following failure message when an +expectation fails: + +``` +expected to match, got <\(actual)> +``` + +You can customize this message by modifying the `failureMessage` struct +from within your `MatcherFunc` closure. To change the verb "match" to +something else, update the `postfixMessage` property: + +```swift +// Swift + +// Outputs: expected to be under the sea, got <\(actual)> +failureMessage.postfixMessage = "be under the sea" +``` + +You can change how the `actual` value is displayed by updating +`failureMessage.actualValue`. Or, to remove it altogether, set it to +`nil`: + +```swift +// Swift + +// Outputs: expected to be under the sea +failureMessage.actualValue = nil +failureMessage.postfixMessage = "be under the sea" +``` + +## 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) + } + } +} +``` + +# 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', '~> 5.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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/.gitignore b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/.gitignore new file mode 100644 index 0000000..5b05d7e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +project.xcworkspace/ +xcuserdata/ diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.h new file mode 100644 index 0000000..6ec6a29 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.h @@ -0,0 +1,30 @@ +// +// 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[]; + +__attribute__((visibility("hidden"))) +NSException* __nullable catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)()); diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.m new file mode 100644 index 0000000..4f9772c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.m @@ -0,0 +1,35 @@ +// +// 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" + +__attribute__((visibility("hidden"))) +NSException* catchExceptionOfKind(Class __nonnull type, __attribute__((noescape)) void (^ __nonnull inBlock)()) { + @try { + inBlock(); + } @catch (NSException *exception) { + if ([exception isKindOfClass:type]) { + return exception; + } else { + @throw; + } + } + return nil; +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.swift new file mode 100644 index 0000000..b44a232 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/CwlCatchException.swift @@ -0,0 +1,32 @@ +// +// 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 + +// We can't simply cast to Self? in the catchInBlock method so we need this generic function wrapper to do the conversion for us. Mildly annoying. +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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/Info.plist new file mode 100644 index 0000000..f14cf1e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlCatchException/CwlCatchException/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 © 2016 Matt Gallagher. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift new file mode 100644 index 0000000..5bf2794 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlBadInstructionException.swift @@ -0,0 +1,76 @@ +// +// 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 + +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 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. + public class func catch_mach_exception_raise_state(_ exception_port: mach_port_t, exception: exception_type_t, code: UnsafePointer, codeCnt: mach_msg_type_number_t, flavor: UnsafeMutablePointer, old_state: UnsafePointer, old_stateCnt: mach_msg_type_number_t, new_state: thread_state_t, new_stateCnt: UnsafeMutablePointer) -> kern_return_t { + + #if arch(x86_64) + // Make sure we've been given enough memory + if old_stateCnt != x86_THREAD_STATE64_COUNT || new_stateCnt.pointee < x86_THREAD_STATE64_COUNT { + return 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 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 KERN_SUCCESS + #else + fatalError("Unavailable for this CPU architecture") + #endif + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.h new file mode 100644 index 0000000..0333ed2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.h @@ -0,0 +1,61 @@ +// +// CwlCatchBadInstruction.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. +// + +#if defined(__x86_64__) + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +// 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; + +extern boolean_t mach_exc_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP); + +NS_ASSUME_NONNULL_END + +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m new file mode 100644 index 0000000..22c1377 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.m @@ -0,0 +1,50 @@ +// +// CwlCatchBadInstruction.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 "CwlCatchBadInstruction.h" + +// Assuming the "PRODUCT_NAME" macro is defined, this will create the name of the Swift generated header file +#define STRINGIZE_NO_EXPANSION(A) #A +#define STRINGIZE_WITH_EXPANSION(A) STRINGIZE_NO_EXPANSION(A) +#define SWIFT_INCLUDE STRINGIZE_WITH_EXPANSION(PRODUCT_NAME-Swift.h) + +// Include the Swift generated header file +#import SWIFT_INCLUDE + +/// 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) { + return [BadInstructionException catch_mach_exception_raise_state:exception_port exception:exception code:code codeCnt:codeCnt flavor:flavor old_state:old_state old_stateCnt:old_stateCnt new_state:new_state new_stateCnt:new_stateCnt]; +} + +// 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift new file mode 100644 index 0000000..4d82f7a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstruction.swift @@ -0,0 +1,193 @@ +// +// 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 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 execTypesCountTuple { + mutating func pointer(in block: (UnsafeMutablePointer) -> R) -> R { + return withUnsafeMutablePointer(to: &self) { p -> R in + return p.withMemoryRebound(to: T.self, capacity: EXC_TYPES_COUNT) { ptr -> R in + return block(ptr) + } + } + } + } + + 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 + + mutating func withUnsafeMutablePointers(in block: (UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer, UnsafeMutablePointer) -> R) -> R { + return masks.pointer { masksPtr in + return ports.pointer { portsPtr in + return behaviors.pointer { behaviorsPtr in + return flavors.pointer { flavorsPtr in + return block(masksPtr, portsPtr, behaviorsPtr, flavorsPtr) + } + } + } + } + } + } + + /// 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) + try kernCheck { request.withMsgHeaderPointer { requestPtr in + mach_msg(requestPtr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0, request.Head.msgh_size, 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 + try kernCheck { reply.withMsgHeaderPointer { replyPtr in + mach_msg(replyPtr, MACH_SEND_MSG, reply.Head.msgh_size, 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) + } + + try kernCheck { context.withUnsafeMutablePointers { masksPtr, 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, context.currentExceptionPort, Int32(bitPattern: UInt32(EXCEPTION_STATE) | MACH_EXCEPTION_CODES), x86_THREAD_STATE64, masksPtr, &context.count, portsPtr, behaviorsPtr, flavorsPtr) + } } + + defer { context.withUnsafeMutablePointers { masksPtr, 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, &context.count, 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift new file mode 100644 index 0000000..bf30908 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlCatchBadInstructionPOSIX.swift @@ -0,0 +1,100 @@ +// +// 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. + +private var env = jmp_buf(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +private func triggerLongJmp() { + longjmp(&env.0, 1) +} + +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 = triggerLongJmp + 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: () -> 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)") + } + } + + // Prepare the jump point + if setjmp(&env.0) != 0 { + // Handle jump received + return BadInstructionException() + } + + // Run the block + block() + + return nil +} + +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift new file mode 100644 index 0000000..35e1ad5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/CwlDarwinDefinitions.swift @@ -0,0 +1,63 @@ +// +// 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/port.h +// #define MACH_PORT_RIGHT_RECEIVE ((mach_port_right_t) 1) +let MACH_PORT_RIGHT_RECEIVE: mach_port_right_t = 1 + +// 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)) +let MACH_MSG_TYPE_MAKE_SEND: UInt32 = 20 +func MACH_MSGH_BITS_REMOTE(_ bits: UInt32) -> UInt32 { return bits & UInt32(MACH_MSGH_BITS_REMOTE_MASK) } +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) +// #define EXCEPTION_DEFAULT 1 +let EXC_BAD_INSTRUCTION: UInt32 = 2 +let EXC_MASK_BAD_INSTRUCTION: UInt32 = 1 << EXC_BAD_INSTRUCTION +let EXCEPTION_DEFAULT: Int32 = 1 + +// From /usr/include/mach/i386/thread_status.h +// #define THREAD_STATE_NONE 13 +// #define x86_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \ +// ( sizeof (x86_thread_state64_t) / sizeof (int) )) +let THREAD_STATE_NONE: Int32 = 13 +let x86_THREAD_STATE64_COUNT = UInt32(MemoryLayout.size / MemoryLayout.size) + +let EXC_TYPES_COUNT = 14 +struct execTypesCountTuple { + // From /usr/include/mach/i386/exception.h + // #define EXC_TYPES_COUNT 14 /* incl. illegal exception 0 */ + 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) + init() { + } +} + +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/Info.plist new file mode 100644 index 0000000..f14cf1e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/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 © 2016 Matt Gallagher. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.c b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.c new file mode 100644 index 0000000..2334538 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.c @@ -0,0 +1,537 @@ +/* + * IDENTIFICATION: + * stub generated Mon Jan 11 00:24:26 2016 + * with a MiG generated by bootstrap_cmds-93 + * OPTIONS: + */ + +/* Module mach_exc */ + +#if defined(__x86_64__) + +#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; + + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.h new file mode 100644 index 0000000..766ba11 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/CwlPreconditionTesting/mach_excServer.h @@ -0,0 +1,298 @@ +#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 */ + + +#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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/README.md new file mode 100644 index 0000000..a1a9a70 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Lib/CwlPreconditionTesting/README.md @@ -0,0 +1,80 @@ +# 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. + +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) + +## Usage + +The short version is: + +1. `git clone https://github.com/mattgallagher/CwlPreconditionTesting.git` +2. drag the "CwlPreconditionTesting.xcodeproj" file into your project's file tree in Xcode +3. go to your testing target's Build Phase settings and under "Target Dependencies" press the "+" button and select the relevant "CwlPreconditionTesting" target ("_iOS" or "_OSX", depending on your testing target's SDK) +4. write `import CwlPreconditionTesting` at the top of any test file where you want to use `catchBadInstruction` (Swift should handle the linkage automatically when you do this) +5. use the `catchBadInstruction` function as shown in the [CwlCatchBadInstructionTests.swift tests file](https://github.com/mattgallagher/CwlPreconditionTesting/blob/master/CwlPreconditionTestingTests/CwlCatchBadInstructionTests.swift?ts=4) + +### Project details + +The "CwlPreconditionTesting.xcodeproj" contains two targets: + +* CwlPreconditionTesting_OSX +* CwlPreconditionTesting_iOS + +both build a framework named "CwlPreconditionTesting.framework". If you're linking manually, be certain to select the "CwlPreconditionTesting.framework" from the appropriate target. + +Remember: the iOS build is useful only in the simulator. All Mach exception handling code will be conditionally excluded in any device build. + +### Static inclusion + +Due to the complications associated with needing to call into and out of Objective-C, static inclusion in other projects is not a single file nor a quick drag and drop. There's at least 7 files and you'll need to add some project settings. + +All of the following files: + +* CwlCatchBadInstruction.swift +* CwlCatchBadInstruction.h +* CwlCatchBadInstruction.m +* CwlCatchException.swift +* CwlCatchException.h +* CwlCatchException.m + +and either: + +* $(SDKROOT)/usr/include/mach/mach_exc.defs +* mach_excServer.c + +need to be added to the testing target for OS X projects or iOS projects, respectively. + +Your target will also need to have the following macros defined in the "Apple LLVM - Preprocessing" → "Preprocessor Macros" build setting: + + PRODUCT_NAME=$(PRODUCT_NAME) + +This lets the Objective-C file generate the include directive for the autogenerated Swift header so it can call back into Swift during the Mach exception handler callbacks. This macro should stay in sync if you change the target name but if you do anything else in your project that changes the name of the autogenerated Swift header independent of the target name (or you want to add spaces or other command-line complications to the target name), you'll want to update "CwlCatchBadInstruction.m" directly with the correct include directive. + +Additionally, you'll need a standard Objective-C "Bridging header" for your testing target and it will need to include the following import statements: + +``` +#if defined(__x86_64__) +#import +#endif + +#import +``` + +### 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AdapterProtocols.swift new file mode 100644 index 0000000..2e58fdf --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionDispatcher.swift new file mode 100644 index 0000000..94a9030 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/AssertionRecorder.swift new file mode 100644 index 0000000..740c392 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift new file mode 100644 index 0000000..1c51cd7 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBExpectation.swift @@ -0,0 +1,131 @@ +import Foundation + +#if _runtime(_ObjC) + +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 + + 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? + } + } + + public var withTimeout: (TimeInterval) -> NMBExpectation { + return ({ timeout in self._timeout = timeout + return self + }) + } + + public var to: (NMBMatcher) -> Void { + return ({ matcher in + self.expectValue.to(ObjCMatcherWrapper(matcher: matcher)) + }) + } + + public var toWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + self.expectValue.to(ObjCMatcherWrapper(matcher: matcher), description: description) + }) + } + + public var toNot: (NMBMatcher) -> Void { + return ({ matcher in + self.expectValue.toNot( + ObjCMatcherWrapper(matcher: matcher) + ) + }) + } + + public var toNotWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + self.expectValue.toNot( + ObjCMatcherWrapper(matcher: matcher), description: description + ) + }) + } + + public var notTo: (NMBMatcher) -> Void { return toNot } + + public var notToWithDescription: (NMBMatcher, String) -> Void { return toNotWithDescription } + + public var toEventually: (NMBMatcher) -> Void { + return ({ matcher in + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + }) + } + + public var toEventuallyWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + self.expectValue.toEventually( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + }) + } + + public var toEventuallyNot: (NMBMatcher) -> Void { + return ({ matcher in + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: nil + ) + }) + } + + public var toEventuallyNotWithDescription: (NMBMatcher, String) -> Void { + return ({ matcher, description in + self.expectValue.toEventuallyNot( + ObjCMatcherWrapper(matcher: matcher), + timeout: self._timeout, + description: description + ) + }) + } + + public var toNotEventually: (NMBMatcher) -> Void { return toEventuallyNot } + + public var toNotEventuallyWithDescription: (NMBMatcher, String) -> Void { return toEventuallyNotWithDescription } + + public class func failWithMessage(_ message: String, file: FileString, line: UInt) { + fail(message, location: SourceLocation(file: file, line: line)) + } +} + +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift new file mode 100644 index 0000000..19a4567 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NMBObjCMatcher.swift @@ -0,0 +1,81 @@ +import Foundation + +#if _runtime(_ObjC) + +public typealias MatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage) -> Bool +public typealias FullMatcherBlock = (_ actualExpression: Expression, _ failureMessage: FailureMessage, _ shouldNotMatch: Bool) -> Bool + +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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleEnvironment.swift new file mode 100644 index 0000000..a55cb27 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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' existance +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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift new file mode 100644 index 0000000..78e6dd9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NimbleXCTestHandler.swift @@ -0,0 +1,76 @@ +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 _runtime(_ObjC) + // 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 { + testCase.recordFailure(withDescription: message, inFile: location.file, atLine: location.line, expected: true) + } else { + let msg = "Attempted to report a test failure to XCTest while no test case was running. " + + "The failure was:\n\"\(message)\"\nIt occurred at: \(location.file):\(location.line)" + NSException(name: .internalInconsistencyException, reason: msg, userInfo: nil).raise() + } +#endif +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift new file mode 100644 index 0000000..dd02aa4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Adapters/NonObjectiveC/ExceptionCapture.swift @@ -0,0 +1,31 @@ +import Foundation + +#if !_runtime(_ObjC) +// 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift new file mode 100644 index 0000000..f7f373f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL+Wait.swift @@ -0,0 +1,98 @@ +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 { + internal class func until( + timeout: TimeInterval, + file: FileString = #file, + line: UInt = #line, + action: @escaping (@escaping () -> Void) -> Void) -> Void { + return throwableUntil(timeout: timeout, file: file, line: line) { done in + action(done) + } + } + + // 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) -> Void { + let awaiter = NimbleEnvironment.activeInstance.awaiter + let leeway = timeout / 2.0 + let result = awaiter.performBlock { (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 SWIFT_PACKAGE + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) -> Void { + until(timeout: 1, file: file, line: line, action: action) + } + #else + @objc(untilFile:line:action:) + internal class func until(_ file: FileString = #file, line: UInt = #line, action: @escaping (() -> Void) -> Void) -> Void { + until(timeout: 1, file: file, line: line, action: action) + } + #endif +} + +internal func blockedRunLoopErrorMessageFor(_ fnName: String, leeway: TimeInterval) -> String { + 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 = 1, file: FileString = #file, line: UInt = #line, action: @escaping (@escaping () -> Void) -> Void) -> Void { + NMBWait.until(timeout: timeout, file: file, line: line, action: action) +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/DSL.swift new file mode 100644 index 0000000..7ebd684 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift new file mode 100644 index 0000000..c5978f4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expectation.swift @@ -0,0 +1,71 @@ +import Foundation + +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.actualValue = "an unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +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.actualValue = "an unexpected error thrown: <\(error)>" + return (false, msg) + } +} + +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) + } + + /// 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) + } + + /// Tests the actual value using a matcher to not match. + public func toNot(_ matcher: U, description: String? = nil) + where U: Matcher, U.ValueType == T { + let (pass, msg) = expressionDoesNotMatch(expression, matcher: matcher, toNot: "to not", description: description) + verify(pass, msg) + } + + /// 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) + } + + // see: + // - AsyncMatcherWrapper for extension + // - NMBExpectation for Objective-C interface +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift new file mode 100644 index 0000000..f7afffe --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Expression.swift @@ -0,0 +1,90 @@ +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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift new file mode 100644 index 0000000..24b6c8f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/FailureMessage.swift @@ -0,0 +1,65 @@ +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? = nil + public var userDescription: String? = nil + + public var stringValue: String { + get { + if let value = _stringValueOverride { + return value + } else { + return computeStringValue() + } + } + set { + _stringValueOverride = newValue + } + } + + internal var _stringValueOverride: String? + + 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 + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Info.plist new file mode 100644 index 0000000..6ac80b8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift new file mode 100644 index 0000000..73e79d3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AllPass.swift @@ -0,0 +1,94 @@ +import Foundation + +public func allPass + (_ passFunc: @escaping (T?) -> Bool) -> NonNilMatcherFunc + where U: Sequence, U.Iterator.Element == T { + return allPass("pass a condition", passFunc) +} + +public func allPass + (_ passName: String, _ passFunc: @escaping (T?) -> Bool) -> NonNilMatcherFunc + where U: Sequence, U.Iterator.Element == T { + return createAllPassMatcher { expression, failureMessage in + failureMessage.postfixMessage = passName + return passFunc(try expression.evaluate()) + } +} + +public func allPass + (_ matcher: V) -> NonNilMatcherFunc + where U: Sequence, V: Matcher, U.Iterator.Element == V.ValueType { + return createAllPassMatcher { + try matcher.matches($0, failureMessage: $1) + } +} + +private func createAllPassMatcher + (_ elementEvaluator: @escaping (Expression, FailureMessage) throws -> Bool) -> NonNilMatcherFunc + where U: Sequence, U.Iterator.Element == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.actualValue = nil + if let actualValue = try actualExpression.evaluate() { + for currentElement in actualValue { + let exp = Expression( + expression: {currentElement}, location: actualExpression.location) + if try !elementEvaluator(exp, failureMessage) { + failureMessage.postfixMessage = + "all \(failureMessage.postfixMessage)," + + " but failed first at element <\(stringify(currentElement))>" + + " in <\(stringify(actualValue))>" + return false + } + } + failureMessage.postfixMessage = "all \(failureMessage.postfixMessage)" + } else { + failureMessage.postfixMessage = "all pass (use beNil() to match nils)" + return false + } + + return true + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func allPassMatcher(_ matcher: NMBObjCMatcher) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + var nsObjects = [NSObject]() + + var collectionIsUsable = true + if let value = actualValue as? NSFastEnumeration { + let 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 { + failureMessage.postfixMessage = + "allPass only works with NSFastEnumeration (NSArray, NSSet, ...) of NSObjects" + failureMessage.expected = "" + failureMessage.to = "" + return false + } + + let expr = Expression(expression: ({ nsObjects }), location: location) + let elementEvaluator: (Expression, FailureMessage) -> Bool = { + expression, failureMessage in + return matcher.matches({try! expression.evaluate()}, failureMessage: failureMessage, location: expr.location) + } + return try! createAllPassMatcher(elementEvaluator).matches( + expr, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift new file mode 100644 index 0000000..b971ccc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/AsyncMatcherWrapper.swift @@ -0,0 +1,141 @@ +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 +} + +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.actualValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.actualValue = "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.actualValue = "an unexpected error thrown: <\(error)>" + return false + case let .raisedException(exception): + failureMessage.actualValue = "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(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(_ 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift new file mode 100644 index 0000000..f636a72 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAKindOf.swift @@ -0,0 +1,48 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is an instance of the given class. +public func beAKindOf(_ expectedType: T.Type) -> NonNilMatcherFunc { + return NonNilMatcherFunc {actualExpression, failureMessage in + failureMessage.postfixMessage = "be a kind of \(String(describing: expectedType))" + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + failureMessage.actualValue = "" + return false + } + + failureMessage.actualValue = "<\(String(describing: type(of: validInstance))) instance>" + + guard validInstance is T else { + return false + } + + return true + } +} + +#if _runtime(_ObjC) + +/// 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) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + let instance = try actualExpression.evaluate() + if let validInstance = instance { + failureMessage.actualValue = "<\(String(describing: type(of: validInstance))) instance>" + } else { + failureMessage.actualValue = "" + } + failureMessage.postfixMessage = "be a kind of \(String(describing: expectedClass))" + return instance != nil && instance!.isKind(of: expectedClass) + } +} + +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift new file mode 100644 index 0000000..07ce3d3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeAnInstanceOf.swift @@ -0,0 +1,50 @@ +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) -> NonNilMatcherFunc { + return NonNilMatcherFunc {actualExpression, failureMessage in + failureMessage.postfixMessage = "be an instance of \(String(describing: expectedType))" + let instance = try actualExpression.evaluate() + guard let validInstance = instance else { + failureMessage.actualValue = "" + return false + } + + failureMessage.actualValue = "<\(String(describing: type(of: validInstance))) instance>" + + if type(of: validInstance) == expectedType { + return true + } + + return false + } +} + +/// 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) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + let instance = try actualExpression.evaluate() + if let validInstance = instance { + failureMessage.actualValue = "<\(String(describing: type(of: validInstance))) instance>" + } else { + failureMessage.actualValue = "" + } + failureMessage.postfixMessage = "be an instance of \(String(describing: expectedClass))" +#if _runtime(_ObjC) + return instance != nil && instance!.isMember(of: expectedClass) +#else + return instance != nil && type(of: instance!) == expectedClass +#endif + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift new file mode 100644 index 0000000..95c52cf --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeCloseTo.swift @@ -0,0 +1,122 @@ +import Foundation + +internal let DefaultDelta = 0.0001 + +internal func isCloseTo(_ actualValue: NMBDoubleConvertible?, expectedValue: NMBDoubleConvertible, delta: Double, failureMessage: FailureMessage) -> Bool { + failureMessage.postfixMessage = "be close to <\(stringify(expectedValue))> (within \(stringify(delta)))" + failureMessage.actualValue = "<\(stringify(actualValue))>" + return actualValue != nil && abs(actualValue!.doubleValue - expectedValue.doubleValue) < 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: Double, within delta: Double = DefaultDelta) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta, failureMessage: failureMessage) + } +} + +/// 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) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + return isCloseTo(try actualExpression.evaluate(), expectedValue: expectedValue, delta: delta, failureMessage: failureMessage) + } +} + +#if _runtime(_ObjC) +public class NMBObjCBeCloseToMatcher: NSObject, NMBMatcher { + var _expected: NSNumber + var _delta: CDouble + init(expected: NSNumber, within: CDouble) { + _expected = expected + _delta = within + } + + 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) + } + + 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) + } + + public var within: (CDouble) -> NMBObjCBeCloseToMatcher { + return ({ delta in + return NMBObjCBeCloseToMatcher(expected: self._expected, within: delta) + }) + } +} + +extension NMBObjCMatcher { + 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) -> NonNilMatcherFunc <[Double]> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be close to <\(stringify(expectedValues))> (each within \(stringify(delta)))" + if let actual = try actualExpression.evaluate() { + failureMessage.actualValue = "<\(stringify(actual))>" + + if actual.count != expectedValues.count { + return false + } else { + for (index, actualItem) in actual.enumerated() { + if fabs(actualItem - expectedValues[index]) > delta { + return false + } + } + return true + } + } + return false + } +} + +// 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift new file mode 100644 index 0000000..2ea2cdb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeEmpty.swift @@ -0,0 +1,91 @@ +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() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualSeq = try actualExpression.evaluate() + if actualSeq == nil { + return true + } + var generator = actualSeq!.makeIterator() + return 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() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualString = try actualExpression.evaluate() + return 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() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualString = try actualExpression.evaluate() + return 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() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualDictionary = try actualExpression.evaluate() + return 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() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actualArray = try actualExpression.evaluate() + return 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() -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be empty" + let actual = try actualExpression.evaluate() + return actual == nil || actual!.count == 0 + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beEmptyMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let location = actualExpression.location + let actualValue = try! actualExpression.evaluate() + failureMessage.postfixMessage = "be empty" + if let value = actualValue as? NMBCollection { + let expr = Expression(expression: ({ value as NMBCollection }), location: location) + return try! beEmpty().matches(expr, failureMessage: failureMessage) + } else if let value = actualValue as? NSString { + let expr = Expression(expression: ({ value as String }), location: location) + return try! beEmpty().matches(expr, failureMessage: failureMessage) + } else if let actualValue = actualValue { + failureMessage.postfixMessage = "be empty (only works for NSArrays, NSSets, NSIndexSets, NSDictionaries, NSHashTables, and NSStrings)" + failureMessage.actualValue = "\(String(describing: type(of: actualValue))) type" + } + return false + } + } +} +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift new file mode 100644 index 0000000..c7eb84c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThan.swift @@ -0,0 +1,41 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be greater than <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual > expected + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual value is greater than the expected value. +public func beGreaterThan(_ expectedValue: NMBComparable?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +public func >(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThan(rhs)) +} + +public func > (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beGreaterThan(rhs)) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeGreaterThanOrEqualTo.swift new file mode 100644 index 0000000..2949fce --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +/// A Nimble matcher that succeeds when the actual value is greater than +/// or equal to the expected value. +public func beGreaterThanOrEqualTo(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +public func >=(lhs: Expectation, rhs: T) { + lhs.to(beGreaterThanOrEqualTo(rhs)) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeIdenticalTo.swift new file mode 100644 index 0000000..8df7e5f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +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?) -> NonNilMatcherFunc { + return beIdenticalTo(expected) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThan.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThan.swift new file mode 100644 index 0000000..5bbbf36 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be less than <\(stringify(expectedValue))>" + if let actual = try actualExpression.evaluate(), let expected = expectedValue { + return actual < expected + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual value is less than the expected value. +public func beLessThan(_ expectedValue: NMBComparable?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +public func <(lhs: Expectation, rhs: T) { + lhs.to(beLessThan(rhs)) +} + +public func < (lhs: Expectation, rhs: NMBComparable?) { + lhs.to(beLessThan(rhs)) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLessThanOrEqual.swift new file mode 100644 index 0000000..a0cd2f0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +/// A Nimble matcher that succeeds when the actual value is less than +/// or equal to the expected value. +public func beLessThanOrEqualTo(_ expectedValue: T?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +public func <=(lhs: Expectation, rhs: T) { + lhs.to(beLessThanOrEqualTo(rhs)) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift new file mode 100644 index 0000000..49272a3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeLogical.swift @@ -0,0 +1,173 @@ +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 matcherWithFailureMessage(_ matcher: NonNilMatcherFunc, postprocessor: @escaping (FailureMessage) -> Void) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + defer { postprocessor(failureMessage) } + return try matcher.matcher(actualExpression, failureMessage) + } +} + +// 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() -> NonNilMatcherFunc { + return matcherWithFailureMessage(equal(true)) { failureMessage in + failureMessage.postfixMessage = "be true" + } +} + +/// A Nimble matcher that succeeds when the actual value is exactly false. +/// This matcher will not match against nils. +public func beFalse() -> NonNilMatcherFunc { + return matcherWithFailureMessage(equal(false)) { failureMessage in + failureMessage.postfixMessage = "be false" + } +} + +// MARK: beTruthy() / beFalsy() + +/// A Nimble matcher that succeeds when the actual value is not logically false. +public func beTruthy() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be truthy" + 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 number.boolValue == true + } + + return actualValue == (true as T) + } + return actualValue != nil + } +} + +/// A Nimble matcher that succeeds when the actual value is logically false. +/// This matcher will match against nils. +public func beFalsy() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be falsy" + 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 number.boolValue == false + } + + return actualValue == (false as T) + } + return actualValue == nil + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + 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) + } + } + + 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) + } + } + + 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) + } + } + + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift new file mode 100644 index 0000000..a6fb31f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeNil.swift @@ -0,0 +1,20 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual value is nil. +public func beNil() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "be nil" + let actualValue = try actualExpression.evaluate() + return actualValue == nil + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beNilMatcher() -> NMBObjCMatcher { + return NMBObjCMatcher { actualExpression, failureMessage in + return try! beNil().matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeVoid.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeVoid.swift new file mode 100644 index 0000000..92a8d43 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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() -> MatcherFunc<()> { + return MatcherFunc { 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift new file mode 100644 index 0000000..31cbe5d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/BeginWith.swift @@ -0,0 +1,63 @@ +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) -> NonNilMatcherFunc + where S.Iterator.Element == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingElement)>" + if let actualValue = try actualExpression.evaluate() { + var actualGenerator = actualValue.makeIterator() + return actualGenerator.next() == startingElement + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual collection's first element +/// is equal to the expected object. +public func beginWith(_ startingElement: Any) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingElement)>" + 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: 0) as? NSObject else { + return false + } + #else + let collectionValue = collection.object(at: 0) as AnyObject + #endif + return 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) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "begin with <\(startingSubstring)>" + if let actual = try actualExpression.evaluate() { + let range = actual.range(of: startingSubstring) + return range != nil && range!.lowerBound == actual.startIndex + } + return false + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func beginWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if let _ = actual as? String { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift new file mode 100644 index 0000000..5053642 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Contain.swift @@ -0,0 +1,94 @@ +import Foundation + +/// A Nimble matcher that succeeds when the actual sequence contains the expected value. +public func contain(_ items: T...) -> NonNilMatcherFunc + where S.Iterator.Element == T { + return contain(items) +} + +public func contain(_ items: [T]) -> NonNilMatcherFunc + where S.Iterator.Element == T { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "contain <\(arrayAsString(items))>" + if let actual = try actualExpression.evaluate() { + return items.all { + return actual.contains($0) + } + } + return false + } +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: String...) -> NonNilMatcherFunc { + return contain(substrings) +} + +public func contain(_ substrings: [String]) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +/// A Nimble matcher that succeeds when the actual string contains the expected substring. +public func contain(_ substrings: NSString...) -> NonNilMatcherFunc { + return contain(substrings) +} + +public func contain(_ substrings: [NSString]) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +/// A Nimble matcher that succeeds when the actual collection contains the expected object. +public func contain(_ items: Any?...) -> NonNilMatcherFunc { + return contain(items) +} + +public func contain(_ items: [Any?]) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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!) + } + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + 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 { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift new file mode 100644 index 0000000..ae8cca2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ContainElementSatisfying.swift @@ -0,0 +1,59 @@ +import Foundation + +public func containElementSatisfying(_ predicate: @escaping ((T) -> Bool), _ predicateDescription: String = "") -> NonNilMatcherFunc where S.Iterator.Element == T { + + return NonNilMatcherFunc { 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 + } +} + +#if _runtime(_ObjC) + extension NMBObjCMatcher { + 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 { + failureMessage.postfixMessage = "containElementSatisfying must be provided an NSFastEnumeration object" + failureMessage.actualValue = nil + failureMessage.expected = "" + failureMessage.to = "" + return false + } + + let 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/EndWith.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/EndWith.swift new file mode 100644 index 0000000..00c7e20 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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) -> NonNilMatcherFunc + where S.Iterator.Element == T { + return NonNilMatcherFunc { 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 + } +} + +/// A Nimble matcher that succeeds when the actual collection's last element +/// is equal to the expected object. +public func endWith(_ endingElement: Any) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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) + } +} + +/// 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) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "end with <\(endingSubstring)>" + if let collection = try actualExpression.evaluate() { + return collection.hasSuffix(endingSubstring) + } + return false + } +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func endWithMatcher(_ expected: Any) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + let actual = try! actualExpression.evaluate() + if let _ = actual as? String { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift new file mode 100644 index 0000000..1dccfd0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Equal.swift @@ -0,0 +1,181 @@ +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?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + let matches = actualValue == expectedValue && expectedValue != nil + if expectedValue == nil || actualValue == nil { + if expectedValue == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + return false + } + return matches + } +} + +/// 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]?) -> NonNilMatcherFunc<[T: C]> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + return false + } + return expectedValue! == actualValue! + } +} + +/// 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]?) -> NonNilMatcherFunc<[T]> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + let actualValue = try actualExpression.evaluate() + if expectedValue == nil || actualValue == nil { + if expectedValue == nil { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + return false + } + return expectedValue! == actualValue! + } +} + +/// A Nimble matcher allowing comparison of collection with optional type +public func equal(_ expectedValue: [T?]) -> NonNilMatcherFunc<[T?]> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + if let actualValue = try actualExpression.evaluate() { + if expectedValue.count != actualValue.count { + return false + } + + for (index, item) in actualValue.enumerated() { + let otherItem = expectedValue[index] + if item == nil && otherItem == nil { + continue + } else if item == nil && otherItem != nil { + return false + } else if item != nil && otherItem == nil { + return false + } else if item! != otherItem! { + return false + } + } + + return true + } else { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + + return false + } +} + +/// A Nimble matcher that succeeds when the actual set is equal to the expected set. +public func equal(_ expectedValue: Set?) -> NonNilMatcherFunc> { + 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?) -> NonNilMatcherFunc> { + 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) -> NonNilMatcherFunc> { + return NonNilMatcherFunc { actualExpression, failureMessage in + failureMessage.postfixMessage = "equal <\(stringify(expectedValue))>" + + if let expectedValue = expectedValue { + if let actualValue = try actualExpression.evaluate() { + failureMessage.actualValue = "<\(stringify(actualValue))>" + + if expectedValue == actualValue { + return true + } + + let missing = expectedValue.subtracting(actualValue) + if missing.count > 0 { + failureMessage.postfixActual += ", missing <\(stringify(missing))>" + } + + let extra = actualValue.subtracting(expectedValue) + if extra.count > 0 { + failureMessage.postfixActual += ", extra <\(stringify(extra))>" + } + } + } else { + failureMessage.postfixActual = " (use beNil() to match nils)" + } + + return false + } +} + +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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift new file mode 100644 index 0000000..5b24af2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/HaveCount.swift @@ -0,0 +1,57 @@ +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) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + 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 + } + } +} + +/// A Nimble matcher that succeeds when the actual collection's count equals +/// the expected value +public func haveCount(_ expectedValue: Int) -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + if let actualValue = try actualExpression.evaluate() { + 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 _runtime(_ObjC) +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Match.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/Match.swift new file mode 100644 index 0000000..7e80331 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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?) -> NonNilMatcherFunc { + return NonNilMatcherFunc { 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 + } +} + +#if _runtime(_ObjC) + +extension NMBObjCMatcher { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift new file mode 100644 index 0000000..2092cb6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatchError.swift @@ -0,0 +1,26 @@ +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 comparision by _domain and _code. +public func matchError(_ error: T) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, error: error) + return errorMatchesNonNilFieldsOrClosure(actualError, error: error) + } +} + +/// A Nimble matcher that succeeds when the actual expression evaluates to an +/// error of the specified type +public func matchError(_ errorType: T.Type) -> NonNilMatcherFunc { + return NonNilMatcherFunc { actualExpression, failureMessage in + let actualError: Error? = try actualExpression.evaluate() + + setFailureMessageForError(failureMessage, postfixMessageVerb: "match", actualError: actualError, errorType: errorType) + return errorMatchesNonNilFieldsOrClosure(actualError, errorType: errorType) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift new file mode 100644 index 0000000..02d3245 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherFunc.swift @@ -0,0 +1,69 @@ +/// 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 recieved 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. +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) + } +} + +/// 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. +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 + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift new file mode 100644 index 0000000..3f27ec1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/MatcherProtocols.swift @@ -0,0 +1,153 @@ +import Foundation +// `CGFloat` is in Foundation (swift-corelibs-foundation) on Linux. +#if _runtime(_ObjC) + import CoreGraphics +#endif + +/// Implement this protocol to implement a custom matcher for Swift +public protocol Matcher { + associatedtype ValueType + func matches(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool + func doesNotMatch(_ actualExpression: Expression, failureMessage: FailureMessage) throws -> Bool +} + +#if _runtime(_ObjC) +/// 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 + +#if _runtime(_ObjC) +/// Protocol for types that support contain() matcher. +@objc public protocol NMBContainer { + @objc(containsObject:) + func contains(_ anObject: Any) -> Bool +} + +// 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 +#else +public protocol NMBContainer { + func contains(_ anObject: Any) -> Bool +} +#endif + +extension NSArray : NMBContainer {} +extension NSSet : NMBContainer {} + +#if _runtime(_ObjC) +/// Protocol for types that support only beEmpty(), haveCount() matchers +@objc public protocol NMBCollection { + var count: Int { get } +} + +extension NSHashTable : NMBCollection {} // Corelibs Foundation does not include these classes yet +extension NSMapTable : NMBCollection {} +#else +public protocol NMBCollection { + var count: Int { get } +} +#endif + +extension NSSet : NMBCollection {} +extension NSIndexSet : NMBCollection {} +extension NSDictionary : NMBCollection {} + +#if _runtime(_ObjC) +/// Protocol for types that support beginWith(), endWith(), beEmpty() matchers +@objc public protocol NMBOrderedCollection: NMBCollection { + @objc(objectAtIndex:) + func object(at index: Int) -> Any +} +#else +public protocol NMBOrderedCollection: NMBCollection { + func object(at index: Int) -> Any +} +#endif + +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 _runtime(_ObjC) +@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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift new file mode 100644 index 0000000..ac8ee5a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/PostNotification.swift @@ -0,0 +1,70 @@ +import Foundation + +internal class NotificationCollector { + private(set) var observedNotifications: [Notification] + private let notificationCenter: NotificationCenter + #if _runtime(_ObjC) + private var token: AnyObject? + #else + private var token: NSObjectProtocol? + #endif + + required init(notificationCenter: NotificationCenter) { + self.notificationCenter = notificationCenter + self.observedNotifications = [] + } + + func startObserving() { + self.token = self.notificationCenter.addObserver(forName: nil, object: nil, queue: nil) { [weak self] n in + // linux-swift gets confused by .append(n) + self?.observedNotifications.append(n) + } + } + + deinit { + #if _runtime(_ObjC) + 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() + +let notificationCenterDefault = NotificationCenter.default + +public func postNotifications( + _ notificationsMatcher: T, + fromNotificationCenter center: NotificationCenter = notificationCenterDefault) + -> MatcherFunc + where T: Matcher, T.ValueType == [Notification] +{ + let _ = mainThread // Force lazy-loading of this value + let collector = NotificationCollector(notificationCenter: center) + collector.startObserving() + var once: Bool = false + return MatcherFunc { 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift new file mode 100644 index 0000000..2867a1b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/RaisesException.swift @@ -0,0 +1,183 @@ +import Foundation + +// This matcher requires the Objective-C, and being built by Xcode rather than the Swift Package Manager +#if _runtime(_ObjC) && !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) -> MatcherFunc { + return MatcherFunc { 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) + } +} + +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 let _ = closure { + failureMessage.postfixMessage += " that satisfies block" + } + if named == nil && reason == nil && userInfo == nil && closure == nil { + failureMessage.postfixMessage = "raise any exception" + } + + if let exception = exception { + 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 + } + + 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) + } + + public func doesNotMatch(_ actualBlock: @escaping () -> NSObject!, failureMessage: FailureMessage, location: SourceLocation) -> Bool { + return !matches(actualBlock, failureMessage: failureMessage, location: location) + } + + public var named: (_ name: String) -> NMBObjCRaiseExceptionMatcher { + return ({ name in + return NMBObjCRaiseExceptionMatcher( + name: name, + reason: self._reason, + userInfo: self._userInfo, + block: self._block + ) + }) + } + + public var reason: (_ reason: String?) -> NMBObjCRaiseExceptionMatcher { + return ({ reason in + return NMBObjCRaiseExceptionMatcher( + name: self._name, + reason: reason, + userInfo: self._userInfo, + block: self._block + ) + }) + } + + public var userInfo: (_ userInfo: NSDictionary?) -> NMBObjCRaiseExceptionMatcher { + return ({ userInfo in + return NMBObjCRaiseExceptionMatcher( + name: self._name, + reason: self._reason, + userInfo: userInfo, + block: self._block + ) + }) + } + + 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 { + public class func raiseExceptionMatcher() -> NMBObjCRaiseExceptionMatcher { + return NMBObjCRaiseExceptionMatcher(name: nil, reason: nil, userInfo: nil, block: nil) + } +} +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift new file mode 100644 index 0000000..6cef4c2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/SatisfyAnyOf.swift @@ -0,0 +1,62 @@ +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...) -> NonNilMatcherFunc + where U: Matcher, U.ValueType == T { + return satisfyAnyOf(matchers) +} + +internal func satisfyAnyOf(_ matchers: [U]) -> NonNilMatcherFunc + 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 + } +} + +public func || (left: NonNilMatcherFunc, right: NonNilMatcherFunc) -> NonNilMatcherFunc { + return satisfyAnyOf(left, right) +} + +public func || (left: MatcherFunc, right: MatcherFunc) -> NonNilMatcherFunc { + return satisfyAnyOf(left, right) +} + +#if _runtime(_ObjC) +extension NMBObjCMatcher { + public class func satisfyAnyOfMatcher(_ matchers: [NMBObjCMatcher]) -> NMBObjCMatcher { + return NMBObjCMatcher(canMatchNil: false) { actualExpression, failureMessage in + if matchers.isEmpty { + failureMessage.stringValue = "satisfyAnyOf must be called with at least one matcher" + return false + } + + var elementEvaluators = [NonNilMatcherFunc]() + for matcher in matchers { + let elementEvaluator: (Expression, FailureMessage) -> Bool = { + expression, failureMessage in + return matcher.matches({try! expression.evaluate()}, failureMessage: failureMessage, location: actualExpression.location) + } + + elementEvaluators.append(NonNilMatcherFunc(elementEvaluator)) + } + + return try! satisfyAnyOf(elementEvaluators).matches(actualExpression, failureMessage: failureMessage) + } + } +} +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift new file mode 100644 index 0000000..c847a1a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowAssertion.swift @@ -0,0 +1,55 @@ +import Foundation + +public func throwAssertion() -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + #if arch(x86_64) && _runtime(_ObjC) && !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 _runtime(_ObjC) conditional statement") + #endif + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift new file mode 100644 index 0000000..151eb9a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Matchers/ThrowError.swift @@ -0,0 +1,53 @@ +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 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? = nil, + errorType: T.Type? = nil, + closure: ((T) -> Void)? = nil) -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, error: error, errorType: errorType, closure: closure) + return errorMatchesNonNilFieldsOrClosure(actualError, error: error, errorType: errorType, closure: closure) + } +} + +/// 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: ((Error) -> Void)? = nil) -> MatcherFunc { + return MatcherFunc { actualExpression, failureMessage in + + var actualError: Error? + do { + _ = try actualExpression.evaluate() + } catch let catchedError { + actualError = catchedError + } + + setFailureMessageForError(failureMessage, actualError: actualError, closure: closure) + return errorMatchesNonNilFieldsOrClosure(actualError, closure: closure) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h new file mode 100644 index 0000000..790d16d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Nimble.h @@ -0,0 +1,14 @@ +#import +#import "NMBExceptionCapture.h" +#import "NMBStringify.h" +#import "DSL.h" + +#import "CwlCatchException.h" +#import "CwlCatchBadInstruction.h" + +#if !TARGET_OS_TV + #import "mach_excServer.h" +#endif + +FOUNDATION_EXPORT double NimbleVersionNumber; +FOUNDATION_EXPORT const unsigned char NimbleVersionString[]; diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift new file mode 100644 index 0000000..943fd30 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Async.swift @@ -0,0 +1,361 @@ +import CoreFoundation +import Dispatch +import Foundation + +#if !_runtime(_ObjC) + 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? = nil + init() { } + + func acquireWaitingLock(_ fnName: String, file: FileString, line: UInt) { + let info = WaitingInfo(name: fnName, file: file, lineNumber: line) + #if _runtime(_ObjC) + 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) + } + + /// 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 recieved 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. + trigger.timeoutSource.scheduleOneshot( + deadline: DispatchTime.now() + timeoutInterval, + leeway: timeoutLeeway) + 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 _runtime(_ObjC) + 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 undesireable 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.suspend() + 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( + _ 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 + nimblePrecondition( + completionCount < 2, + "InvalidNimbleAPIUsage", + "Done closure's was called multiple times. waitUntil(..) expects its " + + "completion closure to only be called once.") + if promise.resolveResult(.completed($0)) { + CFRunLoopStop(CFRunLoopGetMain()) + } + } + } + + 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))) + asyncSource.scheduleRepeating(deadline: .now(), interval: interval, leeway: pollLeeway) + 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 + do { + if try expression() { + return true + } + return nil + } catch let error { + throw error + } + }.timeout(timeoutInterval, forcefullyAbortTimeout: timeoutInterval / 2.0).wait(fnName, file: file, line: line) + + return result +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift new file mode 100644 index 0000000..f376505 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Errors.swift @@ -0,0 +1,141 @@ +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 { + if let error = error as? CustomDebugStringConvertible { + failureMessage.postfixMessage += " <\(error.debugDescription)>" + } else { + failureMessage.postfixMessage += " <\(error)>" + } + } else if errorType != nil || closure != nil { + failureMessage.postfixMessage += " from type <\(T.self)>" + } + if let _ = closure { + 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 +} + +internal func errorMatchesExpectedError( + _ actualError: Error, + expectedError: T) -> Bool + where T: Equatable { + if let actualError = actualError as? T { + return actualError == expectedError + } + return false +} + +internal func errorMatchesNonNilFieldsOrClosure( + _ actualError: Error?, + error: T? = nil, + errorType: T.Type? = nil, + closure: ((T) -> Void)? = nil) -> Bool { + var matches = false + + if let actualError = actualError { + matches = true + + if let error = error { + if !errorMatchesExpectedError(actualError, expectedError: error) { + matches = false + } + } + if let actualError = actualError as? T { + if let closure = closure { + let assertions = gatherFailingExpectations { + closure(actualError as T) + } + let messages = assertions.map { $0.message } + if messages.count > 0 { + matches = false + } + } + } else if errorType != nil { + 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 +} + +// Non-generic + +internal func setFailureMessageForError( + _ failureMessage: FailureMessage, + actualError: Error?, + closure: ((Error) -> Void)?) { + failureMessage.postfixMessage = "throw error" + + if let _ = closure { + failureMessage.postfixMessage += " that satisfies block" + } else { + failureMessage.postfixMessage = "throw any error" + } + + if let actualError = actualError { + failureMessage.actualValue = "<\(actualError)>" + } else { + failureMessage.actualValue = "no error" + } +} + +internal func errorMatchesNonNilFieldsOrClosure( + _ actualError: Error?, + closure: ((Error) -> Void)?) -> Bool { + var matches = false + + if let actualError = 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 +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Functional.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Functional.swift new file mode 100644 index 0000000..6c5126a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/SourceLocation.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/SourceLocation.swift new file mode 100644 index 0000000..4e37aef --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Stringers.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/Nimble/Utils/Stringers.swift new file mode 100644 index 0000000..8a15c4c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) +@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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h new file mode 100644 index 0000000..5d416e4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/CurrentTestCaseTracker.h @@ -0,0 +1,9 @@ +#import +#import + +SWIFT_CLASS("_TtC6Nimble22CurrentTestCaseTracker") +@interface CurrentTestCaseTracker : NSObject ++ (CurrentTestCaseTracker *)sharedInstance; +@end + +@interface CurrentTestCaseTracker (Register) @end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h new file mode 100644 index 0000000..2089607 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.h @@ -0,0 +1,381 @@ +#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)(), NSString *file, NSUInteger line) { \ + return NMB_expect(^id { return EXPR; }, file, line); \ + } + + NIMBLE_EXPORT NIMBLE_OVERLOADABLE + NMBExpectation *NMB_expect(id(^actualBlock)(), 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)(), 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(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 + +// 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m new file mode 100644 index 0000000..31ff810 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/DSL.m @@ -0,0 +1,160 @@ +#import +#import + +SWIFT_CLASS("_TtC6Nimble7NMBWait") +@interface NMBWait : NSObject + ++ (void)untilTimeout:(NSTimeInterval)timeout file:(NSString *)file line:(NSUInteger)line action:(void(^)())action; ++ (void)untilFile:(NSString *)file line:(NSUInteger)line action:(void(^)())action; + +@end + + +NS_ASSUME_NONNULL_BEGIN + + +NIMBLE_EXPORT NIMBLE_OVERLOADABLE NMBExpectation *__nonnull NMB_expect(id __nullable(^actualBlock)(), NSString *__nonnull file, NSUInteger line) { + return [[NMBExpectation alloc] initWithActualBlock:actualBlock + negative:NO + file:file + line:line]; +} + +NIMBLE_EXPORT NMBExpectation *NMB_expectAction(void(^actualBlock)(), 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 NMBObjCRaiseExceptionMatcher *NMB_raiseException() { + return [NMBObjCMatcher raiseExceptionMatcher]; +} + +NIMBLE_EXPORT NMBWaitUntilTimeoutBlock NMB_waitUntilTimeoutBuilder(NSString *file, NSUInteger line) { + return ^(NSTimeInterval timeout, void (^action)(void (^)(void))) { + [NMBWait untilTimeout:timeout file:file line:line action:action]; + }; +} + +NIMBLE_EXPORT NMBWaitUntilBlock NMB_waitUntilBuilder(NSString *file, NSUInteger line) { + return ^(void (^action)(void (^)(void))) { + [NMBWait untilFile:file line:line action:action]; + }; +} + +NS_ASSUME_NONNULL_END diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.h new file mode 100644 index 0000000..d2a54d2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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)())finally; +- (void)tryBlock:(__attribute__((noescape)) void(^ _Nonnull)())unsafeBlock NS_SWIFT_NAME(tryBlock(_:)); + +@end + +typedef void(^NMBSourceCallbackBlock)(BOOL successful); diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBExceptionCapture.m new file mode 100644 index 0000000..0a882b7 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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)(); +@end + +@implementation NMBExceptionCapture + +- (nonnull instancetype)initWithHandler:(void(^ _Nullable)(NSException * _Nonnull))handler finally:(void(^ _Nullable)())finally { + self = [super init]; + if (self) { + self.handler = handler; + self.finally = finally; + } + return self; +} + +- (void)tryBlock:(void(^ _Nonnull)())unsafeBlock { + @try { + unsafeBlock(); + } + @catch (NSException *exception) { + if (self.handler) { + self.handler(exception); + } + } + @finally { + if (self.finally) { + self.finally(); + } + } +} + +@end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.h new file mode 100644 index 0000000..e5d5ddd --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 value 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m new file mode 100644 index 0000000..329d39a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/NMBStringify.m @@ -0,0 +1,6 @@ +#import "NMBStringify.h" +#import + +NSString *_Nonnull NMBStringify(id _Nullable anyObject) { + return [NMBStringer stringify:anyObject]; +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Sources/NimbleObjectiveC/XCTestObservationCenter+Register.m new file mode 100644 index 0000000..35f26fd --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/LinuxMain.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/LinuxMain.swift new file mode 100644 index 0000000..16c6953 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift new file mode 100644 index 0000000..cafa67e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/AsynchronousTest.swift @@ -0,0 +1,222 @@ +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), + ("testWaitUntilPositiveMatches", testWaitUntilPositiveMatches), + ("testToEventuallyWithCustomDefaultTimeout", testToEventuallyWithCustomDefaultTimeout), + ("testWaitUntilTimesOutIfNotCalled", testWaitUntilTimesOutIfNotCalled), + ("testWaitUntilTimesOutWhenExceedingItsTime", testWaitUntilTimesOutWhenExceedingItsTime), + ("testWaitUntilNegativeMatches", testWaitUntilNegativeMatches), + ("testWaitUntilDetectsStalledMainThreadActivity", testWaitUntilDetectsStalledMainThreadActivity), + ("testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed", testCombiningAsyncWaitUntilAndToEventuallyIsNotAllowed), + ("testWaitUntilErrorsIfDoneIsCalledMultipleTimes", testWaitUntilErrorsIfDoneIsCalledMultipleTimes), + ("testWaitUntilMustBeInMainThread", testWaitUntilMustBeInMainThread), + ("testToEventuallyMustBeInMainThread", testToEventuallyMustBeInMainThread), + ] + } + + 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("expected to eventually equal <1>, got an unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.toEventually(equal(1)) + } + failsWithErrorMessage("expected to eventually not equal <0>, got an 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 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() { +#if !SWIFT_PACKAGE + waitUntil { done in + deferToMainQueue { + done() + expect { + done() + }.to(raiseException(named: "InvalidNimbleAPIUsage")) + } + } +#endif + } + + 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 + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/ObjectWithLazyProperty.swift new file mode 100644 index 0000000..26e5a98 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/XCTestCaseProvider.swift new file mode 100644 index 0000000..40d9760 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 where Self: XCTestCaseProviderStatic { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift new file mode 100644 index 0000000..bb552ef --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Helpers/utils.swift @@ -0,0 +1,98 @@ +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 { + lastFailure = assertion + if assertion.message.stringValue == msg { + 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 { + message = "expected failure message, but got none" + } + 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() + } + } + +public class NimbleHelper: NSObject { + 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) + } + + 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) + } + + 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) + } +} + +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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Info.plist new file mode 100644 index 0000000..6d32c15 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/LinuxSupport.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/LinuxSupport.swift new file mode 100644 index 0000000..03ff8e1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/AllPassTest.swift new file mode 100644 index 0000000..2050881 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift new file mode 100644 index 0000000..ea16913 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAKindOfTest.swift @@ -0,0 +1,89 @@ +import Foundation +import XCTest +import Nimble + +fileprivate class TestNull: NSNull {} +fileprivate protocol TestProtocol {} +fileprivate class TestClassConformingToProtocol: TestProtocol {} +fileprivate 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 _runtime(_ObjC) + +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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift new file mode 100644 index 0000000..0660a75 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeAnInstanceOfTest.swift @@ -0,0 +1,79 @@ +import Foundation +import XCTest +import Nimble + +fileprivate protocol TestProtocol {} +fileprivate class TestClassConformingToProtocol: TestProtocol {} +fileprivate 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 _runtime(_ObjC) + 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 NSNumber, got <\(numberTypeName) instance>") { + expect(NSNumber(value:1)).toNot(beAnInstanceOf(NSNumber.self)) + } + } + + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeCloseToTest.swift new file mode 100644 index 0000000..7a7e508 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 be close to <1.2001> (within 1), got <1.2>") { + expect(CGFloat(1.2)).to(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.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")).toNot(beCloseTo(expectedDate, within: 0.004)) + } + } + + 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.004), 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.004)) + } + } + + 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.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")) ≈ (expectedDate, 0.006) + } + failsWithErrorMessage("expected to 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")) == (expectedDate, 0.006) + } + } + + 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.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")) ≈ expectedDate ± 0.006 + } + failsWithErrorMessage("expected to 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")) == expectedDate ± 0.006 + } + } + + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeEmptyTest.swift new file mode 100644 index 0000000..7c4abf3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift new file mode 100644 index 0000000..beec4d7 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanOrEqualToTest.swift @@ -0,0 +1,50 @@ +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 _runtime(_ObjC) + 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) + + failsWithErrorMessage("expected to be greater than or equal to <2>, got <1>") { + expect(1) >= 2 + return + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift new file mode 100644 index 0000000..6da2c0c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeGreaterThanTest.swift @@ -0,0 +1,50 @@ +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 + failsWithErrorMessage("expected to be greater than <2>, got <1>") { + expect(1) > 2 + return + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToObjectTest.swift new file mode 100644 index 0000000..923fa76 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeIdenticalToTest.swift new file mode 100644 index 0000000..6092988 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 = NSArray(array: []) + 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(stringLiteral: "turtles"))) + #if _runtime(_ObjC) + 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 = NSArray(array: []) + let message = "expected to not be identical to \(identityAsString(value2)), got \(identityAsString(value1))" + failsWithErrorMessage(message) { + expect(value1).toNot(be(value2)) + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanOrEqualToTest.swift new file mode 100644 index 0000000..61cfec1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLessThanTest.swift new file mode 100644 index 0000000..f1c3317 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeLogicalTest.swift new file mode 100644 index 0000000..947a1b4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeNilTest.swift new file mode 100644 index 0000000..69f4185 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeVoidTest.swift new file mode 100644 index 0000000..a8eefc1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/BeginWithTest.swift new file mode 100644 index 0000000..a05707c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainElementSatisfyingTest.swift new file mode 100644 index 0000000..a9fe80e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ContainTest.swift new file mode 100644 index 0000000..93b0331 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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("bar", "b")) + } + } + + 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(["bar", "b"])) + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EndWithTest.swift new file mode 100644 index 0000000..3e19426 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift new file mode 100644 index 0000000..102e8e1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/EqualTest.swift @@ -0,0 +1,274 @@ +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 _runtime(_ObjC) + 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]?)) + } + } + + 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 _runtime(_ObjC) + 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?)) + + expect(1).toNot(equal(nil)) + } + + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/HaveCountTest.swift new file mode 100644 index 0000000..a0294c3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift new file mode 100644 index 0000000..940a214 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchErrorTest.swift @@ -0,0 +1,83 @@ +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)) + } + + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/MatchTest.swift new file mode 100644 index 0000000..a95ba56 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/PostNotificationTest.swift new file mode 100644 index 0000000..33b2ff0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift new file mode 100644 index 0000000..20461d9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/RaisesExceptionTest.swift @@ -0,0 +1,166 @@ +import XCTest +import Nimble + +#if _runtime(_ObjC) && !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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/SatisfyAnyOfTest.swift new file mode 100644 index 0000000..0bd9495 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift new file mode 100644 index 0000000..9c66fe6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowAssertionTest.swift @@ -0,0 +1,62 @@ +import Foundation +import XCTest +import Nimble + +#if _runtime(_ObjC) && !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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift new file mode 100644 index 0000000..1c7674c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/Matchers/ThrowErrorTest.swift @@ -0,0 +1,154 @@ +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))) + } + + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/SynchronousTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/SynchronousTests.swift new file mode 100644 index 0000000..eefd178 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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("expected to equal <1>, got an unexpected error thrown: <\(errorToThrow)>") { + expect { try self.doThrowError() }.to(equal(1)) + } + failsWithErrorMessage("expected to not equal <1>, got an 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/UserDescriptionTest.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/UserDescriptionTest.swift new file mode 100644 index 0000000..9bb64b6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/NimbleSpecHelper.h new file mode 100644 index 0000000..282993d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAllPassTest.m new file mode 100644 index 0000000..1146920 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 only works with NSFastEnumeration" + " (NSArray, NSSet, ...) of NSObjects, got <3>", ^{ + expect(@3).to(allPass(beLessThan(@5))); + }); + expectFailureMessage(@"allPass only works with NSFastEnumeration" + " (NSArray, NSSet, ...) of NSObjects, got <3>", ^{ + expect(@3).toNot(allPass(beLessThan(@5))); + }); +} +@end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCAsyncTest.m new file mode 100644 index 0000000..f052e74 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeAnInstanceOfTest.m new file mode 100644 index 0000000..f5fca2d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeCloseToTest.m new file mode 100644 index 0000000..c33d643 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeEmptyTest.m new file mode 100644 index 0000000..723d642 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 <{(1)}>", ^{ + expect([NSSet setWithObject:@1]).toNot(beEmpty()); + }); + expectFailureMessage(@"expected to not be empty, got <(1)>", ^{ + expect([NSIndexSet indexSetWithIndex:1]).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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalseTest.m new file mode 100644 index 0000000..5a5bce8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeFalsyTest.m new file mode 100644 index 0000000..f3f5c98 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m new file mode 100644 index 0000000..22cab3a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanOrEqualToTest.m @@ -0,0 +1,42 @@ +#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)); +} + +- (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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m new file mode 100644 index 0000000..13336d5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeGreaterThanTest.m @@ -0,0 +1,41 @@ +#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)); +} + +- (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 <0>", ^{ + expect(@0).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 <0>", ^{ + expect(0).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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeIdenticalToTest.m new file mode 100644 index 0000000..a9d9d51 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeKindOfTest.m new file mode 100644 index 0000000..7eee261 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanOrEqualToTest.m new file mode 100644 index 0000000..4a738ec --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeLessThanTest.m new file mode 100644 index 0000000..7ba38b2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeNilTest.m new file mode 100644 index 0000000..a43ee50 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTrueTest.m new file mode 100644 index 0000000..c669475 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeTruthyTest.m new file mode 100644 index 0000000..1ad7913 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCBeginWithTest.m new file mode 100644 index 0000000..5ca7be4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfying.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfying.m new file mode 100644 index 0000000..b15d6c3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainElementSatisfying.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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCContainTest.m new file mode 100644 index 0000000..92bb9f9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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(@"bar", @"b")); + }); +} + +@end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEndWithTest.m new file mode 100644 index 0000000..b960f01 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCEqualTest.m new file mode 100644 index 0000000..6c20809 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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("foo")); + }); + 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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCount.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCount.m new file mode 100644 index 0000000..31053c8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCHaveCount.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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCMatchTest.m new file mode 100644 index 0000000..2342ae4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCRaiseExceptionTest.m new file mode 100644 index 0000000..e64c2f2 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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).to(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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSatisfyAnyOfTest.m new file mode 100644 index 0000000..4c80abc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCSyncTest.m new file mode 100644 index 0000000..2aae816 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjCUserDescriptionTest.m new file mode 100644 index 0000000..ffb5407 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/Tests/NimbleTests/objc/ObjcStringersTest.m new file mode 100644 index 0000000..4ba2eae --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/script/release b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/script/release new file mode 100755 index 0000000..eb53530 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/script/release @@ -0,0 +1,186 @@ +#!/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..." + +$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/Nimble/releases/new?tag=$VERSION_TAG" + +rm ${PODSPEC}.backup diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/test b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/test new file mode 100755 index 0000000..8ea482e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Externals/Nimble/test @@ -0,0 +1,142 @@ +#!/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..." + run bundle exec pod lib lint Nimble.podspec +} + +function test_swiftpm { + if [ -d .build ]; then + run swift build --clean + fi + run swift build && swift test +} + +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 +} + +function clean { + run rm -rf ~/Library/Developer/Xcode/DerivedData\; true +} + +function help { + echo "Usage: $0 COMMANDS" + echo + echo "COMMANDS:" + echo " clean - Cleans the derived data directory of Xcode. Assumes default location" + echo " ios - Runs the tests as an iOS device" + echo " tvos - Runs the tests as an tvOS 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 " all - Runs the all tests of macos, ios and tvos" + echo " swiftpm - Runs the tests built by the Swift Package Manager" + echo " help - Displays this help" + 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 ;; + help) help ;; + esac + done + + if [ $# -eq 0 ]; then + clean + test + fi +} + +main $@ diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Gemfile b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Gemfile new file mode 100644 index 0000000..621b34e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Gemfile @@ -0,0 +1,5 @@ +source "https://rubygems.org" + +gem 'cocoapods', '~> 1.1.0.rc.2' +gem 'danger' +gem 'danger-swiftlint' diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Gemfile.lock b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Gemfile.lock new file mode 100644 index 0000000..43c1ed9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Gemfile.lock @@ -0,0 +1,113 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (2.3.4) + activesupport (4.2.7.1) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.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) + claide (1.0.1) + claide-plugins (0.9.2) + cork + nap + open4 (~> 1.3) + cocoapods (1.1.1) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.1, < 2.0) + cocoapods-core (= 1.1.1) + cocoapods-deintegrate (>= 1.0.1, < 2.0) + cocoapods-downloader (>= 1.1.2, < 2.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-stats (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.1.1, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored (~> 1.2) + escape (~> 0.0.4) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.5.1) + nap (~> 1.0) + xcodeproj (>= 1.3.3, < 2.0) + cocoapods-core (1.1.1) + activesupport (>= 4.0.2, < 5) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + cocoapods-deintegrate (1.0.1) + cocoapods-downloader (1.1.3) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.0) + cocoapods-stats (1.0.0) + cocoapods-trunk (1.1.2) + nap (>= 0.8, < 2.0) + netrc (= 0.7.8) + cocoapods-try (1.1.0) + colored (1.2) + 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.0.2) + git (1.3.0) + i18n (0.7.0) + json (1.8.3) + kramdown (1.13.2) + minitest (5.10.1) + molinillo (0.5.5) + multipart-post (2.0.0) + nanaimo (0.2.3) + nap (1.1.0) + netrc (0.7.8) + octokit (4.6.2) + sawyer (~> 0.8.0, >= 0.5.3) + open4 (1.3.4) + public_suffix (2.0.5) + 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.5) + tzinfo (1.2.2) + thread_safe (~> 0.1) + unicode-display_width (1.1.2) + xcodeproj (1.4.2) + CFPropertyList (~> 2.3.3) + activesupport (>= 3) + claide (>= 1.0.1, < 2.0) + colored (~> 1.2) + nanaimo (~> 0.2.3) + +PLATFORMS + ruby + +DEPENDENCIES + cocoapods (~> 1.1.0.rc.2) + danger + danger-swiftlint + +BUNDLED WITH + 1.13.2 diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/LICENSE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/LICENSE new file mode 100644 index 0000000..e900165 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Package.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Package.swift new file mode 100644 index 0000000..3b43f38 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Package.swift @@ -0,0 +1,33 @@ +import PackageDescription + +let package = Package( + name: "Quick", + targets: { +#if _runtime(_ObjC) + 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 !_runtime(_ObjC) + excludes.append("Sources/QuickSpecBase") +#endif + return excludes + }() +) diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.h b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Objective-C/___FILEBASENAME___.m b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/Swift/___FILEBASENAME___.swift new file mode 100644 index 0000000..ae0acbb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateIcon.icns new file mode 100644 index 0000000000000000000000000000000000000000..5cb4ae999f06c9d5b5f3152a034c65f23137821e GIT binary patch literal 529473 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%0D_YWU3_}$$FJi-@LKlix9Xblc5@0Ulz3?A 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%0Dl`^kCYc7e=RkY)F>z4{wSA zDL2C2VU;{3TDoW_Gt1=ew?d-S31*`Nc(yUPGm`RSUq>{eJF7dO&^uLkV$S&O{5@Qf zUa(=GmP9;cIb8o;M1Gtm^`dpq)Z_oY`VVGE0<{2#I^z}~?0@4Bka-m_Tz;BieLS3_6x-A)}=M(YGo1qo=Is@5!fNSWtyn16SnGob^K_Oc@25 z@3|R(3E|)+NQOGPMf#KKkOX8josJdFe);Q}MxdGq>D|va?gFIn9C};6iTv3`J-O_W zHlOk5S7*nOW#?4q|N6o4jQ|m2oc*j$fT6yAL^O_mm4{K$4{zKSt$80vQ2TMxaH_94 z+Ds-pW6%DA?`?mWedE+)VLnFG%e}z|5vy^Mqt3Sq??Xx4+v!*`-~!ydNf8k@I>r`7 z_x6s;(gJYsiq-S6`NOee>OYF}pC#X71{Pz>OgW{y*em%oI>&CJ(yVb?MzdXH z{+PrWrhyk%6?W2&4T&uuY5x9U6~RxM_`WGnj6^Zu&M7n-U>QCe3h&-9G9u+!Z&zhkrj zZ^Yg~y(sjwv5H0U{@*hxeg{}AbGubziSPfwx}6>%4n1DK2iTl`Ss-vN!i@mn#EmwM zzz?(E+5A9F4{e({2ov>wKo<<);tCjliP9e>izzL|6(^RH~1*>fu5#;DL7fAnLZiPOg}0TC8;wwt2tPdCOqZ$ zhE_!&!O>kCw&kWBuOf6kkpBSQro6wvOL4n2NGJW`h6Ikk+XhFAhQjSL4pqN6`(HXZ z<(eV}Dc5T z{aKe9f9WY!n;a2JCr3N?aS@p_}fL)YR1tgAWKRWvnjlyY#s8)Y8AO>#;&cubW&YE80pXMpCxrN z?bKm3qUtPE`Z!L9s-hnKZ|2uxM8jl++w$IDw4T(17{q|tvmIFa{ks&k*Hom_cD1|f z;N;@+NE0X#tX~R4kXqi8S5JJ^^RXal5%b^myMD^~JO6utb7wy8P|}n*->$3e?d_$N z6}EdguWt{;T`evyvRrWh`PpoCwr~oaabSsZ+%z%17I*6E|Miq~M(kM3Jw#pK0a!HK zUfGe`%1*wm_ynevzvRO*VpCF5ej#AEMKsYVdx=CM$zhm4U7T{Zt}_1AX4)8_5^vV4 zsw+d|VeZPm1-Rwm^$Z`r-7bu1c>wCT>0bs#sFjwL9lQic;Tv^Bjt>tXg^P)bPH>)r zx$a$#s#_GLl`~;4+1vf<4Z1ZmzWPp9Rt7~Er zARl1V0d8dnz7DEzn^&{^TR^VisX@NwroX%Q=FG0|6Y2X;LL>vhM1#q!^zX=|vv4_( zQZ=1||3V+E@RUOcurdod`4LAI@I*S$FOv*=uGp(6kUatC#J!dE_uBly5hH4>A>o$m zbi@w*)*W;M;*!5EQ}o!6>O2HF+6nC@LCAp(H8A{5%_%$WRI6*SA>p4=VG+G_JERW$ zad0hwtQO(K(&UQ!`QimZ+MBI^nJJG9f}c^zPz!PHKVUOQ$LMb&*K_;S^&-m1;pM+j zO-L3y)yO#~lRw79k6~cQ@AO1YP~~4rQ(i`ZCinMkdT1}ro1w|;KFoGHb^MIf`RwE! zAPYC}*-G@(ge|bV4@p?VncVv)X8VtpOEI>jaBg3MaR_X*09(VYFkP&x!@OJTCq}1) zE+S!nw~2yI6PL2%^N+Ba%O7s+pn`EDpbd-mTO^-)SCYF%6uy5=PEGU%MX=td5K8c) z>b$p?;7|8y`6=W6rdY1ce?j>V61LESFoZ3%&uLBnpB??P1Rf;*wQh=CWDdpc1=pca&}~c^WM?cHAn9aZ71d7DI{i8nK=0 zbc(6*H)lfozU54D+fG-xnmLGFZ^oZ7UytkJS{g5!gp;;1m;qK02?>460L8YfDi|)n zc#7$A2cxwGJup5qIp1Hc2G%lGY67OD2hIKgG%QvcW!)(U8fE={Zzcew17eZsAOXMv zy9da>IzAS<0IGW?BA)^nVPpS+=Ks97(H>L`@Ialw%k&U$E*;aIGtPm5T@4{udwY9W zwBl`lIX*b3@c@?~5JMit`D3x(5sS>d8#tz}31R+A8Oxz}V0?+SHC36WVjs z{Yy&$I322$WjLf*JKAb638OyZ`8KWf>W2+|u(ZlC;~rIz%-WvZnZ2FekgdhJ{H3~@ zS{x>xqJikZ{-Q4nul@upTg+YHLnKZH~OvuyhbU0o8BPqGTtRH zI~5ek^eCaO;f*)->DW)P+Q#|-Jw69J9^${?xMfozn=WGe3f+x0d>2)^XTlNEDrm+d zj#p1s9P39n02mHX0*TT|6z| z*2J@Fk-t{#+7jZDmILQ-zr!On9}aVivnA`-vLqZ=TXi^=Ra_uBAC5=b>LC(fP$)F z&l4(~%=yvZ6`v{k{xzKC>qTDP`Cb$UkmckeE5wT^BV@3 z)P02Pm#<7>H>tu!>Y^GRexuh{_-%Yy_p%jKRQi5G`(q|K!r0gOX$oHC_bi3+e?=7h z^8WMM*3J@L*}omqOtU1e;dG{)TOnIc`YAx4=PH>?Fq)`482uHPtqFJ@aTf>gU#tAb z?*d?L4qB8S=pEJ~u^&waFo_Ny#9puXBcGwg{$DTq13!1L-zFezux8BGwbUngV_iod zj}+o!#CIC z=Sqn%9w@&Mq`k~ubY=aH=rDDpE;8w$xnKHp$KzjuccFNV$_T}z-3&%R>icmy%)~tSUDhyw z;Zo-ZVLZ@?@{Y`J`Q7Cg(Opudn1;_Nv$xWgLBtR*8-a9H^&r@j zVM>r^!u}!*^@%HvPuncI?4F(b7{TY@*s0Mm2(#_yi@%05qR!6?kXtGfAu zUDkN`iM5y3G7T5CQuOi^TnOA&a}J21@7(}VV{U4v^qhXhvZI?`xnCYfI~r`)H#B8o z)UOWHD~nf4O+GT?NvK`&-_)sBY$@ECQ#>lMYg6)HPsSuV>+72&YApJMzqy}W&M_l4 zzd2g3rmJ@FfnfLUlKqum-6jb6vd#2^UtTJ2Yv#)zC%W1fxgNoznVfrc+GhoN9&V8O z>4k@=>R~F0|GLjLZ?X1EFJLf;Dqx#ofVhWo_63l`hu&DbukDwSA){P!o#W;4eZ)p< zQ+<7^J`_swW8B@}WilOr=+R7h^YPXsgWR`fpM+c9mjMYNxUsfr>Fy0V0$QIrY(PUr zBSW7N*e)rg=rQkoH1vz|yLuRO=Pg0Z&FqCR%)za_sbY84px9pXF@n3NkgeGq{2YmP z@KtM7>9L2*%YpXo*N>9z|IaJh!NcJK%=VSI$w7&LOg(oTxbt<}QiVdQdTm>G-&*YOBhoCQZA>V)f(wt->tZ1-GP!ZdAJOj)JMyfMe_70G~4>T^#lZ*|$ibVx7 z%joX28(SLzuSR8mzrRYlyYg8$T3Ye}ruq3@ncYqI^alYUJ|1%hFP6Z|^flT*9md*C z{3nQ+Jm%S)oI0X#=zNpj&Uk#hj={Y!DNX`6o~&NsKQUiGC!_S$)U7eL^VvLXEK+yA zrLSPbP7op?he5!vq)v~w^&a3n`SIn|yCOCfkF5+i zT`C;$>Wz;fawYc=CD(JY(rmORJADyzE$zP5 z^>gbRTQY(NbcVX@>)U=6@Od=^#hQd#9xH>gLz{gvE)@uCCwPEf7Fi!?)unvUca9f9 zh#$-J?Qb#<4!(MfWwnccTOc7m#;AUokzF171LfXP02teZB<16_gEjA~ok2sDak8ID zrc8%uuQHlS_8$T4Hyk+um*`FiTkPlwn(4fbY1cLd@2u|rR;}^VUg`K$?^ySsB0mCP z55AJD%7W(V#KgoaUd+t`wH|4|{k*mqU_c$*S1jZc22By!)}YJo?QH`%5)vA(W^Atw4JQuXI0 zYPREMZqa7<_RO}+N*0PK3@5=GaXzy%w2)kB#3fr76GT7@P98eiI<(nuC4s0)U7=e+ zkRA2*d5ENBq;PBN63Y;Hzdz!n2_8*k>>79-In1?_&e6>@7n~TFVUtYZ5J3uT3`cs$ z)1the+w1m#y_1|2sVhOFlCWP;_*QsVcnp{RdKb|tJ3Zn@eTVE>HBjaz;D^S2%TvfH z_2(CEG^LoXXVkWrQy!8pDBry{ulWsAc533E8e6#&ed41T_}lD`&X)!c>I(f$G7y>; z6hw;Xe$|G1iXaLH_p*yLYV(%yvZI>e>6rcHq;<}s}qEL zUX;zZ?kL6EM$3;lQme}Tm?{^76ybFZzgO0ko}k(n1hliNHC)D%Ebyv$wa>FlS`o+* zcT0a5B2)BBpt^~GETxZrro>ekIgfd`7FbpGjO8m%fMc-9tB4jcg0{`P^BGF4%Ll0S z3qP`}3%dtAd)0Z<-!;bfb()vO*m;~g^Um|TxkP7Yt4*$ z{jqt_-B%#0!=oEVOtZJ{RxnM*xKhV@Ej&5yCc)`k&=#>$LT0}_UDD22((tXj^@{MF z$Y<{T&p!IytozYLjdjBq4uBXny~)GMZbIiIV_E#U$AE8nk=DQgf8(78AP@bXed1Ui zRsao<;&e6R$Ac^#LWk~~d6Px&Q1yLwq|(Mj$3Iu!L3R`pfM$ny5|*>ot`K*wM3w)j z|H*rQugsHCyIQQ1&jVx{t`oFP!QAn{i)PvnRPpqO2GR}jE~veZ7%Jq}Ur-9>D)MOO z%-V=G3HTQBGQ+8Jop^D|wCCng>(V1P#HD-mW!Z;qChki0%c)+3#f8H$h9FN-p}&^s*yb8$0;m;8a`#OVe1yK|-VuE874yw7p>y7z4#!Wf#CA#rJ6#H)}j&5g7c~+<5x?;rGT9J!rfy z)>uYh9b}`3kg~`YdPW8yZ*7Q^Er8(Ef{k9KQAvy?liHn{6Oa$eep#ya^)AkmHP2q5 z;!%`A4;$T+tZ#*RtCol}kn~OenttOZ0ep(1Q30Lm`;427++ViZJeBE|503Az|{pC+V>WO=wQheT7X#E|I| z$z~^G1l@RNhzB^H@TQQ0(MxOuJAPN7Kp2P&1Y{Vf{M3W{s=Q9$wYmq`W10(5@)I-W zL9na!Uffd@OH}zFX8I#vzeQcd4uzvV!EMZ{pCQS6RMmUQO72M2V^o*!l$Al80Ki9? z1j&v(ejMq3|2R{^=+}aPt+yg|+(rDSufrbR5dZ=gWVh@XM-w-&8NwHiutxC$d2-FxSFz_V>g`gV# zQ@We2A8GI6wY}t}07COK`o6rWp_f)JsAT1`>YnQ0Ebf^n4}AT-MRXh=;-e;7_#6FU z-u+gH%A$HY`wqs^X&}Wu?$ljl-<`Sel$!PpRzT<(?SE6@F=k@YcL5(*BcV$f zYVih50trD^Q?>TP8O`z=oSO%$NL_lxQ%>3iY{AXEey@^LX(DmzU0%`9USf#^;-`wV zR_p8QT@W9UEKDNQS55SD*4gDSQaHZB?p>ull$Q+~nbCcbqqy}hsEkDX_fqG(-=qbZ zq4c}9kqe)YWXPrQ!f(sS zq8Af0I6#~WoQKKb#adUYJL`wP73P1=`|&RB zm%D3*ui6|V&3<>MWSzYQk+jxH|+0?hXMG+}+*X-QC^Y2|YdvfAz9AwY4S)yF9&lU1jzfm~<5X?^mM*h% ze8!z15gD&vN^})Zum8*VjGdsn(G5dR<1_2%sP{@0bkMu0px$zFa3oxv?4x>)Y``oN z#0tpMy4jj0kjKtbr5VY85B|DC&tlu_?y1?kod%vZ@Jz<3-!88AOem-AL!rkAqU z{qZCYrh-ND2O-iR8%W0RV&0}tXXx4gmLD7NEG@gC?Z-CC1>x%cu&2gdz$%`;+XLP| zs{YB=X9fFT!GZ>QkQz(94iO+)0wXB4By~_^i`6aeln+O;-8qsD2CDir2UjAC{EaC~ z^ZTi4ZUvlXz?@9Lz8b;tN@C*626(RYty+Z4g$#0bx_*O$vr#8$;y7V~<5&xv8-ZAb_7czU(OZ z8;3tg5?)cjW{km~^ZuLW--zn{u0BH~-z?#LfMsVK4m4*I8o=2c)r1O=|7j^e^t0|c0cOU?|NoOwA(AgVGW5X3l+S|<_DGn< zgUK1%?gAJ}0o6FLCmHo%nSeI#z4+&zdX_!^-TP_W$%Z<0KsW``gY9C-T0uQ<7>(xV zjo^2^ybVQxZ9;kAUQYml?1u?^!SVT(3E;*Mbeo!TXtet@(?!$U_;^cL^>=+w9BGdq z(t`G}Rj9kYAjvIzyj;_Lf~7_Jk@70eNs)dkD<1~JK}TC-?wC_cefco^z58slmqzS} z`->&i@1s?*N@AU;pe=+hg<2`0F+}0N?fDO9^GvX8>0$U&r*wS%MXIES?l0l;*_O^@ z>(PIB(-rd-6lZL%(l7aC_3T|VVm41Y>TsQSMOv{buBE`UFKLhbhr!#n8-~9E1U=Hp z5hXy+?#JXZ9ejJ8u*V^W_slei+q$n5V)H0O-S5el7;#!r)B|si0emoO{F966!w4Or z^DrPVd|(5aFeIUOzj}>az|}sK2hBxQu@{6nv9G8R4(cKT^ybQl7o|t4gXvGi52ahi zt&|jr$JXcp!|t|8v6JQ%Op%S>zHpsuaQAwkq1qUR5~2;}PtKvBYK%P??2aHtls4*m z?$eobT}^<+n4&GJ5@=dF8}OBDTdQ(sU$;<7fBxO0{Y{=bLuUV$V6~01Ag|ZfgvFH_ zPy#(V8>jn}xJDvnmfyfZMsq*6P?X=9vv=#`dwC_m0*I&I-RAv=SWq8rsGt;A7=CEJf-;m?vL}XBQ}Gni zjb&*datwfDKX}%3)hkgI8vf|VZQVDkYI)$O;^)OpmOfSc1_$0&O`0v#+j68;aC=Oe zyCPisCOod?S_B??!x_uKZAZuVrnoC8)$Z2mtcNE)Hb7b}>p3E$&)Lr0Ir~euh*Fxd z@~2x=<8*Z2fNMIXA!iE?DEoj=O-;d(D^OK-Nvu4lr`_5URG1Kf-@^_%!YBlL)aU@L z5l+USaf#pi7q3X{Iyk6zoMGRl?Z7bn=lOY+fNNqZhvkU7iL8U8E^q}}zQ7`{)<`xP z3j?c+@+=+1FO#k#+^y=XxCuivh>uS%27(z6aDSE^aW&0AJPIW3?J@fAEG#B8pb2X) z5CJm`z!d61dvMV=MiuaEMw$j_Lkw~%-isua1!UO1uq*4W;{|7m2+b6p*2LGlH#ve` z%r_57#+eQYBbk8EINQTKh4chWU8qGBRH0q6Be0DnXuSWiSQC&g7PRMvC#Q-UmhC0Q z1*KG#hA>!8+}~$k=v^(~)Reb|!&Ph!D} z2qAVW!HI23Sx}b0gs>KY%?NusKGJ2j9x87dC!P8J+FJ?Wold~SLp zc4RPVN2j?doW2ir5LqaYCQ{XN%8Ru>d_vyMmlg#wRdrDOeVEbt)_ zs1+Jhy#=~Jiw_aPxthzBoX&n7&cEkWJ^_0}O6;HgD+r&D4q{?n8FlaM?_5KEBOHWe zkS9Gc61NW&J;z0^UQ#xFqu-%X>5+Tv9~tgS!c?0LD^Z|V84 zuXa&+zOBzEo_LElbm@W;ozA(5{99Bh{CHoSuUJs~;t&@FoO*TR)(gS#LWX?0DeT=E zyn1GPJbVFmQR6lAJBhRarQJoF{N`ytTyaBz?Q325>{!pk2mcpQ z1aQp+UM}s@$D$u4(W@W)HF8G$5nJW&MavnQK8tT)XBpo>!5-QpMhNw>5EeFy{K=GD zA4)u`J|jxQGTLa6uEru$2a=!J(44jgcCB@gj^!q1pl7_%TDQk6Gp@qWWlWuq`9*zr z3d1Z&JIbqXI0(udV%hpvp88x@q1Q0C&2~fVhY60Luk5x=xHM@4YZc^Q{V#UfAgmpB zl7RWaWk5$F!QtwmdH@MwLvWQ$;npnsFA^#$=d~|!JcKCETO^T8y)d;sxnLdG<9q7G+;<_nITlbUx|s(C-yzvsr5Y-L&VF zoi)$Nm3Nf&`yH@$6+C6z<;z0D*@F^rCZ*K#Go|GHp~F;l#vy{6V%;s>XFZVYRm)5S zp_iBh{FZ%u*uUqoj{5mB98iBo?q5!ow`ayhwlZ8*fmCu}dWyVnz$eN7oDTUn?lga_ zV1beC+q?g=BmcH%uEa0R$!Gp+InI&ADk0Lmt?%xMGq>$H{3?Kr&7a8du_B4vKC}<_ z{DB{rZy|3-?PzQL-)EB7Wh=+wh}yMEzR*f( zQ@IBK$)0$GGmcoB3d=L(m#J;KFoU=ZoWD)z#LOW260hpTVraz)@n`!4Xv2`|Wtxyc)>wBGX86|JR-9HC^;@=lHw?Kk_IJ{Le zUduxz9eKvZUln5+Q%^yR=aWXmKTfz%A)s@^H(T$-JAskjmn%@}3KnSw&DNHHTs4a$ zHRwa|Lj&bR0wZ&#ORj)xS>#J;DuGNLc~=UP%U-l0c9U}}4n2WrGaUZ#Q;&Z^lx+=$ zrYtrB$p}V|eJJwpO^=uCjOFnV5I6EeP)BVh@&bQ`v7h{B0*dQf_~ZDxQGag)rr>|S z^qP?Z$QAv7Cn~3 z>(=DRt3Eu~=H`qZj;s15dsw{1Ro1)7mCfGy3A&inzncW+YG-SBp10Luk8+*4&hPTI zg2{&cjbxPZbrrLlR>Aw?bMTRP5Kv0v+nLXXCY|2NIoNQhW%>6?uz2>n*uew`I1Mp6 z`8%$G#a5v9=W$FW`$owF4QRWAPv^}^7Jd+dM3X9>%YN*mDk2`U7CHTlzREe&cMc^R z1}Eizv_xhH(f1v|o6kKg`d@#pZKo>Q9=ME+;Uo6)^VN^5Q1h#&C&G&%i#)w-GuA0R({JO!4_#Izh6Y1{} zGAx4t9#SWnw$_6vLBhA(5=aC7BToM40UkmuSj^C+9X|G`F~|vAJ_uNi`&1R~xw=9@ z`J%*9*ommybB_`M9)D{*&FRFYf3^xdH2bTJFIgDt{2a3Iy0h5Je|=95%=Z!KQ?|kdmpCnqkGC=uDR);Nu{{ZAUMNR&5KpOrcQv4-0F-)A zHs}M*%N2dv^%f1dDn5T4DQ!n|-D&Z@5`Rj=qscv+8Mo`fY{i;1DlfM`?)UBvKb(LCM&OrX)7nox<* z4CvDW9F(aO0%Nl^J3JEFDadfe0v)R1<*5M4cdC<9he8y!ve3s^X60}nycv>e0d2e> z{%`e-Y~i#V5`V?fM~}X|es?nz3yG(1f;6IN&3XPtI!g}$#-jGXMZ9`2q%Z(>Al`4} z6}7SJ&tJSI*p_;`b!c~MzUXar#T_Olpo#o(-H6wO&)HA-i%$ZC$`G@D{Ocz@0OH}7Y5 zLsbV>!tWQbN%%}&iagipc*HQ&Ct?PD)jC+MAZ0$sM~8Re%PjWTiA4JeT_)T$+6z(1 z?{aO3^+}aXecHADr}aTBf7CavK7P@(wN77ZKZYM4zL7!#Os~d#scxON4<`^ZL2OAk zTN!Kxv18Yp@RD!qKHyObydY2^$v=wI!7d!E@ju53jC_K>&iC}|YyCQwnbx)jxX}~rJ0ABf4pd$1x7qve@r*2Yr0gIZWJGNm zYDfnf{O+;uCJRUh>ipKmCStL2G?;7ig3gfvbz9xy2mx zb-tC+TxpP*88PD0k!#|H>D~a+a4ioHsgq72T&Cv<6EA^0o6leFstBrBo;!H%r9m~W z&{f_1Jm1;hpS`WK`-h$(IK{=xxzL%tv9S?$a8IRSIE*-Pte0I{6{dU3Ss@#$+iXUb z1S8t!Lp$CTd+V6AbL!*b;;p_jzb%qpckQ^W=48xo^dq>)l5^wO7fEoonH5Yu_TI&9 z-qbpamj4?24frl%{13#sLJU6s)8JZ@__N_;arJKa*Ffn6jq+31JyK98-vuDmcGY{A z&(686x9@sA)O(S868tXW3JF2S^CO>rD4C`GIZWciFf^l=EbLsH!>+4vw#Ma(SN$Q` zN+i2WG<4W52{#4Xfj{zA>D#f(T_sO@qhZzdvNpwett5O6A5EMNBS!|(q59rxAB2b2f3F<*GEAs7s)aU3yh4E4EMy%9FxZJei>mP4iq2|o4fQvwR*C*OY!E_ zr_*-!#7Mvd6b9n#XY*%VXPW#K_;}q<`4GSyk>uBW@LOtF$L+NgE&m>Ml;=||is0<- zKDRhuT14k6zdPF`cmu@(L+ukTA6BP*|EEv+ld5#Pn=6t>0fv|VKY8@^GK&ff&i*Zj z7cD|d;%E6uSd4O#db-}4=@d=~kd1pMM| z(L##Hr4$S?9@|eg#}rFUrorC`bf6W&8drMi4xQj++}MSTA~P`}HN-FLb_#h%QojiD zH?EHgK@E z4|n5xc;2)NTtswH0W>K0ukKV$H^VgnofhUm@2B&XqvL0-XII0D(q3t`zUBeWBJxIf zkE#Tu+nK|$B)|8`POOnT=sL>`(C)5_3;w4-;&Oavao`m>$xaELQNz>;d-LJuUb5UI z$+KFjDxXY%0$N)ae^h-h${o>(kGCz3t>7;`u6&DAF77WcDP1Gha_op~f zYoi2CCKk`u7RQr1ph!bT6V^gpQ8lIC@4x-VRwoM^w^=@U4M?|%-# zDQ!%8ETAwE@Acxu4bII;%jb0LM#`uE8}t4bY*fD+vJVhZ;sx$h;y{Q4YfK*B*cfAi z`ZdQhHg|NN!$YX9AzMV@159XCkboGt`=IxCyW1VcYqY@4OoP=z-?W!fnV?Ye>pupg zAeJ7#EWek%%zJPUES+rgF7w%`Uxjf1SAZ}3RutId|F%U3!J!IBs~4K#zNpAcXm)jU z*jw#RY)1|0-5#{`v$QNNKL;eLM|h|vsMeR;ir;T$-3P7mAaZOZkz_u?qg`|kS}ZLACBoWWuF`4Re&)`|bJRy-K8d?=!?r1y{p zuaimfpk*P9FaA*a+a}9%$3My=;L2aKeYR z7D01ybI1Es>b-~2p{5}IF=-|dbjNkRz=2ky)8;G-K$0c^-z*t6=+Ut87djz)^I`w3 z<)68dw5J6#J0yK5GjE^NBJM|4dk<%X5RBVK6UWuB{TS#vFphLN;QW_2y7sNL`wANn znfi9kfOh4rVKi$@#tEIxVW_7k*X{Sg_VW5*8*nyr1h6g?8fP?@{!Kg<6t!TO(^3l>M@c1=#PO#Vtf`?Xjd1^7jBds@TvHm4Cvg`~J+g%cvolldBKM@qvhN z4Xru(@K9cHaf68gBn~U&r_uyspZv0J(D0ik_+@ueHzHLI4mmh_k>10| zoI8d!i-~e<4`2uLvOZLhg)FWvl~hQ=^uEa|bOOu-vj;Bcn_tZ+IgF9dDSSr_zAw{9 zdgZw+31++;8339{gbYznplE@inm<&KM`zfDh{jcSCP2;R$@QtdGTpv@4S0TFiRtZ!5JhG)GpYLe#qP(# z4=}NZ4cJ#lC@Nex@eRb5dTp9}Y-`^0O_ph)XqWY-g1?R%6NntGkaf_dG4^$oxu*LQ zr|przZr+?bwf2gC`oq7PYV*#rEbCABhOnF3mTLCQxofg2HegbT-F7nW!GBt0dngX1 zjLvLeLw9A5zA~T!FP9(cH8R|Jv%izDYW5LplD7kNJNEFZo#amg+^l}Wi+&INHUX3k z#$@;+f}k|A^$>$ScLiyP@c|ZVw{ParFeJNv{F%;rPr9S!FonJjh1xew7dQHh!p{@) zMvMq`>Ce=bm<~Z}9nyM7sBgG^NQ`CoSlZ0@@UlWF$VR?C+qhhXx-xl;g_H3Til5OO zLgf4s7f!x^PpL8G#-R0!rL6gMs>1#BDF!fu+}v%l%8Lzl#yfOPg7ad649;8G?)oeC zitZ{`v3YuyXcY-8KyM;OgHJSpkL!t0fZ^rP(X2jM6s!A#%!5 z&Cys#Zf!I5gR;F=7mW+-w^zz76t*8HiY7D20_-2G1i6SoUV^icRNC_4LQ@)E7`ieF|^gS+u~Pa!h5U<2R}ZKQO2e5SH|dOUK77h$@ zq9I+}IMH^|)b)VvN%)Ywg#1=~-{u!?RZJAy+vJ=pJbgwM=oPx)7UyKxFsxCk=e2!_ zNUf_WHqS^luiI+ZhMmXk2n#~W>H?xy&hCONDCO??*#n%Tolo{tur;Rh#ecX!bB?fm zn7ZgvtMGPEe3fn1`A`yT^{9*dOH&=qqP6UDO%Cb`DM=WF(p~M|?DxupUPrb)OYZTs zyaLy3F+HFe(x*_#D~8~xRQE^zbbOP!3VF;@Sy^{z(|uBdUbBp-Z{5;-CGidAYigTz zgnq<;fQ9)?Su3WHOCG?KCF%eR@vUJE^TI}t|ITu^PjxXR7bgJbGO6f}kHZ;L{I z&zFn9nz){hvxvOD&L*?23}a2ucQn(_LSNKZlm z9Mcr~Wc{UpVwMmUW8goa^zC0%=E=Qh+s{^f%NhUc!Y{6e-+0EKx&GRq189rIF$&%X zQ#C`e=Flxop_e3jXC~H^xPM}Jfgvit3H5bxAu`Z;w*hbMvi6y@kSl^uvgWjQjs9_m zK9HP=ndat?)bX?H_ zp9DXcoWbJ|(Hhwba@z=0Gj86+j)(Lw}qO9Q-pyK)_RJ& zOcukrU6vG<^%){zL?5<(kUJwGr5aH|<;Xi##Q@v!*}D;c z-@r|EI)z@7ZX6qr_}+Cf@Dph9Hr$r4^m1;IU~%E$fkpY|R5p^s)nE5~0{Hf}9l=mD zS2@{C{1UBeacpEC*GmpPJd>FBt!>Yb&z@B;3wXB2P}S2s^Y8P0@5!A1kJNa!i(SiR zNG9+@&2jbvB~o>|A{O3+IR2o+CF9=EKu^B={bpj{vkea3@=wEHkKi<#pyfh?FaeM} ztZAW9%HcP8+1{Lu#%IPiAUvkFM>d}3%fb|^O_f|w&fNAV;onb0AGK*W;>UNtKSe9G zy886Kym$u~DtbR7P+Zc!UGYG&$mG%=zhDQM!f4`;hwc{8DSI@`^Nc(BqA9Y9=;;1$Ks0blRQfvy6E{QTz!qUC8T~%TQGSZdMB{G zoToUb44AI67^uPdS#+;DFv7jUmZ>l>B_{N);chIF6jUsl?BvoP4MF=L`^VYW^M{vu zV3z?wQv7{dqzVjjiI{Pda1SJ@00jKT3v_`%3GGl&Z6V=xNsbK*Q%>YJm)|r5R8<`Q z+KZ^Hp4UT#cI7yTR0Ov_X^r}etl+(x_kI`v7n^v)!RNOl+&{)?y30*g0^TZ!OhvI& z@_WCu0!{T7J^c6L7FNi&$RODCi@WmLkJKeh{9xkX$1JLQsyyAr)$zhwgE{>dHPt2J zhT1Pu?Vqbp61f6_0v6?0E0ipZBa@3yr_0F-h(TJvh`~bqI*YtxN7ZRheTJP30gVa| z^14K9rNFp&ma@OiL*-%@>YG-=uQL?N^wo!z9D0klGq=#Sze!m-8aQG#gytc_&nCY* zq8QOt9JiOcC+lhkc;-T#{Rhyx&tDDQt;2=#pwV}hmp7+DKhvylDtKh^g_-Pg%+b{LcYEhui!I_dm1L$qP#rCR8RFqH#3uGj&h2#twcJEo@^rFZvntFrW3B^mVrc{N6{00}PgPQ~a zANbBJ_Az1P;u!WAJMIVcDj(?fNH9XQTv`auShAZ%Sc=)tV#bkwmO9GhPAZ4pZRi@u zH1Xj2(00*QSnw-e%3Bl z4}T3$-mmn_DRWABqjHLY1O|{4uc0AqxGfY8^Q2&C8t?P+o3lhTcu~(Z5DktU6W5Ic zdgKBV&wzKx#{&1xGF=-?xii;Ub~nGBbp#VsH|kZ!pkR$$KjnYV$;)%+T5Ltz&^brU zHmBm5hVL}^H}iHqO{dfZ3%MtKtTdohL= zG^CFPZd)SloHjT^w4w_g^F^3Vd)I(>mVH9eD;y&LpZC4t&F=zOqitPsrU|&-qP<;Y zuR5)%KnvZ7`l}hJ$v$`QNJCRyRQ`+oKjzmD4L6EPx4@C4c>2m?` zGzD=up;g$&rUA%HTKR7lv>?67G6{`osf6NbDCIZdF5_=&MA;Up&5DUeqYZcZOHUKz zv7smwl$BcdvBnN`itz;N1^5U@CZEUl_eK&^Ndn)wcaOCa#YwOI^NCPg|@7XbqV+Vd=u5%aZ5YE)a;1|5>GMA z8%z9c`j^JD?Q+fVrGq>zUXa!(4a{T-MDaQ{YTS?g!V_`o=7ZAEpP_L$>KP4~S)pfF z7;v}MJn-!N?;MEg9u+*A4g7fhCS7Ln^Q4rt`&@2@)vdTKiUQ*7&5h&d-UkGNtsqI+ z7o|c_;f%>+y#?3IoT65^rl6+}xIyOrL{;ZKMmM~1OFzj}ip)hCK`7@{+hZC8CL)Zv zQIk~8R3qHM*ULIITr{Q&=-fuPiYOp}o_9ovmmhmoTroW*Ta3dJpThzA5H2=T-33Izv}7 zzTIB&8&*%Wq>q#+bbX1wNS~rM5x#MT9+=57!>D+1P4b~!yBkZIANamULX#=I`;}cj z-#v5WO}K!iJMb*w)z)$yB3^r`o+<2}Gl@HjlszY3z#o-O6tq+WZ=}ryeX7~>s;-4m zrbEA#@oi@24PJJ8oF1ksifrcx9gx_ifiYhl0JhAycm-?h`eUT(ar-H;0d}xnSQjUn zw6mI~2uD%9Bm#ls&BQ;KD`Yg+3kJO>Sy zUS!B|rds`9IMZFckpe5D$JY^(Ksgw(DYK#=T0;C3r(u73(%rURMZ5>sNfW1S%I>2h z5}KaZm*qBXlMgu?IdT4tBd{PxJvL(K^04=NVj{Npo%9OJnXmHfv#}at&<^6KP0&of zAh-l6yNB&%UhrccAt1b_BGkh~O>$%CUQ-Jw&v?o?$e-dux%(O!6b44zKS9uupTV&c z^jMOC-LO@ZI<9qLAxh~`9CxKtv*?l8v002n9Kc|C>c51iM{rQyy!a*asaw`R2^$+y zT)`FYl~h5KHFliQf$8BYIt~8h!Ai6@FZA9F*M)(Cyfgsic1FT-vFGQ0wYH(ftY9FJ z%u?xFw!#KI1q`4V?RJLoYe2ZH!#FqpN6Ldtba#c_uI+~0`ie6Nj3m*#EaAtEKl*0m z+xnO_x@E@s(dEYt_mFbwcPYwUw5$1)@;9;ITG~+OUV9x6V50ejaGs+{Q^@{OYr*Yu z*D0%H%+|tlfkh(1K|9Av=t_P>%7JLgJW0SaSvqTyT0EVUCL+M1Kzx$dV@;EFZ=MF( zh~%3D0gX3_&B2iUUwu=2DZz#(okQj!0E|L@a++qtw!QjKp_qC_#pKeaa1y**YuH;? z#~WL}p@txs3myI0nkqY6t%Iw&@SvyX1w;M^Y$)-Cy^*VV!KS-Xg@lp#P zbwwGyVT{;dCtLxAc}j4!qf_PI>0H7&ZBip)gj23!sYk>~B+v9sbu4DN3A|cRAwP>X zTjNk`I{Qet+k=z#!7Z^u7#n#7OOs54JsH4QDQi0aDS_CiX3FCChW$nwyGh37$sRo^ zOYICUQOq;mQ#9!%QoG8yD1rS%Pu%TOcHN3=az*zzLy*0@;6!_cUoy*@c-CTfp^dm+ zC^E4NAGw&ou5s@q@Q9KBdzuO5c4awsR1$o(i_H*pKGMbrn4(>U@kN3DiF28bO84e+ zU1R&zA_)?9j>RQreWU?S)P89hb3^^XN}OVlkP1+V;)dqnsJ*tmZFq?xlUqcg;kiHu zP#1VA!iI1@n^W}0+h@qUQ7VI|y&+Uz>AS~5o4d(^yMVI27Ujsw&JGv~?&olq9rp3? z*|5ox;8m^ z-c}s`4aecznO-G;)G>*M5%_=u@RX*tZ3Fr*xPDEq+c$O0tt`vN-zCpJ8{c&PErnVh z=7qAZXHQQ)ZWE-!=Qb$79%`T5tb`UuLM0Ne{0kc=+L{)<@ksabA zD%HGS)J6Wfp$XO%fuSt>`5qH#yTPjL-jB}$T9#I>i=+2PtfXRaY*K46j{)HHTkTDmdIU*I=&83%xf)tcBLdkeUc@QT%QB_WsX}6@~ zdS#%!^33ixrjRJ&^Y}|t1v>uif(Fo^FjDiXBFK#@kjqvtRgkgiCQTv83|Afhc&dXI zJ9U0tq1JKie*ev+8wR>hlRp_ZG|Rb~x4q-Gu$)kPNjgyf1@DewJGTVuu_l&a+r7+; zzpz{w1s=82h5R{$x@~axb2%_WvV2Zm#tc>J$F@J*KJ{QTqzQZT18-HeB;VPD4KPIp z6ObRI5y&QEq#K0EWAb8ZzHE*h^piSjUy_&-Y9|NiYi{@R)9JosWNwW#*FW7hU947h zcJJH2oDw66?sO=eY`UUX%HHRcF}457#b{G7RxpJ&VEXqw)^siVaLI&5Bxy$F;AHo| zJZI_u0dwp9Qp+g~;^sVHwBx^sybClbt`pp-_0%D5IjQEkLm<)iYeSu(U0TFc{JF#F z_Z|=St_`RH-8{X6a*a{EuMqwZ^Xh6UJm=`(407EFQvm<8HpW@w8VGL;>(rq zWqRaz!AdMj>mbx(YSDoE-|!maE`ZY3(Q!hFLT{aqKUwzvktES6*sQ_#i=OY~4~UW1 zu3?)`SI)5hD_73gn=OvG_!4?kQK^Da_Qj$5hjwO?W#~0md#9tEbae>JtC#2JpuI%F zebzv59Ox7q@}Z0SV04O7}>mETpahLmC^K;5$^ z@87_2)8k{)zTn))MYQc<)c2f#UOLE@mT+A28aDTAdVX_*K?$$OpZBfiSVOgJM#(af zZoWgXUQ05uE91X;fw;#H};~na^AC?&VP*@~dv%5%5~ui2|p*MOhmYn*z3BcpR=TIW7-~ zN(CEbs=-%drJVVByxnRx)g{s-R*5JBlogYK9bO4Z2anVOk>9JWl-Il+Xe7D3ujqP^ z`cv&k4oG6ky{2z03$5F|4|pcwufJdO8Ee-3T7&BZ8yJxtM)=JUfLt7+3V4Cfx2IqC zzHPZ%*#B6r254E%)_!x+pGAhegZ(|xKkTfRIIt$u+B3lzn)+y%y&OPM>-fJDETI;Q zyXSg{ws)R}q0)SgdMDDY6Vd)Y{ft#)m6$v$ZP>f$eGi=T2k|~G6+j~<*oWjxL>1MA z|F*iz!xbclh$(f?wpc25|4ZCX0gR0WoOU_>~lk3_{YaK<-cZ#{!x zxY>QCFo(33<|a4L&nwAz5QZjq1O3yjVFYABLM-oz#hdA(sDmBe${?&uu_VSU$&2Lb z1j=&|f*3Ij!U(O4$A>=ci?;TkJuLgU$2#&tlu8Of=!yjXB#_zni8<3u*^YnSog|d6 z5CAX~2!^K$GRuO#Nhl?Es!+xLwG$h2(cf1!9uS4{Dgxp3Z0sXX_^WHA2{Oo6RxT6Z z__^A*uwR`HUP(zzjyBwjd0Y*@M96pq)S5{P=${)VpFls{8Wzv=%tlpNazxN`41M1o zMEsnlup*D#^TA3PPUapKjTA6r&gOp9VhVjop>#@~m;TBrxCji>`L7tu4g!KlB`yun zdiq7ZlSg;Awq2uB|35(!+=xbz^iByIh(4KPU%mGyWmHlNBZG$_7yo=+3D$_Lffhn+ z*N9q&M_@ojg!UDz;o0B>Rl6&^K4Sqq3M5&Tx=b;0HvE_&UCKV2*?)8$S6~A@Xa>V; zR+c|RN3qO>6%<9dojrVrxeD;29yf_4-^lEn)ZU)CEUr3$nhUN>ojdkFm5ixD)Z-nf zgq4XbdPW^-zJx~P6u?M$s3MiJFQIYq8LAq6bsCFjG==9tVigvSVxi8muNgp+L6rcD zzXSPN3YL4g%X6D;VGM##-%|{hphrh(GOw3v+*~*0G_1*b!i`GyUS{J29i|g#BKq0# zi+%FcOd+dcxgYF5hgoS;KNk)r|HgsH{=}(Z$fRkdr<@5+NEZD=fFvBxeH}Ak#ai)r zO!32a#%s7b{_#MKGiiAp-o^_>mP#jiIxTnLDvE0t_}K|L`+IKbl#u5Vkpfp7Sh9Ua zUu}5%ZFym*!`Jqudpbd2 zY5n#3N$rM433ku#dc6dU6;bf?y)uw(lAIS2G@7wdntr(PpW9>v%^_4k@k3fAbl)0Q zYdil8I%tiy_AQTF1G&nwAPL<;s>e?8T^Z7fqB}rb$R2qmbvr4#=p}?pQ!6P~JEB#M zPym7}hZ#bMSYg$8NI!SpzjY+zq(_Xntp`A40p=NJOo9_7&h0Dt4XO|E zDY3++GH%13cN~d(NtVyA%%UV_{WE0M{kt6VOdV51i!k%e9n}6pS{b~IxeO3=poaQ` zif7XY!U1p@G7TBZK%~=<{wND-w^5P<+`4G zg<{@OMV!0-{_hz|+77#iRpCfg$~1}#%Yf%5Re^xCPfa0(8{I^sq*aF#sh(cc^36!v zB5f|dSiVGqPbZqoG-;o#`(y_BIbhtw3@inzHJ8WQJ8Auut zp|YqnTNeR{P5&G7pCkqANywC_UKj9cG+MdFXNE2M7eNxb>|!T zq+agTDpK_%V)#_>ytlY7rA+?59BF34w+e+x;V5w2k2kOM9GY<@_fdKeb*BEbrV8Zt zTHu0<+5LAq%~1)cYtJV2_2(@?q-?@rn^=0UV6NiqHF0Y~2e4S{`_Er{0#|SRoC-yi z&(&_7G5=a-3@ZY3Kg&2T&kBTCT~5EFnh&Oft=bQi_HNeqL~SfoTB8osja++oxmfN+ zE#I&4og26A!B}B|zORz0$n>$$<=)?pU?dN6#x_W~Ub{zSLnZ5uM!9ap3YboiOkXck zx7xjRD71?LEiRf9zTkH3donuh}>&4i;G|bruv3g}i>54gwx0tC8V~1=!`q>jN3`DCy z#Ra~S^LVC-Ja`5R+XMX#hp?7x``#7yw7Mf@ma$coO0bgVYqfD|pN?}MY@!k9- zJ?Y5$x)uD+f3hCi9~c6XD{rxTqzw*MBi6^sK(b@?@sF)>Enp!;yeZ;o0Qj$z_-X6B z%gi)HFIROwxl0J?YgritdMHZ*myRJq0mm#y0{jAN@K-9{U0kcw%CC@j=t`RN?RRrv z5cM1ha=@~w>&Mad?}d&sR<6M5*SmN@f3y*x{t$9)f?_D%)}XU{m}tgZxAk2!^>X~H zPUdY{tPk_<_ddgbmlPL55?qK}%)#r0U)GD9B3=v*ZG?Tw1K2y^MiYs$dcS$fUb(lf z*%ElgGHe2kLk#ob7b*akgRijMP5r?xwD}%b8N7QWi&Z?uulvOb;`^fmF_r3oeO_MP zcvIw}#KhK)xMdp5(GX0SHlNin{b7mP{lA}8E6I}fII5Xx0-rxf_PqK#sv_HEPteu) zhd=4%=jO{#@43Oghc#7VYT@**?9rydULXd`M5^q0xp)K$a3}t_Of+SQm}Gh3&FVcTNq+9LX;gEH-=`QMXS^LPZMXHM)~lBUtCNpT z=_C+o(tp~vA?CYx^m#sV?ab^Ia}Z2UWt^Z>)S5!y=hzfCl0mHIx$(Y!h;?X11JN7i zJc<7FbhpdY&$K)zfmDze&RZWLqX-GU{!aA|(htX>i{HB`%!`ek7y~!rq>|FS#K%AR zK<(sHwfVpM2s|Xp=*wL)fc~!wK#Z_35DZw-;{a6L&`WV3je708yL3y@LSwXdHFR$O z)EG+g(&TWV7w6;PjtEEWTttpIW0_>Uf5iqQof~A$*nyOprv&4*y%lJ=1fpjkcRPIr zP-Z)b30a>om<6B8o-#3aNja45r0)krn<_ORH{`n`F@M1a#50I3Xro+%`NPI%oP-IP zFg5hBkX=RvhhD|+b5;+4M7e6{zuZxeXkkd@R=ytl3K*F^P9|O#O?SJ0If@atEx=GX<#Kw1YYKE{I`DFk4Me7h2ic=9e?y3!R{=U zIR%pGZx;#L_qDVTjUo_?wSKS#iuk8k0OQ~exi;OC;paM=pjrbAm-+M=#9*CQ#au=Z z9B!J(GeV^zM9i_POuzr&CfF?pf(vpXR4$d&!rV$}mC2_>H`XJc_aQF-WVhxS+;>~g z7V)PoW-Pyw=pR$CHM@+0RO!d-r%WGYBl9WgM4_ROR*L2)|JsOl0r8`BCc63W9rJx|vjP8cf2!coqq$LJQs7QAR zNR8Y`VSvTS<8!Ah*OH%^l95-8mf_L68^lip z{u#+Gg>vJb-OKh{kCqePFQ~}r779LgtlR%s>ivX7^t(4FuUIQdCd3N4BVN$0NpxG} z?EPI(l^1jkJ{cDIejo6&W!rc`;3sVP`>qE@Vh+9|dnd?~l9~Gcmlu~Dlg%OR_Ln}W zj&s7Lg9r+&&8brRP8s((*RFETOF`0)?uZU0u8YU_%KFHgk0PGMP=C56sQ_Wa>+HSn zuXY&mhz=ph!$aVn%)zwtF}a8PoEhhhcIaOt!Sgm^`f#vyc@M6A$bDe(&&l!E0#<6l zT~-_Ee^6{cfowEdZk`mDb(~+0P!{+%B=%oH1tTFxzTGD3#VfVbSczX|5(J^N4r6LI zSdE*Tu(QjVZ;0|KlG&Zgw9THWnllTT17AYUrlB2IisS8{AFZ5z0m%sU6IL}-JUyvv z_eoqu-w59QuuU;D9s2F!GHb29fBL!=-TwZ|>W!!*!`BPW>zzzbT7H@28__*h(7i-E z$8HM#$GH~je)U++JA`{rg2?k@Ub%`U{f0s`Z{h^;w-9)O%Ac1KF#nPC6aDMz#LrzR zGCzwgr!;ie-Z~t5mwXjJe-`(})a}0(X%HL<;FWTjC7vED9{1u`UN%PeHpP2B6{8iNJ7ea-<_!9i(`;tAf^NdR_{Hv_u6c!hueJ?{k72bcu z>yTm}or+IjT)dJ}UZtq#MAynIRrWxYvCCQQ(|YI+pqG%f0Kn#J&j(ctBk`)ro|lio zS!TVPB&A+mPeWBbGcO6gg*N4~c`|&2D*nvmpUdcBe;t*G191EQh}i{{c{s|A?ywR` zJfb@J46sFBKQAmdIGQWS(nw5Fe@HnEtR<~$s=Gm^LGCWI**rA8fu+|$n*)Cw+YYFY z1I?zJBuZFuIX%fEJbpONmiZs_DfnOL^GI-xo*v6)xHR*CG^bTPm-El?!M4J{&673} z&WkgzNvqw5;Q`ZbT=caItw3J-I}x$-;Y&dKD)pNkpkOxG(emiViHaGIuE$)?Z>Im32e$^@c*JwwEi+o3ojP zDDc5h56(~KxD~h+wds@H`{&6Cm(+BRxn<_Pg8PKq+PwJX-rKaKo=b#)!Aen-!WTf zakpvzgsew*cnS1EltXTi>@R;GD?R=7Oc6!pp*9P5V3?u|)f^jle|5yXN1r6SQmBq8 zD9k%CH&(pYdmM=(ICpDK(NLq*tlo)V8zeO@%>l=kg`q+l6(B&=F(xk{ zdHn4sOW|p*M0I;97uR330%bUa_dDxPuVv^g=F_b+8Bb$>nEu|jZp_Y?l1G?kV~3huV%T8R0vhVq$!9xsg!zzuW&sjg{SR%WGKRa0mBIt zdg4l9@3-5X)`+HE6+f7iRu1}e1@!w*2q+&hboE27z=9Ly=^unH5tp;QDGf$qEV^(T zB7%%dv%#p(byhk)Y(6M7yhsNPK$kL9n0>{|}zmEpe%k_v`G z#W>D%8@tr*L`0cUM6A36j9=XV~3$(2kawgu& z{QAG=7wJA-zlg&XX=x`Df2J0i6;MdIF`;CdKzaOKE9F}J^0MD?#6$*!-!!`Z_a&C6 z!=sr}-z!-&fR7&I^_CF`tQgzYr9)@?;;j_dWlzoJC3`KU7v?X-zcp=+rC+xXH< zRf8Y?p8BXp(B60VAp$THt&c^@ z%jje1#pTzp91AMZoD=Usi6mOxH)J8EkWYYjq3k(FPE#Bbr^DZjO_Bq4+FDGJgOx#A zw^_lOc{8nYK%S>bm#=glwsooEQI|2ws2(U9$=2K}0*d}T>2GF=K;5bWZvN>gagYoL z4nh~s0w$b4+=ySgM|i6Jmn&OJXhrSAUNcDA9Jyy2b%Rv5IkcRXQ6@CCqB zhLP9pT0sH_oZEKk6`}wr8+ZNNLN{_#!bu=reQejjfYT054`1jLR3(D$4X1Lp)u6!L zC(RsoYTnx)L_R5LU!)Y+uVM@%lA_NxKUliWdLJ z{+}WCgVTQ>y1R%9nC=3zqS{0wUY@rS3{d$th0g-ok)zW$? zFI?{l38^1*UMB~-3IOV$k$v~q{y5`dO&ftKwt`;_@Hv*(YY$O}+7`8q_}aG^+K3l` zp67scoLay0<96#C#t1H}MX5&wjLf(#&;Y?PD08q$-aRsW-y#G8} zdw+v~Klbbp12s*&1`XVZl5!u7BJDd~X*fi1`4O<6WOwT2Jsq6l&FS+wyW}TsQp3&l zE{)OW(xbjK8de0&M&axhRa(qm$-(M{T7iL9 zYD=l|Hv1Sf1j`r!q_HRe-4wZ9R#v-7rpDx={PPgxcNA3-H(?(oG*k%!fU?7q51!Ww zw?DTO#$rpLmx!NAdu~5pED;tB#SfWXdJgg9RW}zJY0byl5ZDa}l#6oC@Lh&qpgxwBmCe70iV@eIGwDx?UvZr$?_CgEKF4c^LAU|jSC?n; z((VVr=g48mZr8Rg*Fa5wVxex9f#?$27N2|<2ktM<&s}1CKB*`O`i;{tgp#h2RgJcz zTtyg8pz*eS&Een7{N3Lf8>Z!wvm5M^XlkkZR2d6De!oXrnAx zd6$u1nxK=^5jL;+^DQ@6;l%dlj180c@rzUO30BTF(SaXV-xn;i9Tki!+h*80fz zHlIkcqA8^`NE0uI?nZ_=a^TV`@x8^L|O2sBHNy}+?^#W8WG9H7b}$)o_R8oVJ@=&351LfF`0M$F2RXv@cKKO zO-_lE5LhkJjOsIZ8x{F&&^dAMcs(v0=JIn53dr^QaHaOnq$|wZo9<2o6;8S7UmI@b zcA4t({5W;E&-M0Mo#54buatR%2*U4)=>VG4V`*!5GOkMG-U7J?zQA^geD2b7r}6jd zj0xNve;gd9tA}qMT}My7`D%a8d7<7WlT>-1uzu$jSgCTny2`b0J)qa`JOL~Wg6(ih zfY@PM5zoT#l}!WLoT;K-B=p3@1O!xbaisCp%NDNgVJb3y3;aX2%>O#%z`d`gVkEd^ z1_TB%u<~z+?msoHsj`*Ug~J0pNSW#&QHq6DHK|28al}FO{e0b>q<6bkp%chm(jjU47N0312H%g7>WP$kR2i&`h*xPU%GS(*tdm=J-p6gQvmTa*M#uD8 zu6FP-zA@q_KLBS4I`B z+gz;~VWdoqk-}Os`|?ZTd))a~Bu(!6g8E2@xo_NNq<>ZZkFH}!1Yey&eLd)C5fLGA zw;~p z)%3{H?F%e8WB*o0CBnDoqtMXqVsGeUT#C^4tH{e>Tb`1=iCwqd#ZHZw5T+MrTMvg2 zuU=O6@k|z19sk6}y8g;dkDCHCv#X%{dL=2A#RZ(NHpN~J&#)>6pk{O{TT8f%W`W_o z^(RwX?-d_=;WT(q+|@E2`l-wom+5x97soq`kG~Z$RsBQ4?E&DG8p(HQGe!zYXXSzy z|MVvRQCqBY0|uC9Ic4%r1zA(vCg37oUXC>EG)-GW1+F#4A<9VeQ{9Jvf@M6W>!1cf z;9)nk=^pH7qYwjH>E%`L8+g3H(N8fv?nom%<-k$YdYB<`){w$;WM_V`0XLaF3X;U8 zD$vbFQ40R}yPJUdgthlai8TXr&7Rp^1XNvr%@J(&y0unoTYPT!08}YD3xTisgCe`MsK-hNb^CL9HZ?+)8j6 z;2zpm47*}rMOyn;B!>tPzqqr+uhY6bjyKKmMYf$q(hqtU0Kjdw0`(;UM09?=7x<1Q zmgiQ!al`=^r{MPAy4`IzrOlW2$|Bnfoux?5+sklqO!-)w#g+!|uhH*%Q9zof90oGTqeB&_fj?2pABbxsrOh z!1!X%NivoKnKL-$Z+_HjDXyk@wm0rOTsMA)NeegjVHm zo>%-{^F*ARia>-|4i}U0?27Zqx6PO3lRgw*zJSP~JDpT7(sAWt}2>m?4CEP9h= zr~dB2*xmR%4f*N_CORGMxtZFUiw9&zPd$VX(gaZ-uo}x+9Jg(0Lo4gW``r(-RfKr^ zy&n%rNV$-rDkhay1dCK1CggfZcc^gF0=zGOS@sov3{5DjS#7X;sMC?(vRBy@_Sste zGjiQY$v1?Fhlp$NM#2?eGu%M4N=$9>44N|~`0gn*qa$R2`|zGMSVpBy?v4G;ayJa; zrtlD;H{otH6jpL`i;6MX*@9RNUWYDWNOQ8ip*&%rbHx{?Y44RIWcp{v-iI0+J>Jr<+O#w5RYhvVjQze6Rs-jAfS z0k8FWcb1p%jL{c7Hdmu6r+b!oA9P88Y+*gKXw9MnQq=ocH9jdl3z#`IIOz+oV?X)8 z73R3Z@|e<7^X;Ox@=zKqH%}>ovzz?0|LdXAi9#A_Vf>***j2pDh)=B)ASpP^*F{q` zqF2Qta$xQ@lNoT3J(J5Lz+6bX$~v&>zFtKAjlh4TG(|Y;;nbCR>rx*9Iv3meM;*>< zFoGW6SA6@n;onc5v=y(RWgW^`*P&f>W;9Sf*vOvOih?at|)%iCr z^o034wCdnHvatpk%`d-bPr!z%r6wo*lh6NEGAdfP_fmqM38Q*-A;V?h^Wkfa{s{NwE zec}dja<8*ED#zon^vp`hyQFMiOHHWm`~h^`X&e9kRuh@)i2_2L1e93i>Z`));Wt2Sgy|QC*sw(#l6#1a@~C z!xYWDpi-VKa`WlPhqbuZ(*z<(kBK{n6vN!EDG9SgwB>+>O1A1aX*+Y`Uix3*0LSuq32DaFB`jpg;ozhM(U z^&9qB>#JVdim;_?YI41dScn7Ab(g>O?|jQUo(# z0nan@hQp=k#^*iwWist)=-v zlJb(2z^|n$SJ&g$g;&5wn5N<@%}FatE&jBNRVOLfdM^8)lGgfaxo!3f55K(zu`E-{ zmI$4m9-Ge+9^Yf6Yvw7HRMYcHv@dRCSzHlhVQWR04?TEF&0swqyC%v>9eIh>g7mHFcP+!0`q^4LU6!NpVyFt*$U{3J(AA& zIGxO}<9pMLLt04T`R|ENH{jmt_^WxF!TD>E#K+yDRx|7L_~VM}J;=hf!K)Gx?FSH{ z3Fw&MMZ-OkQO>%ZfDe2w&kgavPZ|zAi|=4YYBDLjM!!i!$+DSRbw`T`+CGgw)tHla zmtgzd33O!rcci&SnE?+H;kS~cqTiR5YnHe+5_Y$($~8j=5j0s#xs!X&t^R)$&(EXU zU?sxes^awNuw?3+b#6s&`Jg(TAGz0Rn#BTlPbb%0C|Ai2^aNhD)@y%0KR?)_c~CJMy!JwDe>b#O%q0vM6^18GsAZQgE}RQ+aOe2-K1 zW)?$F2A`;OuV}Tt0&vKc~G*Sl~qCCqI+HLI-E%?M3MjoR#1gdzl12ScwYE%oz;UDv#+*Fq4_`9XJb+D zv$&41Ygs;PdY1;!CA(rsf1I?vbs*c_OPDESpp2f8>#ps>JDu?UvH;6l$nP_=8bpSZ zDbxA6hQragg5v2I1?43!N+a-VutP+Bg53L@G16QB{z*uvyU&lu>+CLu@=A$ik)U3W z9EVO;_HzN$D{=e#wpI{^amZde=If-_OyK!{R(c2L4~6{BS#%C;~@-oHID3q-3nG9mL)f^YN6 z{&vG9gHeQ03Q<~ZC>zRSGuK+JGR*fe2QZVFBzazl3X+~4z9q;m_^t1nZRv9p357Sn zMPy|Z*_FnPRwBFG$O=8$rc*$l4ycUmQTtV?29tQBq-i^`5XW2?SlJ>7&gl9l1abq7 z{WY98!2X==n*VSJ{1C1V{KD0q=!0_0t<3t|mK!URgO&30FG@qQESat6sw$$TfM04_ z(P*&Q(R|@;Pir*UZ!Kwi77+rpjOF8{-Z(T`tRw7_W*g$sO$pSIwjB5W!-N&sI6I^r zZgs1%+}f(6ktW5@typOCNhZ!Wa`FJkKh7`T&8D%!=MX*Ikd|#;n3D8eeJZZ|&JbI1 z!p>b(f`{-*yE5rnTKv@%K$a}rsn1J8!S>gt1&x#`+U%XZxy z^34wu#-3Ji{7tFIxdU^8IZr{U>-?lH#$b``*e7z$t5-(^uwE-AVeHicSo(rypjAu- z>VtwNp0MY%(mD%n1!;X0kUj8NxmwL#x(dEL4R!t2#%|te0VfdU9ie9URM>q$@Nqiw z0a^q~eLT-POnrXXUCAKrq3e9glQSW|I*P?jVB9zJF-*Wd0Rn6Y(Aus5&)B}phqQk? zmjhyjFAg#kdxE96ZbsN7KK~_^C&dfny@^lRRgq0H`Hn-easG{d_X%_Bay!?1C;sLH zaM}i)eTHQASkQS1h4j5n9*F!&xm;niQF~V=Zy@$KJTq)#Hr7r0cAiW*|I`&K?_V`K z$+pud9Kr(Hs#zK{vNf0VA?lNDMEdBkoi5TBQ!c;O*vyffTFC7H4eU=G8Ao3)+DDqm@X!5_mU0 z%3;zs=_|F@sLk)4^MK!1)SwM;Lg8xh1j&W>0~8+|+d9px8Q zA4j%-OpJ)fGz|%}9LyJtV1a08i0kOwL3z&gXkW?T&s%-Uw6vS&o+=354 z<-bGp4{9TqG<|p9&v&b??0^fC+OC!Mc~*s)4!^Lvtz2=K{mKc~KbiSfHleX(tcgP+ zVJ8wx{Cgd#s(MRj+Z)~d6_@osIgZ-P%Wo%nqxFgHfW_Wi>5pzl-?_8&EWy}6OO5ScemC4!S?LR=`xk9R=cYiSm z-I&Meq083D1M%pLO;upo_O-BYW+6cBC+fk~)RJgSN@cZWf5`wb4**-MeL_i+#vxuC zKA@#X`Cr%n5@husuRJi`X>aF)gI>zMl+pnm5y&JJD=VL_kkRZ)RCRT;h{$b%wg;1*Kf~1=v`kmG`rTYg?&n6R#=PeM^Y=fpJb5Nn3>Sap@aO%YK}^l=)M-6TJ@a%1QtzwVc%eJJ zGyl4B{Cj|@`L4;I-|k%TE(cX+mn47HZQZ(o&%Vdv>;P&4U*`&17#m~Uie7uvS7Q=8 zH@TMH&DXsR@@Yc`x-`nXeckJWcA@7AACZ_K9!z1s-{+iPn1rreg!xQvx}v$2uPU0a zb0sVB<@9u02~yjw_8B^A(pd}{93DEDvzWWD!45kCw^v$N8#wiZQKDK(Oxg0S(U9>=t?VAE1-r?Cx&3T< ziG2OWkcv*=93C1zL&l6MY|MQ%2px(Nh{f06pS>%GV078D(wSaEnhaMh%| zMeG2X^F45P@m(?D7t57u?ul*a^CDMSs86Bi@+KJ8B&ZS@Nw|;8@bE@{SgQt0!LiR2 zk=Kp5?N9x0`>((7*9_w$d_z9fYw&nNKhKcvk<2DvVvXdMC}Wp{7v5j1P`_uD-*=5a zCp`|@UimTTC>XMun_N$FQB!f6^#gJw{w+LPc+FjKzsz*^8}JQ8vHbDmj)?q))(d0Z z!g#8zFPSK{P%(=Y+qoy|`mwk&Uz(TD*HNc>B*cAXMF*98KzDMsZxTbK6w}i7BM#JE z!hzyPX{|FV*<@v@+IzbWUJa{JrO5EWW((z=y@O?-WUHq^EKBUDUMG)tlvHzBN;A1x zx!VQRFH@KaFjs{S&h-7Rx|Y}O1a9cdjiu#0K<+bG#!Bp5r6kqXNLS8igB5s0>^8I; zazMgOvQpJAhrYgTNIhYQ_v!4Vps-j3tM}WlPIyo^~mj6`>#Ki^48;4W+xL9rhP6beOB192EW&Pw$oO1JKV- zFm!4J?oH}SWXlpis=fs0>|@xF{;SkQZ1Ljalr?F$cimY4M7z(c?C+}A!+K{m)cCiN z8r7qv+?QgzFcp3gw;6h(i;lR zZaq6Y!Y>uqA6iI~ilEu{lC9jIvtYRZlss*)nEB+mc1>s>vD%E7#i`WJkm3Z;@?ob& z;4y2$9+USTKL5hmi^}7UkNV8*>>}%HymjdT#(xJBF+2co&_f6nGXTDb&F;KdBRfK7 z_N1fkIjsBcjJ0(@lp~Ymm1YXCK%JG`rHLr`*EFO&=!Qom4>VYrT+{F=mRO`Z2YxGk zhN8>+dDr7ANYm%Kl;&LEKSyvy)Sn-B1ii)cSYP3=*B!0Aey!|IrLZe$-PKJi(`j`c zD3V)*HP`#oTt1-iF@c}=r+k^TIGvyE*HG~q!tG9e$lsZ*cPfl)-^vvFWdu_H1kE}q zTok41w9kr?BM)OQo^Dy?G(DfzbK@-cpP@VHY_I`Tp6cg~j%q_EsSvvNor<BadbYMPd?q#gA1-E z2y%5_I+VM?wPRQOkGHjM6TBWu1+k{KzXx4RTi&wzb%bii-e*G*b5?$m;Ij>*R`Fkv zu<&%bJUIa;Sc2&pQ1K|_-2O7l`}S%w(cB(cxHU$S4rWYvbjLl(8VN_;l*Bo?%xYWY zokGHRe;s9EI+LoY9Zo0ILo^=nC!!Ik#im`QK2;00bM8J}_u7E35hF1@XW|#v*E|1w zM=tj*!yzFS&*05>O6eR<_B)hdR~OU$Y6PvYm>t7o!6YiTd`;X+g)PsoT-{#oqicS* z;cXbv%J)@J97)tR$3Z+CYZ7sKKcOK0XuNn|RM^<5%H46NLJQs)lF zk?8pYX=?@sTBKFMASxt%kLyDi;Feh zMRGJFyv-YS*3&%h#~PpUqOS6C1Q$+5kEb_wPaD|3%;8%5H5z7}uwzIPChv;ki50db6A{LZ#7Xf%baIB=FytGk*K?<`3eZ#8}9vW@M|9SRbE3$ZI+LUto<H^xJ!1m7C{%Sz%?+AACZX#$nWaSc2#X4(_uO~z)B)xo9+kAX;9b2%LM=MkM z`!euUjEhnnevs1`x&JxbrL`X0?;{%l+wS~OMU%6-&>Q^NF_R*KU1@=e(HW@(tR_nX zFY_!5haOXYlrE~42~!ATS6o+KbczD4@pbN8O{m%sP_Tq`|Gpi$`>>geOYdh{*Ow+d zjz65;*izXGIZ6CRj!vq=KGUcAkxznYORaS0MoA^{nF-BEH_Se@kPgJ96208nfN_cQ zSD5{*I^gDlM8&5HJ*JliKl$7;`d#pEpHt38wE5=h+GFfdow=f2*Bi;IrjNjE+w2cz zQRII~Lm$roue)!|mWpXR_$-}f)QT29N15-Iom<_NhY-Q#j5%fqJ)?;7LkoqEj`c&9 zo#cRyO5dfkZPf+ z8ohfvOfb4cGal2)!ScM%bSMhT6E43{@^It^fyT$E!D)`cmkf*cPiKeBy602%r1dHw zgtm9`FoWO`pH<+<0A^k*wp3P;&C#GR91-ftIV-vtUHTqlqj@Zs0?&lqc|R=vok|x;FM^jzERg-C=MH(c zHY<}cd+C82Nd8v{W(M!f9$5k+Tav$nTPwOvqyTSrM4Pz~T$-Bo?f?#bb2??&pIe%Z zU_+;dR*_;h|Be11vB0<)5@_<>Nbq!fM&|A}&1+1T@Z8%$k)grXb6V!jDd15*O%H8b z0nPV#jQ$VBs;Bfvqd$Iae79Tm#*@3TeCq@{5jp%nobnc6FtL+ znOl7dxMPLeQEy!|d?X~ZEOaclM8-ni@bQ9Kg1*rr)UCkpEQHU_s zfahR80^v%=zht26x`1_SRxiZwOU`6B69@NT|BJumSyBL-yBzSTv=N{DhJF7eI9eJ8 zgjAL<@~*WF%E+>HFNcyUt?2!##_Pnc%Fv4-6EUE+TrsAik>rfRokPmF-i1Y< zm$M*qq#Snvt%)J4rlW9;r_cbc)-vPIR>YVs-ixS{9~Fa8`iGczNeyv2!|Tt=c53o| z_&oNwoc&6EJ@y@#Zg1(9Q)BHk)LwHkX+AWXFj^)&IIFi{rIaDRIp{ZwyIDjS@%jvN zx%<@Im&26U(w{Tsv@{=Pf&ye;uKKWK!33$_Ff*@nE(jtLurhlHd1rQ6D>)GR?y!$m z(k(dPDV$`1CXN}x?ZcexGDD`f7`wRnFvQpU7S{m;oz4F49)G+$=G*KG*bo@nYQecL*JobB_UyT5 z=figHD+dh9iWT@CiX^|4P=@)?H!o3+ECgKd93E4>O(_k>F(**6e>HV>lKojR%|lYr zNZIAjNzdFrS(xi4t^1&j)$blZLjRbQ95s$Nz4xB~%&^Iq{J59m zmqcQx0B4oFCKT0HKjIu;2eNukVlx_}>f`!MQ&>Y$k=i$3$ zg-tDSVCuc2)1&OnNwwQN9kvl^`@S8q^lZ(eACktE6OpSQ{oJX$nT;#K7IN}B7Vr#) zr=hLwn~RgQEQsZhabg;X49->)NxW-jUX6ESf48iSD12PvQ}NMY@DF+5J#W3`3J4=~ zHPYH9^Nn5DtIsT7dvs)2(jDK(z;aa!IYBp z7r;yC+w~JtAjU5yKE6l(QWVjgo4KSQM{F z4Sw|`+0`-a=dCNn3!fjwx|V0!Rb0r_Hp!a66KwkMpbBlepP3)ryfGef=zR=tFZR-@e;M4=*Vgt6T1gO^pnrX>*q)}WcsPtryFr`dr6C=a8)uM1v&)~M=O9B~(ZtM)HR2&N zs?bU&?mY|a@uA@oeCVUs>Gm`O{HyN8N~Z8p$npGIZtmhxvQNoldGpWA54OWqkT~qU zR$5!|=twwo>ggQ}-MZSU(JK(X=cVlDI}j}YhIBci z=G*Z5H*94e7nyGKW{W0kg-;5mWY<$TU-*x8y^F2{96Yu$*chGEMpiN_b1(3YYU~F4 z9V|~#0NRt5=>J3WW9VN`b(XYf;)%>6D6o68+rDq;%;6S&dxc;CF=&pPKrJl- z*cRi^cX@CGWSkeDrRrc{B&sJXBBULuxUCumd;R(dOXp`1(f3#X+1;a;_#jRcFZ>Zi zMmkm*CZo%?XniaB#iL9grhsDrSZWcW?( zHDl*bs5Iu&Gtu`N1&i5?#l!k-Lc_lL4^AnD9fTpfmor6JZXm}>n*8NsQTz5I7Ct+R zn=9<%2X+k$Hnb-^IHVYT>6jr$bTprD`gyn6A*musx?J}wHJt-Xz*8OU{XtBh?3wG2 zUfhoV*W=c^Can)m>{OuXC$g}x_9y7n1-xqhU}YU=xV@sXP_b_I@QtNI)1OMel-i`0 z?`k>H2uH0S93wY^;H(p-696iJ6Jb*()!6PR`YO;_(t|({~FM@qT4D zm>C8!U9SWY5IH2lNNp+@13tk(_pr#P;~|R_7)lYMVZ`LxkdfEZ-?3#=ar$A8ggrEs zq~&uzjp?%-&jU!JTJZ3VmN*olE2gKbw5`4yy%0IT%{dA}5hi^}INP6v<^YF9q0XcU zf#Lm63sl#)Ea5pXGd~-xvjVJd=b8*rXHCItyRB3x7N1lBskcXatsOW?3pzCS>mm%h z!AA~@(0$A_f=O$AV?_R~Po4*I7`c{6su!u`+w!EZELj15evq8xn`fwEHO%d`unwj* zO7z)z^|RGU(*rQyQzVes8LzI4PLZS!5_UcE56sgIjLz*bPa8=U@+Mr>e%|` zy&5ou=rwaEtRj8m4tN7OR{VW~<`UlbwBqKVhYKe+N@=!rSzHoQm^W7qj*z>1!KDm#64S&FxMCaRo~*F@Ap8TZ|dnwZ8jG%+1RT z!~%qF_p)e@BYT@i4ms^SKQQDp$qq6^)E=*ooT&`y0$69}1E0oJ^TED=S*+iLV))p} zFj_1Ue&oY~$8!N;VhtbaxCh z;XudbGB37a#j48A+1bA4#>?2(Chlum_5z0I0i6Q~iijTm?O$xng7fAuV*DI3KB(dU zcmW96q%(-ciUo*D*(qN7K`}}Q&ErXo)S>S1;xE*B1kQGSw`w^JE#f1977O?uU8-=D z3vtJ{qC!8p9zc<|U5195xm6Z*0} zE5l^PGXfjY`tvFL{bf!gf&_`OTMaiaYR*B|&tpm`x9*wGKXg#AD_-R9Rb&k}thPE- ziPn2$9{kV{$}w`^bVOvgDCs3@#xs}jM|u8}>I*OIfM9oI-WTs*ib#&JY(ovJX12E# znMu~IZbqg>tY5E>^J;kAvK(cISI;jl{O0o>1mKJQSxV{z{p@>#*wM^SIK#%Y%naK?wyk^0nqHAe*h1Ci5>Jh!EXB`&rrrDstjKcZ6a< zCG&X6IRN)hMP@6h%!JL&ib~s1`E_bNd^pt0_=CqGa~G9yHOb^jvHpTfm?YOIP z{Y4#TV&?=`r|l1r%jdhpuCNfj79nzEkS;sIJgufkB*U)qyK+eYT28;3!dBx6ICZ-(wY)r8W8cw^ zYx-7|oYp{x@oF(pOk|RW?2W695bL~b(ro3}W-oi7OA2seU>Hkc`iMBh#JbO+@R+o> zr!SE@_snj%@xsSXsq$b5A$wvMm#Z1KEolt#!^`{7dREaCwa>}=Bi&gM!3{S)2z@{k ztHdh}msf?Ycds?!+^Ub4Lh=qv_vZzc#KJ!KwQk$WS)7$3u~$|}h?;c{W4F2TMj71y zQu|keEQqP zAm_9oby{(^RM9VPwOA0s7AW7Y9C}V@8`p2*AbO$CeZWPXB{eP`iwU9h@E2;su#__A zUbYb?qU*@!A6=d9j+{A>+hbE@8PC2Ub`iKo)WJhq19f_I^%pBQs2=vxx60Ko!_jun zCxInLT+bwl5uD?HsHIL3Z~g*X<%4hFL_3xgY37+7Vc+a*X2Ps8ArN8{D+-K21UT?sP|$<_-G3(($njCp*pm`M{|7R1_6T;G{euCt?9*?#IuJ6C}ZF1zJtbbe35FQQiJ>lsvN=ZQz$uX@T>TKzjfhFMGqWbJ1I z$9FjSF^C>OLW7!mU(+-iTKEVv9=taKSv(6d&0}S3io1Bd;=pJ?Cox9scs0$DcXBRK z0fR1SwcI4Kvja^hNl(NqKru&pHID-98vH#L*JqcH_YUV)7E96VVMx;sv6g}7& z@6m^(8YfSi4X^zywE4zQx4_di$}7{mAPiSeKqXQ>{12vWN>I*_+W|(*Q5_uA{W@pEn{E2TAj_Qme zM0_Ic%ch6nJ^8k0DhOaOX`dT2g}`PoYoC>nOx7(crq=#^xW#QD{eouZ?}`MUIB!_Q zKph)z``%t%eehf;Ym|@eVA$hg>{VzUqk*ostHVGk8k%c0=jE8=vpo zKC0wj&EvoM#6Y)6x%huq4g><`?Z!q+cDpDE5+Xt$i%Y#wH(Hw(AJ-RDY zAGE%LDz|E?&eyUnWV7{;j`o}Qwf0-WB8>FOW<^%oRv@e=Ph9by5taMs zkeze>p5R~Iu^5Sk36lR7qI$rv3ZZAH#V<2cOdC?6LV0KaGqYVmji^!MwSJ0hw3=iYtkekZiyxawr~5b9J!q)xIXOM#3UJXKN6+jo8N*CYV%le( zt(>}D?nx{lj@Ia&rK!t)m~wKHhf$t@J9t^J@sKv<1iTHCD|QTd9@umFrCNCI zLnc$Cp^(79cu>7x_Ndhd&m$v0vC<=iTZ5)!VJlu!!7f`Kfqw$K%S?BGJ8&Ymgz!v2u@ZO1K=uTbJKVqkW>GV!w0GFy-G zGveO+^^4Zm1`R5h!s`$UZarH5lMzOv+`qu3YprvL57 zB<8qKNuQ8a2xx%B?$om@??=8VR&+>47btW>w+*ArcPP z=*8=JnfJX3bWi4mL?@Sn*yBqUTa;NXX?i(=V`c)sc`2m#1pCnr4UUkwx9yEw%2~q< zycT|TpRllo1Xz6hz|hcsrsaB?^kV8GQ32hO$)w5QEIFK2WM5Ieoe{nW59}T)blVqf zTM%wx>Ir+D+$yZ`e$$~&tl$schU6vGao5?AK{x&fnzj>7-&xmh&oKYC_?Z}{Ay1~H zjm0hF*^%JNNHg2luo{ux6JKdW+=f_13My(|OL-+w)?t72lJ|(9b@1qES@yhxg;h>V zuPei#(C!CW=+&5HuaVT*UZq%%URQKL)2z6MKR+~9=U3#)%uiZ>f6U828cIn)ZtO&T zgL5k{8$ujYD)Zn=J%=O>Y)o-wn-MbZzuL1O5%MZ)6gvEpBEb|40Be{pxn1d`m}Qim zbK3V_3!j+ZpLLFKUJ7SJ6=38}>YM^e!N{SP-w;ySO0KD+H9bH<;gjzv>N1tXixUnd z`+T-&f6cLD5E^qQJTpC6`K$0HgT!L95BB{y$Z+rbr8%vcm(1)wbtFTTumMJXVqWx! zx5MvhFyZa8k4eQ1sgCRz{_OxUhWaM!r+=>hV$#aIbMjQ0X+~�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

#OaG=$jQXJIUFE~t-iL6<6w#8rj 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 literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Configuration Class.xctemplate/TemplateInfo.plist new file mode 100755 index 0000000..146a6df --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Objective-C/___FILEBASENAME___.m b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/Swift/___FILEBASENAME___.swift new file mode 100644 index 0000000..a8371cf --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateIcon.icns new file mode 100644 index 0000000000000000000000000000000000000000..5cb4ae999f06c9d5b5f3152a034c65f23137821e GIT binary patch literal 529473 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%0D_YWU3_}$$FJi-@LKlix9Xblc5@0Ulz3?A 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%0Dl`^kCYc7e=RkY)F>z4{wSA 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�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

#OaG=$jQXJIUFE~t-iL6<6w#8rj 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 literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick Templates/Quick Spec Class.xctemplate/TemplateInfo.plist new file mode 100755 index 0000000..7b8088f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Quick.podspec b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.podspec new file mode 100644 index 0000000..a0a2c21 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.podspec @@ -0,0 +1,38 @@ +Pod::Spec.new do |s| + s.name = "Quick" + s.version = "1.1.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/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj new file mode 100644 index 0000000..bd37459 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/project.pbxproj @@ -0,0 +1,2649 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* 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 */; }; + 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 */; }; + 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 = ""; }; + 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; }; + 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 */, + ); + 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 */, + ); + 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 */, + ); + 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 */, + A870E6171DE00FC7006891AD /* ShellScript */, + ); + 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 */, + A870E6161DE00E50006891AD /* ShellScript */, + ); + 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 */, + A870E6151DE00E37006891AD /* ShellScript */, + ); + 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 = 0810; + 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; + }; + 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 */, + ); + }; +/* 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 */ + A870E6151DE00E37006891AD /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint; fi"; + }; + A870E6161DE00E50006891AD /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint; fi"; + }; + A870E6171DE00FC7006891AD /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\nswiftlint; fi"; + }; +/* 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 */, + 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 */, + 1F118D141BDCA556005013A2 /* FailureTests+ObjC.m 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 */, + 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 */, + 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 */, + DAA63EA419F7637300CD0A3B /* PendingTests.swift in Sources */, + DA8F91AC19F3299E006F6675 /* SharedExamplesTests.swift in Sources */, + DA7AE6F219FC493F000AFDCE /* ItTests.swift in Sources */, + 4748E8951A6AEBB3009EC992 /* SharedExamples+BeforeEachTests+ObjC.m 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 */, + 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 */, + 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 */, + DAE714F019FF65D3005905B8 /* Configuration+BeforeEachTests.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 */, + 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; + }; + 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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + 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_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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + 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_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; + }; + 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/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a459aa8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme new file mode 100644 index 0000000..c8b0c3b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-iOS.xcscheme @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme new file mode 100644 index 0000000..db251d5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-macOS.xcscheme @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme new file mode 100644 index 0000000..4537096 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcodeproj/xcshareddata/xcschemes/Quick-tvOS.xcscheme @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..48af53a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Quick.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/README.md new file mode 100644 index 0000000..e6dc0ad --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Rakefile b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Rakefile new file mode 100644 index 0000000..7eb39cd --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Rakefile @@ -0,0 +1,68 @@ +def run(command) + system(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| + run "mv Package.swift .Package.swift && cp .Package.test.swift Package.swift" + run "swift build --clean && swift build && swift test" + run "mv .Package.swift Package.swift" + 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift new file mode 100644 index 0000000..bb5cc0c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Callsite.swift @@ -0,0 +1,32 @@ +import Foundation + +/** + An object encapsulating the file and line number at which + a particular example is defined. +*/ +final public class Callsite: NSObject { + /** + 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Configuration/Configuration.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Configuration/Configuration.swift new file mode 100644 index 0000000..583651b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + @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 _runtime(_ObjC) + @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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Configuration/QuickConfiguration.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Configuration/QuickConfiguration.swift new file mode 100644 index 0000000..6f5d0e6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) + +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, superclass: 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) +} + +/** + 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 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) +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift new file mode 100644 index 0000000..127ca54 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/DSL/World+DSL.swift @@ -0,0 +1,175 @@ +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 _runtime(_ObjC) + @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 _runtime(_ObjC) + @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) + } + +#if _runtime(_ObjC) + @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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift new file mode 100644 index 0000000..8405a81 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ErrorUtility.swift @@ -0,0 +1,10 @@ +import Foundation + +internal func raiseError(_ message: String) -> Never { +#if _runtime(_ObjC) + 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Example.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Example.swift new file mode 100644 index 0000000..56b3303 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Example.swift @@ -0,0 +1,113 @@ +import Foundation + +private var numberOfExamplesRun = 0 + +/** + Examples, defined with the `it` function, use assertions to + demonstrate how code should behave. These are like "tests" in XCTest. +*/ +final public class Example: NSObject { + /** + 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 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 >= world.includedExampleCount { + 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift new file mode 100644 index 0000000..ca38356 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ExampleGroup.swift @@ -0,0 +1,103 @@ +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] { + var examples = childExamples + for group in childGroups { + examples.append(contentsOf: group.examples) + } + return examples + } + + internal var name: String? { + if let parent = parent { + guard let name = parent.name else { return description } + return "\(name), \(description)" + } else { + return isInternalRootExampleGroup ? nil : 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift new file mode 100644 index 0000000..e7510f7 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/ExampleMetadata.swift @@ -0,0 +1,24 @@ +import Foundation + +/** + 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: NSObject { + /** + 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift new file mode 100644 index 0000000..d452efe --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Filter.swift @@ -0,0 +1,31 @@ +import Foundation + +/** + 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: NSObject { + /** + 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/Closures.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/Closures.swift new file mode 100644 index 0000000..9c7d310 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/ExampleHooks.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/ExampleHooks.swift new file mode 100644 index 0000000..449cbfc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/HooksPhase.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/HooksPhase.swift new file mode 100644 index 0000000..2440158 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/SuiteHooks.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Hooks/SuiteHooks.swift new file mode 100644 index 0000000..b39292b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/Info.plist new file mode 100644 index 0000000..9667430 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift new file mode 100644 index 0000000..994dd72 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/NSBundle+CurrentTestBundle.swift @@ -0,0 +1,25 @@ +#if os(OSX) || 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift new file mode 100644 index 0000000..4514863 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/NSString+C99ExtendedIdentifier.swift @@ -0,0 +1,33 @@ +#if os(OSX) || 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickMain.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickMain.swift new file mode 100644 index 0000000..eb9aba5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift new file mode 100644 index 0000000..d49e859 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickSelectedTestSuiteBuilder.swift @@ -0,0 +1,74 @@ +#if os(OSX) || 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift new file mode 100644 index 0000000..5682a78 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickSpec.swift @@ -0,0 +1,122 @@ +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 _runtime(_ObjC) +import QuickSpecBase + +public typealias QuickSpecBase = _QuickSpecBase +#else +public typealias QuickSpecBase = XCTestCase +#endif + +open class QuickSpec: QuickSpecBase { + open func spec() {} + +#if !_runtime(_ObjC) + 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. + override open class func defaultTestSuite() -> XCTestSuite { + 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 + + return super.defaultTestSuite() + } + + 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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift new file mode 100644 index 0000000..0cb5187 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/QuickTestSuite.swift @@ -0,0 +1,52 @@ +#if os(OSX) || 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`. + */ + public static func selectedTestSuite(forTestCaseWithName name: String) -> QuickTestSuite? { + guard let builder = QuickSelectedTestSuiteBuilder(forTestCaseWithName: name) else { return nil } + + if builtTestSuites.contains(builder.testSuiteClassName) { + return nil + } else { + builtTestSuites.insert(builder.testSuiteClassName) + return builder.buildTestSuite() + } + } + +} + +#endif diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/URL+FileName.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/URL+FileName.swift new file mode 100644 index 0000000..23c4781 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/World.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/World.swift new file mode 100644 index 0000000..fb5ec25 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/Quick/World.swift @@ -0,0 +1,233 @@ +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 + +/** + 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: NSObject { + /** + 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 _runtime(_ObjC) + // 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 _runtime(_ObjC) + @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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.h new file mode 100644 index 0000000..5646199 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Configuration/QuickConfiguration.m new file mode 100644 index 0000000..937b818 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.h new file mode 100644 index 0000000..c5f3152 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/QCKDSL.m new file mode 100644 index 0000000..10e8a3d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h new file mode 100644 index 0000000..a3b8524 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/DSL/World+DSL.h @@ -0,0 +1,20 @@ +#import + +@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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Quick.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/Quick.h new file mode 100644 index 0000000..87dad10 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h new file mode 100644 index 0000000..105a97e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.h @@ -0,0 +1,50 @@ +#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; + +@end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m new file mode 100644 index 0000000..4891679 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/QuickSpec.m @@ -0,0 +1,141 @@ +#import "QuickSpec.h" +#import "QuickConfiguration.h" +#import "World.h" +#import + +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 { } + +#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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/World.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/World.h new file mode 100644 index 0000000..e638cf6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/World.h @@ -0,0 +1,18 @@ +#import + +@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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m new file mode 100644 index 0000000..e49939e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickObjectiveC/XCTestSuite+QuickTestSuiteBuilder.m @@ -0,0 +1,40 @@ +#import +#import +#import + +@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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickSpecBase/QuickSpecBase.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickSpecBase/QuickSpecBase.m new file mode 100644 index 0000000..10b6f7e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h new file mode 100644 index 0000000..69e96cc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Sources/QuickSpecBase/include/QuickSpecBase.h @@ -0,0 +1,11 @@ +@import Foundation; +@import XCTest; + +@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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/LinuxMain.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/LinuxMain.swift new file mode 100644 index 0000000..2a67c4a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests+ObjC.m new file mode 100644 index 0000000..cd3522d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/AfterSuiteTests.swift new file mode 100644 index 0000000..ea4fc3e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickAfterSuiteTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests+ObjC.m new file mode 100644 index 0000000..5069f2b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift new file mode 100644 index 0000000..777629f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/FocusedTests.swift @@ -0,0 +1,59 @@ +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)") {} + } + } +} + +// 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") + } +} + +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, 5 as UInt) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickFocusedTests/Info.plist new file mode 100644 index 0000000..ba72822 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/SpecRunner.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/SpecRunner.swift new file mode 100644 index 0000000..66dec1b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/TestRun.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/TestRun.swift new file mode 100644 index 0000000..3ef0d6c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/XCTestCaseProvider.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTestHelpers/XCTestCaseProvider.swift new file mode 100644 index 0000000..43dc05f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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(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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Fixtures/FunctionalTests_SharedExamplesTests_SharedExamples.swift new file mode 100644 index 0000000..e5eed68 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift new file mode 100644 index 0000000..2879a4b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/AfterEachTests.swift @@ -0,0 +1,93 @@ +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(AfterEachType.OuterOne) } + afterEach { afterEachOrder.append(AfterEachType.OuterTwo) } + afterEach { afterEachOrder.append(AfterEachType.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([AfterEachType.OuterOne, AfterEachType.OuterTwo, AfterEachType.OuterThree])) + } + + context("when there are nested afterEach") { + afterEach { afterEachOrder.append(AfterEachType.InnerOne) } + afterEach { afterEachOrder.append(AfterEachType.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([ + AfterEachType.OuterOne, AfterEachType.OuterTwo, AfterEachType.OuterThree, + AfterEachType.OuterOne, AfterEachType.OuterTwo, AfterEachType.OuterThree + ])) + } + } + + context("when there are nested afterEach without examples") { + afterEach { afterEachOrder.append(AfterEachType.NoExamples) } + } + } +#if _runtime(_ObjC) && !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 = [ + // [1] The outer afterEach closures are executed from top to bottom. + AfterEachType.OuterOne, AfterEachType.OuterTwo, AfterEachType.OuterThree, + // [2] The outer afterEach closures are executed from top to bottom. + AfterEachType.OuterOne, AfterEachType.OuterTwo, AfterEachType.OuterThree, + // [3] The inner afterEach closures are executed from top to bottom, + // then the outer afterEach closures are executed from top to bottom. + AfterEachType.InnerOne, AfterEachType.InnerTwo, + AfterEachType.OuterOne, AfterEachType.OuterTwo, AfterEachType.OuterThree + ] + XCTAssertEqual(afterEachOrder, expectedOrder) + + afterEachOrder = [] + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift new file mode 100644 index 0000000..a770b5f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeEachTests.swift @@ -0,0 +1,76 @@ +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(BeforeEachType.OuterOne) } + beforeEach { beforeEachOrder.append(BeforeEachType.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(BeforeEachType.InnerOne) } + beforeEach { beforeEachOrder.append(BeforeEachType.InnerTwo) } + beforeEach { beforeEachOrder.append(BeforeEachType.InnerThree) } + + it("executes the outer and inner beforeEach closures [3]") {} + } + + context("when there are nested beforeEach without examples") { + beforeEach { beforeEachOrder.append(BeforeEachType.NoExamples) } + } + } +#if _runtime(_ObjC) && !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 = [ + // [1] The outer beforeEach closures are executed from top to bottom. + BeforeEachType.OuterOne, BeforeEachType.OuterTwo, + // [2] The outer beforeEach closures are executed from top to bottom. + BeforeEachType.OuterOne, BeforeEachType.OuterTwo, + // [3] The outer beforeEach closures are executed from top to bottom, + // then the inner beforeEach closures are executed from top to bottom. + BeforeEachType.OuterOne, BeforeEachType.OuterTwo, + BeforeEachType.InnerOne, BeforeEachType.InnerTwo, BeforeEachType.InnerThree + ] + XCTAssertEqual(beforeEachOrder, expectedOrder) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeSuiteTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BeforeSuiteTests.swift new file mode 100644 index 0000000..df39126 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BundleModuleNameTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/BundleModuleNameTests.swift new file mode 100644 index 0000000..4f99689 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEach.swift new file mode 100644 index 0000000..c3f6717 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/AfterEach/Configuration+AfterEachTests.swift new file mode 100644 index 0000000..d7c2105 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEach.swift new file mode 100644 index 0000000..228ab98 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/Configuration/BeforeEach/Configuration+BeforeEachTests.swift new file mode 100644 index 0000000..ddf1509 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift new file mode 100644 index 0000000..c626478 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ContextTests.swift @@ -0,0 +1,20 @@ +import XCTest +import Quick +import Nimble + +#if _runtime(_ObjC) && !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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CrossReferencingSpecs.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/CrossReferencingSpecs.swift new file mode 100644 index 0000000..56d1eb4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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() { + let _ = FunctionalTests_CrossReferencingSpecB() + it("does not crash") {} + } +} + +class FunctionalTests_CrossReferencingSpecB: QuickSpec { + override func spec() { + let _ = FunctionalTests_CrossReferencingSpecA() + it("does not crash") {} + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift new file mode 100644 index 0000000..875cf4e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/DescribeTests.swift @@ -0,0 +1,34 @@ +import XCTest +import Nimble +import Quick + +#if _runtime(_ObjC) && !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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ItTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ItTests.swift new file mode 100644 index 0000000..0973dc8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) && !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 _runtime(_ObjC) && !SWIFT_PACKAGE + func testAllExamplesAreExecuted() { + let result = qck_runSpec(FunctionalTests_ItSpec.self) + XCTAssertEqual(result?.executionCount, 10 as UInt) + } +#else + func testAllExamplesAreExecuted() { + let result = qck_runSpec(FunctionalTests_ItSpec.self) + XCTAssertEqual(result?.executionCount, 2 as UInt) + } +#endif +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/AfterEachTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/AfterEachTests+ObjC.m new file mode 100644 index 0000000..4216a86 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeEachTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeEachTests+ObjC.m new file mode 100644 index 0000000..c7a5897 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeSuiteTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/BeforeSuiteTests+ObjC.m new file mode 100644 index 0000000..ce7efc9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureTests+ObjC.m new file mode 100644 index 0000000..dc786e8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureUsingXCTAssertTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/FailureUsingXCTAssertTests+ObjC.m new file mode 100644 index 0000000..1f05853 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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.failureCount, 2); +} + +@end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/ItTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/ItTests+ObjC.m new file mode 100644 index 0000000..39e0b7d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/PendingTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/PendingTests+ObjC.m new file mode 100644 index 0000000..970175f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamples+BeforeEachTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamples+BeforeEachTests+ObjC.m new file mode 100644 index 0000000..cdbf259 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamplesTests+ObjC.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/ObjC/SharedExamplesTests+ObjC.m new file mode 100644 index 0000000..7fcb8b1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift new file mode 100644 index 0000000..e9951b5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/PendingTests.swift @@ -0,0 +1,54 @@ +import XCTest +import Quick +import Nimble + +var oneExampleBeforeEachExecutedCount = 0 +var onlyPendingExamplesBeforeEachExecutedCount = 0 + +class FunctionalTests_PendingSpec: QuickSpec { + override func spec() { + xit("an example that will not run") { + expect(true).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") {} + } + } +} + +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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamples+BeforeEachTests.swift new file mode 100644 index 0000000..2b0fd77 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamplesTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/FunctionalTests/SharedExamplesTests.swift new file mode 100644 index 0000000..d296601 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 _runtime(_ObjC) && !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 as UInt) + } + + func testSharedExamplesWithContextPassContextToExamples() { + let result = qck_runSpec(FunctionalTests_SharedExamples_ContextSpec.self) + XCTAssert(result!.hasSucceeded) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.h new file mode 100644 index 0000000..183118e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QCKSpecRunner.m new file mode 100644 index 0000000..a2aa78c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.h new file mode 100644 index 0000000..99e20f8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickSpec+QuickSpec_MethodList.m new file mode 100644 index 0000000..c648bd1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/QuickTestsBridgingHeader.h new file mode 100644 index 0000000..301c5d5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.h new file mode 100644 index 0000000..d69f808 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Helpers/XCTestObservationCenter+QCKSuspendObservation.m new file mode 100644 index 0000000..1a32e10 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/Info.plist new file mode 100644 index 0000000..6d32c15 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/QuickConfigurationTests.m b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/Tests/QuickTests/QuickTests/QuickConfigurationTests.m new file mode 100644 index 0000000..ace4577 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/script/release b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/release new file mode 100755 index 0000000..26409c4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-install-linux b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-install-linux new file mode 100755 index 0000000..279cd88 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-install-macos b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-install-macos new file mode 100755 index 0000000..64edf92 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-script-linux b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-script-linux new file mode 100755 index 0000000..7a6558d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-script-macos b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Quick/script/travis-script-macos new file mode 100755 index 0000000..ac60f1c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Result/.gitignore b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.gitignore new file mode 100644 index 0000000..29471cb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +xcuserdata +*.xcuserdatad +*.xccheckout +*.mode* +*.pbxuser + +Carthage/Build +.build diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.swift-version b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.travis.yml b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.travis.yml new file mode 100644 index 0000000..17ee849 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/.travis.yml @@ -0,0 +1,44 @@ +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 1080p" | xcpretty + - xcodebuild build -scheme Result-watchOS -sdk watchsimulator | xcpretty + # - pod lib lint + env: + - JOB=Xcode + - XCODE_ACTION="build-for-testing test-without-building" + os: osx + osx_image: xcode8 + language: objective-c + - script: + - swift build + - swift test + env: JOB=SPM + os: osx + osx_image: xcode8 + language: objective-c + - script: + - 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)" + - script: + - swift build + - swift test + env: + - JOB=Linux + - SWIFT_VERSION=3.1-DEVELOPMENT-SNAPSHOT-2017-03-01-a + 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/ReactiveSwift/Carthage/Checkouts/Result/CONTRIBUTING.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/CONTRIBUTING.md new file mode 100644 index 0000000..f58c3fa --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Result/LICENSE b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/LICENSE new file mode 100644 index 0000000..3026ee1 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Result/Package.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Package.swift new file mode 100644 index 0000000..3004377 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Package.swift @@ -0,0 +1,10 @@ +import PackageDescription + +let package = Package( + name: "Result", + targets: [ + Target( + name: "Result" + ) + ] +) diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/README.md new file mode 100644 index 0000000..7343ade --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 in 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/ReactiveSwift/Carthage/Checkouts/Result/Result.podspec b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.podspec new file mode 100644 index 0000000..887ac0d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = 'Result' + s.version = '3.2.1' + 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' +end diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ca9516b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj @@ -0,0 +1,1012 @@ +// !$*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 */; }; + 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 = ""; }; + 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 = ( + 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 = ( + 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 = 0800; + ORGANIZATIONNAME = "Rob Rix"; + TargetAttributes = { + 57FCDE3C1BA280DC00130C48 = { + LastSwiftMigration = 0800; + }; + 57FCDE491BA280E000130C48 = { + LastSwiftMigration = 0800; + }; + D03579991B2B788F005D26AE = { + LastSwiftMigration = 0800; + }; + D45480561A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0800; + }; + D45480661A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0800; + }; + D454807C1A957361009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0800; + }; + D45480861A957362009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0800; + }; + }; + }; + 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 = ( + 57FCDE3E1BA280DC00130C48 /* ResultProtocol.swift in Sources */, + 57FCDE3F1BA280DC00130C48 /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 57FCDE4C1BA280E000130C48 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 57FCDE4D1BA280E000130C48 /* ResultTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799A1B2B788F005D26AE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 45AE89E61B3A6564007B99D7 /* ResultProtocol.swift in Sources */, + D035799B1B2B788F005D26AE /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480521A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E93621461B35596200948F2A /* ResultProtocol.swift in Sources */, + D45480971A957465009D7229 /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480631A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D454806F1A9572F5009D7229 /* ResultTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480781A957361009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E93621471B35596200948F2A /* ResultProtocol.swift in Sources */, + D45480981A957465009D7229 /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480831A957362009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480991A9574B8009D7229 /* ResultTests.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=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; + SWIFT_VERSION = 3.0; + 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=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; + SWIFT_VERSION = 3.0; + 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; + SWIFT_VERSION = 3.0; + }; + 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; + SWIFT_VERSION = 3.0; + 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=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; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + D03579A21B2B788F005D26AE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "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; + SWIFT_VERSION = 3.0; + }; + 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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + 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_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"; + 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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + 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_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"; + 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; + SWIFT_VERSION = 3.0; + 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; + SWIFT_VERSION = 3.0; + 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)"; + SWIFT_VERSION = 3.0; + }; + 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)"; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; + D45480901A957362009D7229 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "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; + SWIFT_VERSION = 3.0; + 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=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; + SWIFT_VERSION = 3.0; + 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; + SWIFT_VERSION = 3.0; + }; + 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; + SWIFT_VERSION = 3.0; + 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/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..10cf711 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme new file mode 100644 index 0000000..1af5f9a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-Mac.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme new file mode 100644 index 0000000..d7935af --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-iOS.xcscheme @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme new file mode 100644 index 0000000..6cb5a66 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-tvOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme new file mode 100644 index 0000000..1228755 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result.xcodeproj/xcshareddata/xcschemes/Result-watchOS.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/Info.plist new file mode 100644 index 0000000..5466556 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 + 3.2.1 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2015 Rob Rix. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/Result.h b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/Result.h new file mode 100644 index 0000000..4742701 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/Result/Result/Result.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/Result.swift new file mode 100644 index 0000000..b08ea8e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/Result.swift @@ -0,0 +1,271 @@ +// 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(T) + case failure(Error) + + // MARK: Constructors + + /// Constructs a success wrapping a `value`. + public init(value: T) { + 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: T?, 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 -> T) { + self.init(attempt: f) + } + + /// Constructs a result from a function that uses `throw`, failing with `Error` if throws. + public init(attempt f: () throws -> T) { + do { + self = .success(try f()) + } catch { + self = .failure(error as! Error) + } + } + + // MARK: Deconstruction + + /// Returns the value from `success` Results or `throw`s the error. + public func dematerialize() throws -> T { + 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: (T) -> 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 { + return analysis( + ifSuccess: { ".success(\($0))" }, + ifFailure: { ".failure(\($0))" }) + } + + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + return description + } +} + +// MARK: - Derive result from failable closure + +public func materialize(_ f: () throws -> T) -> Result { + return materialize(try f()) +} + +public func materialize(_ f: @autoclosure () throws -> T) -> Result { + do { + return .success(try f()) + } catch { + return .failure(AnyError(error)) + } +} + +@available(*, deprecated, message: "Use the overload which returns `Result` instead") +public func materialize(_ f: () throws -> T) -> Result { + return materialize(try f()) +} + +@available(*, deprecated, message: "Use the overload which returns `Result` instead") +public func materialize(_ f: @autoclosure () throws -> T) -> Result { + do { + return .success(try f()) + } catch { +// This isn't great, but it lets us maintain compatibility until this deprecated +// method can be removed. +#if _runtime(_ObjC) + return .failure(error as NSError) +#else + // https://github.com/apple/swift-corelibs-foundation/blob/swift-3.0.2-RELEASE/Foundation/NSError.swift#L314 + let userInfo = _swift_Foundation_getErrorDefaultUserInfo(error) as? [String: Any] + let nsError = NSError(domain: error._domain, code: error._code, userInfo: userInfo) + return .failure(nsError) +#endif + } +} + +// MARK: - Cocoa API conveniences + +#if !os(Linux) + +/// 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) } +public func `try`(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> T?) -> Result { + var error: NSError? + return `try`(&error).map(Result.success) ?? .failure(error ?? Result.error(function: function, file: file, line: line)) +} + +/// 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) } +public func `try`(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> Bool) -> Result<(), NSError> { + var error: NSError? + return `try`(&error) ? + .success(()) + : .failure(error ?? Result<(), NSError>.error(function: function, file: file, line: line)) +} + +#endif + +// MARK: - ErrorProtocolConvertible conformance + +extension NSError: ErrorProtocolConvertible { + public static func error(from error: Swift.Error) -> Self { + func cast(_ error: Swift.Error) -> T { + return error as! T + } + + return cast(error) + } +} + +// MARK: - Errors + +/// 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 + } +} + +/// 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: ErrorProtocolConvertible { + public static func error(from error: Error) -> AnyError { + return AnyError(error) + } +} + +extension AnyError: CustomStringConvertible { + public var description: String { + return String(describing: error) + } +} + +// There appears to be a bug in Foundation on Linux which prevents this from working: +// https://bugs.swift.org/browse/SR-3565 +// Don't forget to comment the tests back in when removing this check when it's fixed! +#if !os(Linux) + +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 + } +} + +#endif + +// MARK: - migration support +extension Result { + @available(*, unavailable, renamed: "success") + public static func Success(_: T) -> Result { + fatalError() + } + + @available(*, unavailable, renamed: "failure") + public static func Failure(_: Error) -> Result { + fatalError() + } +} + +extension NSError { + @available(*, unavailable, renamed: "error(from:)") + public static func errorFromErrorType(_ error: Swift.Error) -> Self { + fatalError() + } +} + +import Foundation diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/ResultProtocol.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/ResultProtocol.swift new file mode 100644 index 0000000..165567a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Result/ResultProtocol.swift @@ -0,0 +1,200 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// A type that can represent either failure with an error or success with a result value. +public protocol ResultProtocol { + associatedtype Value + associatedtype Error: Swift.Error + + /// Constructs a successful result wrapping a `value`. + init(value: Value) + + /// Constructs a failed result wrapping an `error`. + init(error: Error) + + /// Case analysis for ResultProtocol. + /// + /// Returns the value produced by appliying `ifFailure` to the error if self represents a failure, or `ifSuccess` to the result value if self represents a success. + func analysis(ifSuccess: (Value) -> U, ifFailure: (Error) -> U) -> U + + /// Returns the value if self represents a success, `nil` otherwise. + /// + /// A default implementation is provided by a protocol extension. Conforming types may specialize it. + var value: Value? { get } + + /// Returns the error if self represents a failure, `nil` otherwise. + /// + /// A default implementation is provided by a protocol extension. Conforming types may specialize it. + var error: Error? { get } +} + +public extension ResultProtocol { + + /// Returns the value if self represents a success, `nil` otherwise. + public var value: Value? { + return analysis(ifSuccess: { $0 }, ifFailure: { _ in nil }) + } + + /// Returns the error if self represents a failure, `nil` otherwise. + public var error: Error? { + return analysis(ifSuccess: { _ in nil }, ifFailure: { $0 }) + } + + /// 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 { + return analysis( + ifSuccess: transform, + ifFailure: Result.failure) + } + + /// 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 () -> R) -> Result<(Value, R.Value), Error> + where Error == R.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 { + return analysis( + ifSuccess: Result.success, + ifFailure: transform) + } + + /// 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 { + return analysis( + ifSuccess: { .success(success($0)) }, + ifFailure: { .failure(failure($0)) } + ) + } +} + +public extension ResultProtocol { + + // 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 () -> Self) -> Self { + return analysis( + ifSuccess: { _ in self }, + ifFailure: { _ in result() }) + } +} + +/// Protocol used to constrain `tryMap` to `Result`s with compatible `Error`s. +public protocol ErrorProtocolConvertible: Swift.Error { + static func error(from error: Swift.Error) -> Self +} + +public extension ResultProtocol where Error: ErrorProtocolConvertible { + + /// 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 + +infix operator &&& : LogicalConjunctionPrecedence + +/// Returns a Result with a tuple of `left` and `right` values if both are `Success`es, or re-wrapping the error of the earlier `Failure`. +@available(*, deprecated, renamed: "ResultProtocol.fanout(self:_:)") +public func &&& (left: L, right: @autoclosure () -> R) -> Result<(L.Value, R.Value), L.Error> + where L.Error == R.Error +{ + return left.fanout(right) +} + +precedencegroup ChainingPrecedence { + associativity: left + higherThan: TernaryPrecedence +} + +infix operator >>- : ChainingPrecedence + +/// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors. +/// +/// This is a synonym for `flatMap`. +@available(*, deprecated, renamed: "ResultProtocol.flatMap(self:_:)") +public func >>- (result: T, transform: (T.Value) -> Result) -> Result { + return result.flatMap(transform) +} + +/// 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 func == (left: T, right: T) -> Bool + where T.Value: Equatable, T.Error: Equatable +{ + 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 +} + +/// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values. +public func != (left: T, right: T) -> Bool + where T.Value: Equatable, T.Error: Equatable +{ + return !(left == right) +} + +/// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits. +public func ?? (left: T, right: @autoclosure () -> T.Value) -> T.Value { + return left.recover(right()) +} + +/// Returns `left` if it is a `Success`es, or `right` otherwise. Short-circuits. +public func ?? (left: T, right: @autoclosure () -> T) -> T { + return left.recover(with: right()) +} + +// MARK: - migration support +@available(*, unavailable, renamed: "ResultProtocol") +public typealias ResultType = ResultProtocol + +@available(*, unavailable, renamed: "Error") +public typealias ResultErrorType = Swift.Error + +@available(*, unavailable, renamed: "ErrorProtocolConvertible") +public typealias ErrorTypeConvertible = ErrorProtocolConvertible + +extension ResultProtocol { + @available(*, unavailable, renamed: "recover(with:)") + public func recoverWith(_ result: @autoclosure () -> Self) -> Self { + fatalError() + } +} + +extension ErrorProtocolConvertible { + @available(*, unavailable, renamed: "error(from:)") + public static func errorFromErrorType(_ error: Swift.Error) -> Self { + fatalError() + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/LinuxMain.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/LinuxMain.swift new file mode 100644 index 0000000..b23e8fc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/LinuxMain.swift @@ -0,0 +1,8 @@ +import XCTest + +@testable import ResultTests + +XCTMain([ + testCase(ResultTests.allTests), + testCase(NoErrorTests.allTests), +]) diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist new file mode 100644 index 0000000..43869a4 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 + 3.2.1 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift new file mode 100644 index 0000000..5a5a8f5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift @@ -0,0 +1,349 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +final class ResultTests: XCTestCase { + func testMapTransformsSuccesses() { + XCTAssertEqual(success.map { $0.characters.count } ?? 0, 7) + } + + func testMapRewrapsFailures() { + XCTAssertEqual(failure.map { $0.characters.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.characters.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) + } + +// These tests fail on linux, root cause possibly https://bugs.swift.org/browse/SR-3565 +// Try again when it's fixed + #if !os(Linux) + + 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") + } + + #endif + + // 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 testMaterializeProducesSuccesses() { + let result1: Result = materialize(try tryIsSuccess("success")) + XCTAssert(result1 == success) + + let result2: Result = materialize { try tryIsSuccess("success") } + XCTAssert(result2 == success) + } + + func testMaterializeProducesFailures() { + let result1: Result = materialize(try tryIsSuccess(nil)) + XCTAssert(result1.error == error) + + let result2: Result = materialize { try tryIsSuccess(nil) } + XCTAssert(result2.error == error) + } + + // 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) + } + + // MARK: Cocoa API idioms + + #if !os(Linux) + + func testTryProducesFailuresForBooleanAPIWithErrorReturnedByReference() { + let result = `try` { attempt(true, succeed: false, error: $0) } + XCTAssertFalse(result ?? false) + XCTAssertNotNil(result.error) + } + + func testTryProducesFailuresForOptionalWithErrorReturnedByReference() { + let result = `try` { attempt(1, succeed: false, error: $0) } + XCTAssertEqual(result ?? 0, 0) + XCTAssertNotNil(result.error) + } + + func testTryProducesSuccessesForBooleanAPI() { + let result = `try` { attempt(true, succeed: true, error: $0) } + XCTAssertTrue(result ?? false) + XCTAssertNil(result.error) + } + + func testTryProducesSuccessesForOptionalAPI() { + let result = `try` { attempt(1, succeed: true, error: $0) } + XCTAssertEqual(result ?? 0, 1) + XCTAssertNil(result.error) + } + + #endif + + func testTryMapProducesSuccess() { + let result = success.tryMap(tryIsSuccess) + XCTAssert(result == success) + } + + func testTryMapProducesFailure() { + let result = Result.success("fail").tryMap(tryIsSuccess) + XCTAssert(result == failure) + } +} + +final class NoErrorTests: XCTestCase { + static var allTests: [(String, (NoErrorTests) -> () throws -> Void)] { + return [ ("testEquatable", testEquatable) ] + } + + func testEquatable() { + let foo = Result(1) + let bar = Result(1) + XCTAssertTrue(foo == bar) + } +} + + +// MARK: - Fixtures + +private 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 + } +} + +#if !os(Linux) + +func attempt(_ value: T, succeed: Bool, error: NSErrorPointer) -> T? { + if succeed { + return value + } else { + error?.pointee = Result<(), NSError>.error() + return nil + } +} + +#endif + +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 + } +} + +#if os(Linux) + +extension ResultTests { + static var allTests: [(String, (ResultTests) -> () throws -> Void)] { + return [ + ("testMapTransformsSuccesses", testMapTransformsSuccesses), + ("testMapRewrapsFailures", testMapRewrapsFailures), + ("testInitOptionalSuccess", testInitOptionalSuccess), + ("testInitOptionalFailure", testInitOptionalFailure), + ("testFanout", testFanout), + ("testBimapTransformsSuccesses", testBimapTransformsSuccesses), + ("testBimapTransformsFailures", testBimapTransformsFailures), + ("testErrorsIncludeTheSourceFile", testErrorsIncludeTheSourceFile), + ("testErrorsIncludeTheSourceLine", testErrorsIncludeTheSourceLine), + ("testErrorsIncludeTheCallingFunction", testErrorsIncludeTheCallingFunction), + ("testTryCatchProducesSuccesses", testTryCatchProducesSuccesses), + ("testTryCatchProducesFailures", testTryCatchProducesFailures), + ("testTryCatchWithFunctionProducesSuccesses", testTryCatchWithFunctionProducesSuccesses), + ("testTryCatchWithFunctionCatchProducesFailures", testTryCatchWithFunctionCatchProducesFailures), + ("testMaterializeProducesSuccesses", testMaterializeProducesSuccesses), + ("testMaterializeProducesFailures", testMaterializeProducesFailures), + ("testRecoverProducesLeftForLeftSuccess", testRecoverProducesLeftForLeftSuccess), + ("testRecoverProducesRightForLeftFailure", testRecoverProducesRightForLeftFailure), + ("testRecoverWithProducesLeftForLeftSuccess", testRecoverWithProducesLeftForLeftSuccess), + ("testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess", testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess), + ("testRecoverWithProducesRightFailureForLeftFailureAndRightFailure", testRecoverWithProducesRightFailureForLeftFailureAndRightFailure), +// ("testTryProducesFailuresForBooleanAPIWithErrorReturnedByReference", testTryProducesFailuresForBooleanAPIWithErrorReturnedByReference), +// ("testTryProducesFailuresForOptionalWithErrorReturnedByReference", testTryProducesFailuresForOptionalWithErrorReturnedByReference), +// ("testTryProducesSuccessesForBooleanAPI", testTryProducesSuccessesForBooleanAPI), +// ("testTryProducesSuccessesForOptionalAPI", testTryProducesSuccessesForOptionalAPI), + ("testTryMapProducesSuccess", testTryMapProducesSuccess), + ("testTryMapProducesFailure", testTryMapProducesFailure), + +// These tests fail on linux, root cause possibly https://bugs.swift.org/browse/SR-3565 +// Try again when it's fixed +// ("testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError", testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError), +// ("testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError", testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError), +// ("testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError", testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError), +// ("testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError", testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError), + ] + } +} + +#endif + +import Foundation +import Result +import XCTest diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/.gitignore b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/.gitignore new file mode 100644 index 0000000..b29206a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/.gitignore @@ -0,0 +1 @@ +Carthage/Build diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Common.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Common.xcconfig new file mode 100644 index 0000000..26cea4b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Common.xcconfig @@ -0,0 +1,190 @@ +// +// 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 + +// Warn about implicit capture of self (e.g. direct ivar access) +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = 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 + +// This warnings detects when a function will recursively call itself on every +// code path though that function. More information can be found here: +// http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20131216/096004.html +CLANG_WARN_INFINITE_RECURSION = YES + +// This warning detects suspicious uses of std::move. +CLANG_WARN_SUSPICIOUS_MOVE = YES diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Debug.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Debug.xcconfig new file mode 100644 index 0000000..6ef0040 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Profile.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Profile.xcconfig new file mode 100644 index 0000000..0d01553 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Release.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Release.xcconfig new file mode 100644 index 0000000..c83729b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Test.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Configurations/Test.xcconfig new file mode 100644 index 0000000..2da35e8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/Application.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/Application.xcconfig new file mode 100644 index 0000000..a91feca --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/Framework.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/Framework.xcconfig new file mode 100644 index 0000000..c92f57f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/Framework.xcconfig @@ -0,0 +1,37 @@ +// +// This file defines additional configuration options that are appropriate only +// for a framework. Typically, you want to use a platform-specific variant +// instead. +// + +// Disable code signing for successful device builds with Xcode 8. Frameworks do +// need to be signed, but they don't need to be signed at compile time because +// they'll be re-signed when you include them in your app. +CODE_SIGNING_REQUIRED = NO +CODE_SIGN_IDENTITY = + +// 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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/StaticLibrary.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Base/Targets/StaticLibrary.xcconfig new file mode 100644 index 0000000..b3b2b87 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Application.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Application.xcconfig new file mode 100644 index 0000000..2e552c7 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Base.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Base.xcconfig new file mode 100644 index 0000000..8fdeccc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-DynamicLibrary.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-DynamicLibrary.xcconfig new file mode 100644 index 0000000..1e2a37c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Framework.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-Framework.xcconfig new file mode 100644 index 0000000..dd98764 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-StaticLibrary.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/Mac OS X/Mac-StaticLibrary.xcconfig new file mode 100644 index 0000000..97d0318 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/README.md b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/README.md new file mode 100644 index 0000000..8b69024 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-Application.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-Application.xcconfig new file mode 100644 index 0000000..a700868 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-Base.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-Base.xcconfig new file mode 100644 index 0000000..f45f905 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-Framework.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-Framework.xcconfig new file mode 100644 index 0000000..e538a7d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-StaticLibrary.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/iOS/iOS-StaticLibrary.xcconfig new file mode 100644 index 0000000..7e3b507 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Application.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Application.xcconfig new file mode 100644 index 0000000..74f892c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 tvOS. 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 tvOS +#include "tvOS-Base.xcconfig" diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Base.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Base.xcconfig new file mode 100644 index 0000000..e5cb616 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Base.xcconfig @@ -0,0 +1,15 @@ +// +// This file defines additional configuration options that are appropriate only +// for tvOS. 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/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Framework.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-Framework.xcconfig new file mode 100644 index 0000000..cb08820 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 tvOS. 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/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-StaticLibrary.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/tvOS/tvOS-StaticLibrary.xcconfig new file mode 100644 index 0000000..34d0200 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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 tvOS. 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 tvOS +#include "tvOS-Base.xcconfig" diff --git a/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Application.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Application.xcconfig new file mode 100644 index 0000000..5d88df9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Base.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Base.xcconfig new file mode 100644 index 0000000..21e4a82 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Framework.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-Framework.xcconfig new file mode 100644 index 0000000..3893494 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-StaticLibrary.xcconfig b/Carthage/Checkouts/ReactiveSwift/Carthage/Checkouts/xcconfigs/watchOS/watchOS-StaticLibrary.xcconfig new file mode 100644 index 0000000..b9f92d8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/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/ReactiveSwift/CodeOfConduct.md b/Carthage/Checkouts/ReactiveSwift/CodeOfConduct.md new file mode 100644 index 0000000..9974280 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/CodeOfConduct.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 members of [the ReactiveSwift team](https://github.com/orgs/ReactiveCocoa/teams/reactiveswift). 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/ReactiveSwift/Documentation/APIContracts.md b/Carthage/Checkouts/ReactiveSwift/Documentation/APIContracts.md new file mode 100644 index 0000000..f62daa8 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Documentation/APIContracts.md @@ -0,0 +1,568 @@ +# Design Guidelines + +This document contains guidelines for projects that want to make use of +ReactiveSwift. The content here is heavily inspired by the [Rx Design +Guidelines](http://blogs.msdn.com/b/rxteam/archive/2010/10/28/rx-design-guidelines.aspx). + +This document assumes basic familiarity +with the features of ReactiveSwift. The [Framework Overview][] is a better +resource for getting up to speed on the main types and concepts provided by ReactiveSwift. + +**[The `Event` contract](#the-event-contract)** + + 1. [`value`s provide values or indicate the occurrence of events](#values-provide-values-or-indicate-the-occurrence-of-events) + 1. [`failure`s behave like exceptions and propagate immediately](#failures-behave-like-exceptions-and-propagate-immediately) + 1. [`completion` indicates success](#completion-indicates-success) + 1. [`interruption`s cancel outstanding work and usually propagate immediately](#interruptions-cancel-outstanding-work-and-usually-propagate-immediately) + 1. [Events are serial](#events-are-serial) + 1. [Events are never delivered recursively, and values cannot be sent recursively](#events-are-never-delivered-recursively-and-values-cannot-be-sent-recursively) + 1. [Events are sent synchronously by default](#events-are-sent-synchronously-by-default) + +**[The `Signal` contract](#the-signal-contract)** + + 1. [Signals start work when instantiated](#signals-start-work-when-instantiated) + 1. [Observing a signal does not have side effects](#observing-a-signal-does-not-have-side-effects) + 1. [All observers of a signal see the same events in the same order](#all-observers-of-a-signal-see-the-same-events-in-the-same-order) + 1. [A signal is alive as long as it is publicly reachable or is being observed](#a-signal-is-alive-as-long-as-it-is-publicly-reachable-or-is-being-observed) + 1. [Terminating events dispose of signal resources](#terminating-events-dispose-of-signal-resources) + +**[The `SignalProducer` contract](#the-signalproducer-contract)** + + 1. [Signal producers start work on demand by creating signals](#signal-producers-start-work-on-demand-by-creating-signals) + 1. [Each produced signal may send different events at different times](#each-produced-signal-may-send-different-events-at-different-times) + 1. [Signal operators can be lifted to apply to signal producers](#signal-operators-can-be-lifted-to-apply-to-signal-producers) + 1. [Disposing of a produced signal will interrupt it](#disposing-of-a-produced-signal-will-interrupt-it) + + +**[The Property contract](#the-property-contract)** + + 1. [A property must have its latest value sent synchronously accessible](#a-property-must-have-its-latest-value-sent-synchronously-accessible) + 1. [Events must be synchronously emitted after the mutation is visible](#events-must-be-synchronously-emitted-after-the-mutation-is-visible) + 1. [Reentrancy must be supported for reads](#reentrancy-must-be-supported-for-reads) + 1. [A composed property does not have a side effect on its sources, and does not own its lifetime](#a-composed-property-does-not-have-a-side-effect-on-its-sources-and-does-not-own-its-lifetime) + +**[Best practices](#best-practices)** + + 1. [Process only as many values as needed](#process-only-as-many-values-as-needed) + 1. [Observe events on a known scheduler](#observe-events-on-a-known-scheduler) + 1. [Switch schedulers in as few places as possible](#switch-schedulers-in-as-few-places-as-possible) + 1. [Capture side effects within signal producers](#capture-side-effects-within-signal-producers) + 1. [Share the side effects of a signal producer by sharing one produced signal](#share-the-side-effects-of-a-signal-producer-by-sharing-one-produced-signal) + 1. [Prefer managing lifetime with operators over explicit disposal](#prefer-managing-lifetime-with-operators-over-explicit-disposal) + +**[Implementing new operators](#implementing-new-operators)** + + 1. [Prefer writing operators that apply to both signals and producers](#prefer-writing-operators-that-apply-to-both-signals-and-producers) + 1. [Compose existing operators when possible](#compose-existing-operators-when-possible) + 1. [Forward failure and interruption events as soon as possible](#forward-failure-and-interruption-events-as-soon-as-possible) + 1. [Switch over `Event` values](#switch-over-event-values) + 1. [Avoid introducing concurrency](#avoid-introducing-concurrency) + 1. [Avoid blocking in operators](#avoid-blocking-in-operators) + +## The `Event` contract + +[Events][] are fundamental to ReactiveSwift. [Signals][] and [signal producers][] both send +events, and may be collectively called “event streams.” + +Event streams must conform to the following grammar: + +``` +value* (interrupted | failed | completed)? +``` + +This states that an event stream consists of: + + 1. Any number of `value` events + 1. Optionally followed by one terminating event, which is any of `interrupted`, `failed`, or `completed` + +After a terminating event, no other events will be received. + +#### `value`s provide values or indicate the occurrence of events + +`value` events contain a payload known as the “value”. Only `value` events are +said to have a value. Since an event stream can contain any number of `value`s, +there are few restrictions on what those values can mean or be used for, except +that they must be of the same type. + +As an example, the value might represent an element from a collection, or +a progress update about some long-running operation. The value of a `value` event +might even represent nothing at all—for example, it’s common to use a value type +of `()` to indicate that something happened, without being more specific about +what that something was. + +Most of the event stream [operators][] act upon `value` events, as they represent the +“meaningful data” of a signal or producer. + +#### `failure`s behave like exceptions and propagate immediately + +`failed` events indicate that something went wrong, and contain a concrete error +that indicates what happened. Failures are fatal, and propagate as quickly as +possible to the consumer for handling. + +Failures also behave like exceptions, in that they “skip” operators, terminating +them along the way. In other words, most [operators][] immediately stop doing +work when a failure is received, and then propagate the failure onward. This even applies to time-shifted operators, like [`delay`][delay]—which, despite its name, will forward any failures immediately. + +Consequently, failures should only be used to represent “abnormal” termination. If it is important to let operators (or consumers) finish their work, a `value` +event describing the result might be more appropriate. + +If an event stream can _never_ fail, it should be parameterized with the +special [`NoError`][NoError] type, which statically guarantees that a `failed` +event cannot be sent upon the stream. + +#### `completion` indicates success + +An event stream sends `completed` when the operation has completed successfully, +or to indicate that the stream has terminated normally. + +Many operators manipulate the `completed` event to shorten or extend the +lifetime of an event stream. + +For example, [`take`][take] will complete after the specified number of values have +been received, thereby terminating the stream early. On the other hand, most +operators that accept multiple signals or producers will wait until _all_ of +them have completed before forwarding a `completed` event, since a successful +outcome will usually depend on all the inputs. + +#### `interruption`s cancel outstanding work and usually propagate immediately + +An `interrupted` event is sent when an event stream should cancel processing. +Interruption is somewhere between [success](#completion-indicates-success) +and [failure](#failures-behave-like-exceptions-and-propagate-immediately)—the +operation was not successful, because it did not get to finish, but it didn’t +necessarily “fail” either. + +Most [operators][] will propagate interruption immediately, but there are some +exceptions. For example, the [flattening operators][flatten] will ignore +`interrupted` events that occur on the _inner_ producers, since the cancellation +of an inner operation should not necessarily cancel the larger unit of work. + +ReactiveSwift will automatically send an `interrupted` event upon [disposal][Disposables], but it can +also be sent manually if necessary. Additionally, [custom +operators](#implementing-new-operators) must make sure to forward interruption +events to the observer. + +#### Events are serial + +ReactiveSwift guarantees that all events upon a stream will arrive serially. In other +words, it’s impossible for the observer of a signal or producer to receive +multiple `Event`s concurrently, even if the events are sent on multiple threads +simultaneously. + +This simplifies [operator][Operators] implementations and [observers][]. + +#### Events are never delivered recursively, and values cannot be sent recursively. + +Just like [the guarantee of events not being delivered +concurrently](#events-are-serial), it is also guaranteed that events would not be +delivered recursively. As a consequence, [operators][] and [observers][] _do not_ need to +be reentrant. + +If a `value` event is sent upon a signal from a thread that is _already processing_ +a previous event from that signal, it would result in a deadlock. This is because +recursive signals are usually programmer error, and the determinacy of +a deadlock is preferable to nondeterministic race conditions. + +Note that a terminal event is permitted to be sent recursively. + +When a recursive signal is explicitly desired, the recursive event should be +time-shifted, with an operator like [`delay`][delay], to ensure that it isn’t sent from +an already-running event handler. + +#### Events are sent synchronously by default + +ReactiveSwift does not implicitly introduce concurrency or asynchrony. [Operators][] that +accept a [scheduler][Schedulers] may, but they must be explicitly invoked by the consumer of +the framework. + +A “vanilla” signal or producer will send all of its events synchronously by +default, meaning that the [observer][Observers] will be synchronously invoked for each event +as it is sent, and that the underlying work will not resume until the event +handler finishes. + +This is similar to how `NSNotificationCenter` or `UIControl` events are +distributed. + +## The `Signal` contract + +A [signal][Signals] is a stream of values that obeys [the `Event` contract](#the-event-contract). + +`Signal` is a reference type, because each signal has identity — in other words, each +signal has its own lifetime, and may eventually terminate. Once terminated, +a signal cannot be restarted. + +#### Signals start work when instantiated + +[`Signal.init`][Signal.init] immediately executes the generator closure that is passed to it. +This means that side effects may occur even before the initializer returns. + +It is also possible to send [events][] before the initializer returns. However, +since it is impossible for any [observers][] to be attached at this point, any +events sent this way cannot be received. + +#### Observing a signal does not have side effects + +The work associated with a `Signal` does not start or stop when [observers][] are +added or removed, so the [`observe`][observe] method (or the cancellation thereof) never +has side effects. + +A signal’s side effects can only be stopped through [a terminating event](#signals-are-retained-until-a-terminating-event-occurs), or by a silent disposal at the point that [the signal is neither publicly reachable nor being observed](#a-signal-is-alive-as-long-as-it-is-publicly-reachable-or-is-being-observed). + +#### All observers of a signal see the same events in the same order + +Because [observation does not have side +effects](#observing-a-signal-does-not-have-side-effects), a `Signal` never +customizes events for different [observers][]. When an event is sent upon a signal, +it will be [synchronously](#events-are-sent-synchronously-by-default) +distributed to all observers that are attached at that time, much like +how `NSNotificationCenter` sends notifications. + +In other words, there are not different event “timelines” per observer. All +observers effectively see the same stream of events. + +There is one exception to this rule: adding an observer to a signal _after_ it +has already terminated will result in exactly one +[`interrupted`](#interruption-cancels-outstanding-work-and-usually-propagates-immediately) +event sent to that specific observer. + +#### A signal is alive as long as it is publicly reachable or is being observed + +A `Signal` must be publicly retained for attaching new observers, but not +necessarily for keeping the stream of events alive. Moreover, a `Signal` retains +itself as long as there is still an active observer. + +In other words, if a `Signal` is neither publicly retained nor being observed, +it would dispose of the signal resources silently. + +Note that the input observer of a signal does not retain the signal itself. + +Long-running side effects are recommended to be modeled as an observer to the +signal. + +#### Terminating events dispose of signal resources + +When a terminating [event][Events] is sent along a `Signal`, all [observers][] will be +released, and any resources being used to generate events should be disposed of. + +The easiest way to ensure proper resource cleanup is to return a [disposable][Disposables] +from the generator closure, which will be disposed of when termination occurs. +The disposable should be responsible for releasing memory, closing file handles, +canceling network requests, or anything else that may have been associated with +the work being performed. + +## The `SignalProducer` contract + +A [signal producer][Signal Producers] is like a “recipe” for creating +[signals][]. Signal producers do not do anything by themselves—[work begins only +when a signal is produced](#signal-producers-start-work-on-demand-by-creating-signals). + +Since a signal producer is just a declaration of _how_ to create signals, it is +a value type, and has no memory management to speak of. + +#### Signal producers start work on demand by creating signals + +The [`start`][start] and [`startWithSignal`][startWithSignal] methods each +produce a `Signal` (implicitly and explicitly, respectively). After +instantiating the signal, the closure that was passed to +[`SignalProducer.init`][SignalProducer.init] will be executed, to start the flow +of [events][] after any observers have been attached. + +Although the producer itself is not _really_ responsible for the execution of +work, it’s common to speak of “starting” and “canceling” a producer. These terms +refer to producing a `Signal` that will start work, and [disposing of that +signal](#disposing-of-a-produced-signal-will-interrupt-it) to stop work. + +A producer can be started any number of times (including zero), and the work +associated with it will execute exactly that many times as well. + +#### Each produced signal may send different events at different times + +Because signal producers [start work on +demand](#signal-producers-start-work-on-demand-by-creating-signals), there may +be different [observers][] associated with each execution, and those observers +may see completely different [event][Events] timelines. + +In other words, events are generated from scratch for each time the producer is +started, and can be completely different (or in a completely different order) +from other times the producer is started. + +Nonetheless, each execution of a signal producer will follow [the `Event` +contract](#the-event-contract). + +#### Signal operators can be lifted to apply to signal producers + +Due to the relationship between signals and signal producers, it is possible to +automatically promote any [operators][] over one or more `Signal`s to apply to +the same number of `SignalProducer`s instead, using the [`lift`][lift] method. + +`lift` will apply the behavior of the specified operator to each `Signal` that +is [created when the signal producer is started](#signal-producers-start-work-on-demand-by-creating-signals). + +#### Disposing of a produced signal will interrupt it + +When a producer is started using the [`start`][start] or +[`startWithSignal`][startWithSignal] methods, a [`Disposable`][Disposables] is +automatically created and passed back. + +Disposing of this object will +[interrupt](#interruption-cancels-outstanding-work-and-usually-propagates-immediately) +the produced `Signal`, thereby canceling outstanding work and sending an +`interrupted` [event][Events] to all [observers][], and will also dispose of +everything added to the [`CompositeDisposable`][CompositeDisposable] in +[SignalProducer.init]. + +Note that disposing of one produced `Signal` will not affect other signals created +by the same `SignalProducer`. + +## The Property contract. + +A property is essentially a `Signal` which guarantees it has an initial value, and its latest value is always available for being read out. + +All read-only property types should conform to `PropertyProtocol`, while the mutable counterparts should conform to `MutablePropertyProtocol`. ReactiveSwift includes two primitives that implement the contract: `Property` and `MutableProperty`. + +#### A property must have its latest value sent synchronously accessible. + +A property must have its latest value cached or stored at any point of time. It must be synchronously accessible through `PropertyProtocol.value`. + +The `SignalProducer` of a property must replay the latest value before forwarding subsequent changes, and it may ensure that no race condition exists between the replaying and the setup of the forwarding. + +#### Events must be synchronously emitted after the mutation is visible. + +A mutable property must emit its values and the `completed` event synchronously. + +The observers of a property should always observe the same value from the signal and the producer as `PropertyProtocol.value`. This implies that all observations are a `didSet` observer. + +#### Reentrancy must be supported for reads. + +All properties must guarantee that observers reading `PropertyProtocol.value` would not deadlock. + +In other words, if a mutable property type implements its own, or inherits a synchronization mechanism from its container, the synchronization generally should be reentrant due to the requirements of synchrony. + +#### A composed property does not have a side effect on its sources, and does not own its lifetime. + +A composed property presents a transformed view of its sources. It should not have a side effect on them, as [observing a signal does not have side effects](#observing-a-signal-does-not-have-side-effects) either. This implies a composed property should never retain its sources, or otherwise the `completed` event emitted upon deinitialization would be influenced. + +Moreover, it does not own its lifetime, and its deinitialization should not affect its signal and its producer. The signal and the producer should respect the lifetime of the ultimate sources in a property composition graph. + +## Best practices + +The following recommendations are intended to help keep ReactiveSwift-based code +predictable, understandable, and performant. + +They are, however, only guidelines. Use best judgement when determining whether +to apply the recommendations here to a given piece of code. + +#### Process only as many values as needed + +Keeping an event stream alive longer than necessary can waste CPU and memory, as +unnecessary work is performed for results that will never be used. + +If only a certain number of values or certain number of time is required from +a [signal][Signals] or [producer][Signal Producers], operators like +[`take`][take] or [`takeUntil`][takeUntil] can be used to +automatically complete the stream once a certain condition is fulfilled. + +The benefit is exponential, too, as this will terminate dependent operators +sooner, potentially saving a significant amount of work. + +#### Observe events on a known scheduler + +When receiving a [signal][Signals] or [producer][Signal Producers] from unknown +code, it can be difficult to know which thread [events][] will arrive upon. Although +events are [guaranteed to be serial](#events-are-serial), sometimes stronger +guarantees are needed, like when performing UI updates (which must occur on the +main thread). + +Whenever such a guarantee is important, the [`observeOn`][observeOn] +[operator][Operators] should be used to force events to be received upon +a specific [scheduler][Schedulers]. + +#### Switch schedulers in as few places as possible + +Notwithstanding the [above](#observe-events-on-a-known-scheduler), [events][] +should only be delivered to a specific [scheduler][Schedulers] when absolutely +necessary. Switching schedulers can introduce unnecessary delays and cause an +increase in CPU load. + +Generally, [`observeOn`][observeOn] should only be used right before observing +the [signal][Signals], starting the [producer][Signal Producers], or binding to +a [property][Properties]. This ensures that events arrive on the expected +scheduler, without introducing multiple thread hops before their arrival. + +#### Capture side effects within signal producers + +Because [signal producers start work on +demand](#signal-producers-start-work-on-demand-by-creating-signals), any +functions or methods that return a [signal producer][Signal Producers] should +make sure that side effects are captured _within_ the producer itself, instead +of being part of the function or method call. + +For example, a function like this: + +```swift +func search(text: String) -> SignalProducer +``` + +… should _not_ immediately start a search. + +Instead, the returned producer should execute the search once for every time +that it is started. This also means that if the producer is never started, +a search will never have to be performed either. + +#### Share the side effects of a signal producer by sharing one produced signal + +If multiple [observers][] are interested in the results of a [signal +producer][Signal Producers], calling [`start`][start] once for each observer +means that the work associated with the producer will [execute that many +times](#signal-producers-start-work-on-demand-by-creating-signals) and [may not +generate the same results](#each-produced-signal-may-send-different-events-at-different-times). + +If: + + 1. the observers need to receive the exact same results + 1. the observers know about each other, or + 1. the code starting the producer knows about each observer + +… it may be more appropriate to start the producer _just once_, and share the +results of that one [signal][Signals] to all observers, by attaching them within +the closure passed to the [`startWithSignal`][startWithSignal] method. + +#### Prefer managing lifetime with operators over explicit disposal + +Although the [disposable][Disposables] returned from [`start`][start] makes +canceling a [signal producer][Signal Producers] really easy, explicit use of +disposables can quickly lead to a rat's nest of resource management and cleanup +code. + +There are almost always higher-level [operators][] that can be used instead of manual +disposal: + + * [`take`][take] can be used to automatically terminate a stream once a certain + number of values have been received. + * [`takeUntil`][takeUntil] can be used to automatically terminate + a [signal][Signals] or producer when an event occurs (for example, when + a “Cancel” button is pressed in the UI). + * [Properties][] and the `<~` operator can be used to “bind” the result of + a signal or producer, until termination or until the property is deallocated. + This can replace a manual observation that sets a value somewhere. + +## Implementing new operators + +ReactiveSwift provides a long list of built-in [operators][] that should cover most use +cases; however, ReactiveSwift is not a closed system. It's entirely valid to implement +additional operators for specialized uses, or for consideration in ReactiveSwift +itself. + +Implementing a new operator requires a careful attention to detail and a focus +on simplicity, to avoid introducing bugs into the calling code. + +These guidelines cover some of the common pitfalls and help preserve the +expected API contracts. It may also help to look at the implementations of +existing [`Signal`][Signals] and [`SignalProducer`][Signal Producers] operators for reference points. + +#### Prefer writing operators that apply to both signals and producers + +Since any [signal operator can apply to signal +producers](#signal-operators-can-be-lifted-to-apply-to-signal-producers), +writing custom operators in terms of [`Signal`][Signals] means that +[`SignalProducer`][Signal Producers] will get it “for free.” + +Even if the caller only needs to apply the new operator to signal producers at +first, this generality can save time and effort in the future. + +Of course, some capabilities _require_ producers (for example, any retrying or +repeating), so it may not always be possible to write a signal-based version +instead. + +#### Compose existing operators when possible + +Considerable thought has been put into the operators provided by ReactiveSwift, and they +have been validated through automated tests and through their real world use in +other projects. An operator that has been written from scratch may not be as +robust, or might not handle a special case that the built-in operators are aware +of. + +To minimize duplication and possible bugs, use the provided operators as much as +possible in a custom operator implementation. Generally, there should be very +little code written from scratch. + +#### Forward failure and interruption events as soon as possible + +Unless an operator is specifically built to handle +[failures](#failures-behave-like-exceptions-and-propagate-immediately) and +[interruptions](#interruption-cancels-outstanding-work-and-usually-propagates-immedaitely) +in a custom way, it should propagate those events to the observer as soon as +possible, to ensure that their semantics are honored. + +#### Switch over `Event` values + +Create your own [observer][Observers] to process raw [`Event`][Events] values, and use +a `switch` statement to determine the event type. + +For example: + +```swift +producer.start { event in + switch event { + case let .Next(value): + print("Next event: \(value)") + + case let .Failed(error): + print("Failed event: \(error)") + + case .Completed: + print("Completed event") + + case .Interrupted: + print("Interrupted event") + } +} +``` + +Since the compiler will generate a warning if the `switch` is missing any case, +this prevents mistakes in a custom operator’s event handling. + +#### Avoid introducing concurrency + +Concurrency is an extremely common source of bugs in programming. To minimize +the potential for deadlocks and race conditions, operators should not +concurrently perform their work. + +Callers always have the ability to [observe events on a specific +scheduler](#observe-events-on-a-known-scheduler), and ReactiveSwift offers built-in ways +to parallelize work, so custom operators don’t need to be concerned with it. + +#### Avoid blocking in operators + +Signal or producer operators should return a new signal or producer +(respectively) as quickly as possible. Any work that the operator needs to +perform should be part of the event handling logic, _not_ part of the operator +invocation itself. + +This guideline can be safely ignored when the purpose of an operator is to +synchronously retrieve one or more values from a stream, like `single()` or +`wait()`. + +[CompositeDisposable]: ../Sources/Disposable.swift +[Disposables]: FrameworkOverview.md#disposables +[Events]: FrameworkOverview.md#events +[Framework Overview]: FrameworkOverview.md +[NoError]: ../Sources/Errors.swift +[Observers]: FrameworkOverview.md#observers +[Operators]: BasicOperators.md +[Properties]: FrameworkOverview.md#properties +[Schedulers]: FrameworkOverview.md#schedulers +[Signal Producers]: FrameworkOverview.md#signal-producers +[Signal.init]: ../Sources/Signal.swift +[Signal.pipe]: ../Sources/Signal.swift +[SignalProducer.init]: ../Sources/SignalProducer.swift +[Signals]: FrameworkOverview.md#signals +[delay]: ../Sources/Signal.swift +[flatten]: BasicOperators.md#flattening-producers +[lift]: ../Sources/SignalProducer.swift +[observe]: ../Sources/Signal.swift +[observeOn]: ../Sources/Signal.swift +[start]: ../Sources/SignalProducer.swift +[startWithSignal]: ../Sources/SignalProducer.swift +[take]: ../Sources/Signal.swift +[takeUntil]: ../Sources/Signal.swift diff --git a/Carthage/Checkouts/ReactiveSwift/Documentation/BasicOperators.md b/Carthage/Checkouts/ReactiveSwift/Documentation/BasicOperators.md new file mode 100644 index 0000000..64c0d99 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Documentation/BasicOperators.md @@ -0,0 +1,519 @@ +# Basic Operators + +This document explains some of the most common operators used in ReactiveCocoa, +and includes examples demonstrating their use. + +Note that “operators”, in this context, refers to functions that transform +[`Signal`s][Signal] and [`SignalProducer`s][SignalProducer], _not_ custom Swift operators. In other +words, these are composable primitives provided by ReactiveCocoa for working +with event streams. + +This document will use the term “event stream” when dealing with concepts that +apply to both `Signal` and `SignalProducer`. When the distinction matters, the +types will be referred to by name. + +**[Performing side effects with event streams](#performing-side-effects-with-event-streams)** + + 1. [Observation](#observation) + 1. [Injecting effects](#injecting-effects) + +**[Operator composition](#operator-composition)** + + 1. [Lifting](#lifting) + +**[Transforming event streams](#transforming-event-streams)** + + 1. [Mapping](#mapping) + 1. [Filtering](#filtering) + 1. [Aggregating](#aggregating) + +**[Combining event streams](#combining-event-streams)** + + 1. [Combining latest values](#combining-latest-values) + 1. [Zipping](#zipping) + +**[Flattening event streams](#flattening-event-streams)** + + 1. [Merging](#merging) + 1. [Concatenating](#concatenating) + 1. [Switching to the latest](#switching-to-the-latest) + +**[Working with errors](#working-with-errors)** + + 1. [Catching failures](#catching-failures) + 1. [Failable transformations](#failable-transformations) + 1. [Retrying](#retrying) + 1. [Mapping errors](#mapping-errors) + 1. [Promote](#promote) + +## Performing side effects with event streams + +### Observation + +`Signal`s can be observed with the `observe` function. + +```Swift +signal.observe { event in + switch event { + case let .value(value): + print("Value: \(value)") + case let .failed(error): + print("Failed: \(error)") + case .completed: + print("Completed") + case .interrupted: + print("Interrupted") + } +} +``` + +Alternatively, callbacks for the `value`, `failed`, `completed` and `interrupted` events can be provided which will be called when a corresponding event occurs. + +```Swift +signal.observeValues { value in + print("Value: \(value)") +} + +signal.observeFailed { error in + print("Failed: \(error)") +} + +signal.observeCompleted { + print("Completed") +} + +signal.observeInterrupted { + print("Interrupted") +} +``` + +### Injecting effects + +Side effects can be injected on an event stream with the `on` operator without actually subscribing to it. + +```Swift +let producer = signalProducer + .on(starting: { + print("Starting") + }, started: { + print("Started") + }, event: { event in + print("Event: \(event)") + }, value: { value in + print("Value: \(value)") + }, failed: { error in + print("Failed: \(error)") + }, completed: { + print("Completed") + }, interrupted: { + print("Interrupted") + }, terminated: { + print("Terminated") + }, disposed: { + print("Disposed") + }) +``` + + +Note that it is not necessary to provide all parameters - all of them are optional, you only need to provide callbacks for the events you care about. + +Note that nothing will be printed until `producer` is started (possibly somewhere else). + +## Operator composition + +### Lifting + +`Signal` operators can be _lifted_ to operate upon `SignalProducer`s using the +`lift` method. + +This will create a new `SignalProducer` which will apply the given operator to +_every_ `Signal` created, just as if the operator had been applied to each +produced `Signal` individually. + +## Transforming event streams + +These operators transform an event stream into a new stream. + +### Mapping + +The `map` operator is used to transform the values in an event stream, creating +a new stream with the results. + +```Swift +let (signal, observer) = Signal.pipe() + +signal + .map { string in string.uppercased() } + .observeValues { value in print(value) } + +observer.send(value: "a") // Prints A +observer.send(value: "b") // Prints B +observer.send(value: "c") // Prints C +``` + +[Interactive visualisation of the `map` operator.](http://neilpa.me/rac-marbles/#map) + +### Filtering + +The `filter` operator is used to only include values in an event stream that +satisfy a predicate. + +```Swift +let (signal, observer) = Signal.pipe() + +signal + .filter { number in number % 2 == 0 } + .observeValues { value in print(value) } + +observer.send(value: 1) // Not printed +observer.send(value: 2) // Prints 2 +observer.send(value: 3) // Not printed +observer.send(value: 4) // prints 4 +``` + +[Interactive visualisation of the `filter` operator.](http://neilpa.me/rac-marbles/#filter) + +### Aggregating + +The `reduce` operator is used to aggregate a event stream’s values into a single +combined value. Note that the final value is only sent after the input stream +completes. + +```Swift +let (signal, observer) = Signal.pipe() + +signal + .reduce(1) { $0 * $1 } + .observeValues { value in print(value) } + +observer.send(value: 1) // nothing printed +observer.send(value: 2) // nothing printed +observer.send(value: 3) // nothing printed +observer.sendCompleted() // prints 6 +``` + +The `collect` operator is used to aggregate a event stream’s values into +a single array value. Note that the final value is only sent after the input +stream completes. + +```Swift +let (signal, observer) = Signal.pipe() + +signal + .collect() + .observeValues { value in print(value) } + +observer.send(value: 1) // nothing printed +observer.send(value: 2) // nothing printed +observer.send(value: 3) // nothing printed +observer.sendCompleted() // prints [1, 2, 3] +``` + +[Interactive visualisation of the `reduce` operator.](http://neilpa.me/rac-marbles/#reduce) + +## Combining event streams + +These operators combine values from multiple event streams into a new, unified +stream. + +### Combining latest values + +The `combineLatest` function combines the latest values of two (or more) event +streams. + +The resulting stream will only send its first value after each input has sent at +least one value. After that, new values on any of the inputs will result in +a new value on the output. + +```Swift +let (numbersSignal, numbersObserver) = Signal.pipe() +let (lettersSignal, lettersObserver) = Signal.pipe() + +let signal = Signal.combineLatest(numbersSignal, lettersSignal) +signal.observeValues { next in print("Next: \(next)") } +signal.observeCompleted { print("Completed") } + +numbersObserver.send(value: 0) // nothing printed +numbersObserver.send(value: 1) // nothing printed +lettersObserver.send(value: "A") // prints (1, A) +numbersObserver.send(value: 2) // prints (2, A) +numbersObserver.sendCompleted() // nothing printed +lettersObserver.send(value: "B") // prints (2, B) +lettersObserver.send(value: "C") // prints (2, C) +lettersObserver.sendCompleted() // prints "Completed" +``` + +The `combineLatest(with:)` operator works in the same way, but as an operator. + +[Interactive visualisation of the `combineLatest` operator.](http://neilpa.me/rac-marbles/#combineLatest) + +### Zipping + +The `zip` function joins values of two (or more) event streams pair-wise. The +elements of any Nth tuple correspond to the Nth elements of the input streams. + +That means the Nth value of the output stream cannot be sent until each input +has sent at least N values. + +```Swift +let (numbersSignal, numbersObserver) = Signal.pipe() +let (lettersSignal, lettersObserver) = Signal.pipe() + +let signal = Signal.zip(numbersSignal, lettersSignal) +signal.observeValues { next in print("Next: \(next)") } +signal.observeCompleted { print("Completed") } + +numbersObserver.send(value: 0) // nothing printed +numbersObserver.send(value: 1) // nothing printed +lettersObserver.send(value: "A") // prints (0, A) +numbersObserver.send(value: 2) // nothing printed +numbersObserver.sendCompleted() // nothing printed +lettersObserver.send(value: "B") // prints (1, B) +lettersObserver.send(value: "C") // prints (2, C) & "Completed" + +``` + +The `zipWith` operator works in the same way, but as an operator. + +[Interactive visualisation of the `zip` operator.](http://neilpa.me/rac-marbles/#zip) + +## Flattening event streams + +The `flatten` operator transforms a stream-of-streams into a single stream - where values are forwarded from the inner stream in accordance with the provided `FlattenStrategy`. The flattened result becomes that of the outer stream type - i.e. a `SignalProducer`-of-`SignalProducer`s or `SignalProducer`-of-`Signal`s gets flattened to a `SignalProducer`, and likewise a `Signal`-of-`SignalProducer`s or `Signal`-of-`Signal`s gets flattened to a `Signal`. + +To understand why there are different strategies and how they compare to each other, take a look at this example and imagine the column offsets as time: + +```Swift +let values = [ +// imagine column offset as time +[ 1, 2, 3 ], + [ 4, 5, 6 ], + [ 7, 8 ], +] + +let merge = +[ 1, 4, 2, 7,5, 3,8,6 ] + +let concat = +[ 1, 2, 3,4, 5, 6,7, 8] + +let latest = +[ 1, 4, 7, 8 ] +``` + +Note, how the values interleave and which values are even included in the resulting array. + + +### Merging + +The `.merge` strategy immediately forwards every value of the inner event streams to the outer event stream. Any failure sent on the outer event stream or any inner event stream is immediately sent on the flattened event stream and terminates it. + +```Swift +let (lettersSignal, lettersObserver) = Signal.pipe() +let (numbersSignal, numbersObserver) = Signal.pipe() +let (signal, observer) = Signal, NoError>.pipe() + +signal.flatten(.merge).observeValues { print($0) } + +observer.send(value: lettersSignal) +observer.send(value: numbersSignal) +observer.sendCompleted() + +lettersObserver.send(value: "a") // prints "a" +numbersObserver.send(value: "1") // prints "1" +lettersObserver.send(value: "b") // prints "b" +numbersObserver.send(value: "2") // prints "2" +lettersObserver.send(value: "c") // prints "c" +numbersObserver.send(value: "3") // prints "3" +``` + +[Interactive visualisation of the `flatten(.merge)` operator.](http://neilpa.me/rac-marbles/#merge) + +### Concatenating + +The `.concat` strategy is used to serialize events of the inner event streams. The outer event stream is started observed. Each subsequent event stream is not observed until the preceeding one has completed. Failures are immediately forwarded to the flattened event stream. + +```Swift +let (lettersSignal, lettersObserver) = Signal.pipe() +let (numbersSignal, numbersObserver) = Signal.pipe() +let (signal, observer) = Signal, NoError>.pipe() + +signal.flatten(.concat).observeValues { print($0) } + +observer.send(value: lettersSignal) +observer.send(value: numbersSignal) +observer.sendCompleted() + +numbersObserver.send(value: "1") // nothing printed +lettersObserver.send(value: "a") // prints "a" +lettersObserver.send(value: "b") // prints "b" +numbersObserver.send(value: "2") // nothing printed +lettersObserver.send(value: "c") // prints "c" +lettersObserver.sendCompleted() // nothing printed +numbersObserver.send(value: "3") // prints "3" +numbersObserver.sendCompleted() // nothing printed +``` + +[Interactive visualisation of the `flatten(.concat)` operator.](http://neilpa.me/rac-marbles/#concat) + +### Switching to the latest + +The `.latest` strategy forwards only values or a failure from the latest input event stream. + +```Swift +let (lettersSignal, lettersObserver) = Signal.pipe() +let (numbersSignal, numbersObserver) = Signal.pipe() +let (signal, observer) = Signal, NoError>.pipe() + +signal.flatten(.latest).observeValues { print($0) } + +observer.send(value: lettersSignal) // nothing printed +numbersObserver.send(value: "1") // nothing printed +lettersObserver.send(value: "a") // prints "a" +lettersObserver.send(value: "b") // prints "b" +numbersObserver.send(value: "2") // nothing printed +observer.send(value: numbersSignal) // nothing printed +lettersObserver.send(value: "c") // nothing printed +numbersObserver.send(value: "3") // prints "3" +``` + +## Working with errors + +These operators are used to handle failures that might occur on an event stream, or perform operations that might fail on an event stream. + +### Catching failures + +The `flatMapError` operator catches any failure that may occur on the input event stream, then starts a new `SignalProducer` in its place. + +```Swift +let (signal, observer) = Signal.pipe() +let producer = SignalProducer(signal: signal) + +let error = NSError(domain: "domain", code: 0, userInfo: nil) + +producer + .flatMapError { _ in SignalProducer(value: "Default") } + .startWithValues { print($0) } + + +observer.send(value: "First") // prints "First" +observer.send(value: "Second") // prints "Second" +observer.send(error: error) // prints "Default" +``` + +### Failable transformations + +`SignalProducer.attempt(_:)` allows you to turn a failable operation into an event stream. +The `attempt(_:)` and `attemptMap(_:)` operators allow you to perform failable operations or transformations on an event stream. + +```swift +let dictionaryPath = URL(fileURLWithPath: "/usr/share/dict/words") + +// Create a `SignalProducer` that lazily attempts the closure +// whenever it is started +let data = SignalProducer.attempt { try Data(contentsOf: dictionaryPath) } + +// Lazily apply a failable transformation +let json = data.attemptMap { try JSONSerialization.jsonObject(with: $0) } + +json.startWithResult { result in + switch result { + case let .success(words): + print("Dictionary as JSON:") + print(words) + case let .failure(error): + print("Couldn't parse dictionary as JSON: \(error)") + } +} +``` + +### Retrying + +The `retry` operator will restart the original `SignalProducer` on failure up to `count` times. + +```Swift +var tries = 0 +let limit = 2 +let error = NSError(domain: "domain", code: 0, userInfo: nil) +let producer = SignalProducer { (observer, _) in + tries += 1 + if tries <= limit { + observer.send(error: error) + } else { + observer.send(value: "Success") + observer.sendCompleted() + } +} + +producer + .on(failed: {e in print("Failure")}) // prints "Failure" twice + .retry(upTo: 2) + .start { event in + switch event { + case let .value(next): + print(next) // prints "Success" + case let .failed(error): + print("Failed: \(error)") + case .completed: + print("Completed") + case .interrupted: + print("Interrupted") + } +} +``` + +If the `SignalProducer` does not succeed after `count` tries, the resulting `SignalProducer` will fail. E.g., if `retry(1)` is used in the example above instead of `retry(2)`, `"Failed: Error Domain=domain Code=0 "(null)""` will be printed instead of `"Success"`. + +### Mapping errors + +The `mapError` operator transforms the error of any failure in an event stream into a new error. + +```Swift +enum CustomError: String, Error { + case foo = "Foo Error" + case bar = "Bar Error" + case other = "Other Error" +} + +let (signal, observer) = Signal.pipe() + +signal + .mapError { (error: NSError) -> CustomError in + switch error.domain { + case "com.example.foo": + return .foo + case "com.example.bar": + return .bar + default: + return .other + } + } + .observeFailed { error in + print(error.rawValue) +} + +observer.send(error: NSError(domain: "com.example.foo", code: 42, userInfo: nil)) // prints "Foo Error" +``` + +### Promote + +The `promoteErrors` operator promotes an event stream that does not generate failures into one that can. + +```Swift +let (numbersSignal, numbersObserver) = Signal.pipe() +let (lettersSignal, lettersObserver) = Signal.pipe() + +numbersSignal + .promoteErrors(NSError.self) + .combineLatest(with: lettersSignal) +``` + +The given stream will still not _actually_ generate failures, but this is useful +because some operators to [combine streams](#combining-event-streams) require +the inputs to have matching error types. + + +[Signal]: Documentation/ReactivePrimitives.md#signal-a-unidirectional-stream-of-events +[SignalProducer]: Documentation/ReactivePrimitives.md#signalproducer-deferred-work-that-creates-a-stream-of-values +[Observation]: FrameworkOverview.md#observation + diff --git a/Carthage/Checkouts/ReactiveSwift/Documentation/DebuggingTechniques.md b/Carthage/Checkouts/ReactiveSwift/Documentation/DebuggingTechniques.md new file mode 100644 index 0000000..2ef72f5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Documentation/DebuggingTechniques.md @@ -0,0 +1,100 @@ +# Debugging Techniques + +This document lists debugging techniques and infrastructure helpful for debugging ReactiveCocoa applications. + +#### Unscrambling Swift compiler errors + +Type inferrence can be a source of hard-to-debug compiler errors. There are two potential places to be wrong when type inferrence used: + +1. Definition of type inferred variable +2. Consumption of type inferred variable + +In both cases errors are related to incorrect assumptions about type. Such issues are common for ReactiveCocoa applications as it is all about operations over data and related types. The current state of the Swift compiler can cause misleading type errors, especially when error happens in the middle of a signal chain. + +Below is an example of type-error scenario: + +```swift +SignalProducer(value:42) + .on(value: { answer in + return _ + }) + .startWithCompleted { + print("Completed.") + } +``` + +The code above will not compile with the following error on the `.startWithCompleted` call `error: cannot convert value of type 'Disposable' to closure result type '()'. To find the actual compile error, the chain needs to be broken apart. Add explicit definitions of closure types on each of the steps: + +```swift +let initialProducer = SignalProducer.init(value:42) +let sideEffectProducer = initialProducer.on(value: { (answer: Int) in + return _ +}) +let disposable = sideEffectProducer.startWithCompleted { + print("Completed.") +} +``` + +The code above will not compile too, but with the error `error: cannot convert value of type '(Int) -> _' to expected argument type '((Int) -> Void)?'` on definition of `on` closure. This gives enough of information to locate unexpected `return _` since `on` closure should not have any return value. + +#### Debugging event streams + +As mentioned in the README, stream debugging can be quite difficut and tedious, so we provide the `logEvents` operator. In its simplest form: + +```swift +let property = MutableProperty("") +... +let searchString = property.producer + .throttle(0.5, on: QueueScheduler.main) + .logEvents() +``` + +This will print to the standard output the events. For most use cases, this is enough and will greatly help you understand your flow. +The biggest problem with this approach, is that it will continue to ouput in Release mode. This leaves with you with two options: + +1. Comment out the operator: `//.logEvents()`. This is the simpleste approach, but it's error prone, since you will eventually forget to do this. +2. Pass your own function and manipulate the output as you see fit. This is the recommended approach. + +Let's see how this would look like if we didn't want to print in Release mode: + +```swift +func debugLog(identifier: String, event: String, fileName: String, functionName: String, lineNumber: Int) { + // Don't forget to set up the DEBUG symbol (http://stackoverflow.com/a/24112024/491239) + #if DEBUG + print(event) + #endif +} +``` + +You would then: + +```swift +let property = MutableProperty("") +... +let searchString = property.producer + .throttle(0.5, on: QueueScheduler.main) + .logEvents(logger: debugLog) +``` + +We also provide the `identifier` parameter. This is useful when you are debugging multiple streams and you don't want to get lost: + +```swift +let property = MutableProperty("") +... +let searchString = property.producer + .throttle(0.5, on: QueueScheduler.main) + .logEvents(identifier: "✨My awesome stream ✨") +``` + +There also cases, specially with [hot signals][Signal], when there is simply too much output. For those, you can specify which events you are interested in: + +```swift +let property = MutableProperty("") +... +let searchString = property.producer + .throttle(0.5, on: QueueScheduler.main) + .logEvents(events: [.disposed]) // This will happen when `property` is released +``` + +[Signal]: ../Sources/Signal.swift + diff --git a/Carthage/Checkouts/ReactiveSwift/Documentation/Example.OnlineSearch.md b/Carthage/Checkouts/ReactiveSwift/Documentation/Example.OnlineSearch.md new file mode 100644 index 0000000..e545350 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Documentation/Example.OnlineSearch.md @@ -0,0 +1,173 @@ +# Example: Online Searching + +Let’s say you have a text field, and whenever the user types something into it, +you want to make a network request which searches for that query. + +_Please note that the following examples use Cocoa extensions in [ReactiveCocoa][] for illustration._ + +#### Observing text edits + +The first step is to observe edits to the text field, using a RAC extension to +`UITextField` specifically for this purpose: + +```swift +let searchStrings = textField.reactive.continuousTextValues +``` + +This gives us a [Signal][] which sends values of type `String?`. + +#### Making network requests + +With each string, we want to execute a network request. ReactiveSwift offers an +`URLSession` extension for doing exactly that: + +```swift +let searchResults = searchStrings + .flatMap(.latest) { (query: String?) -> SignalProducer<(Data, URLResponse), AnyError> in + let request = self.makeSearchRequest(escapedQuery: query) + return URLSession.shared.reactive.data(with: request) + } + .map { (data, response) -> [SearchResult] in + let string = String(data: data, encoding: .utf8)! + return self.searchResults(fromJSONString: string) + } + .observe(on: UIScheduler()) +``` + +This has transformed our producer of `String`s into a producer of `Array`s +containing the search results, which will be forwarded on the main thread +(using the [`UIScheduler`][Schedulers]). + +Additionally, [`flatMap(.latest)`][flatMapLatest] here ensures that _only one search_—the +latest—is allowed to be running. If the user types another character while the +network request is still in flight, it will be cancelled before starting a new +one. Just think of how much code that would take to do by hand! + +#### Receiving the results + +Since the source of search strings is a `Signal` which has a hot signal semantic, +the transformations we applied are automatically evaluated whenever new values are +emitted from `searchStrings`. + +Therefore, we can simply observe the signal using `Signal.observe(_:)`: + +```swift +searchResults.observe { event in + switch event { + case let .value(results): + print("Search results: \(results)") + + case let .failed(error): + print("Search error: \(error)") + + case .completed, .interrupted: + break + } +} +``` + +Here, we watch for the `Value` [event][Events], which contains our results, and +just log them to the console. This could easily do something else instead, like +update a table view or a label on screen. + +#### Handling failures + +In this example so far, any network error will generate a `Failed` +[event][Events], which will terminate the event stream. Unfortunately, this +means that future queries won’t even be attempted. + +To remedy this, we need to decide what to do with failures that occur. The +quickest solution would be to log them, then ignore them: + +```swift + .flatMap(.latest) { (query: String) -> SignalProducer<(Data, URLResponse), AnyError> in + let request = self.makeSearchRequest(escapedQuery: query) + + return URLSession.shared.reactive + .data(with: request) + .flatMapError { error in + print("Network error occurred: \(error)") + return SignalProducer.empty + } + } +``` + +By replacing failures with the `empty` event stream, we’re able to effectively +ignore them. + +However, it’s probably more appropriate to retry at least a couple of times +before giving up. Conveniently, there’s a [`retry`][retry] operator to do exactly that! + +Our improved `searchResults` producer might look like this: + +```swift +let searchResults = searchStrings + .flatMap(.latest) { (query: String) -> SignalProducer<(Data, URLResponse), AnyError> in + let request = self.makeSearchRequest(escapedQuery: query) + + return URLSession.shared.reactive + .data(with: request) + .retry(upTo: 2) + .flatMapError { error in + print("Network error occurred: \(error)") + return SignalProducer.empty + } + } + .map { (data, response) -> [SearchResult] in + let string = String(data: data, encoding: .utf8)! + return self.searchResults(fromJSONString: string) + } + .observe(on: UIScheduler()) +``` + +#### Throttling requests + +Now, let’s say you only want to actually perform the search periodically, +to minimize traffic. + +ReactiveCocoa has a declarative `throttle` operator that we can apply to our +search strings: + +```swift +let searchStrings = textField.reactive.continuousTextValues + .throttle(0.5, on: QueueScheduler.main) +``` + +This prevents values from being sent less than 0.5 seconds apart. + +To do this manually would require significant state, and end up much harder to +read! With ReactiveCocoa, we can use just one operator to incorporate _time_ into +our event stream. + +#### Debugging event streams + +Due to its nature, a stream's stack trace might have dozens of frames, which, more often than not, can make debugging a very frustrating activity. +A naive way of debugging, is by injecting side effects into the stream, like so: + +```swift +let searchString = textField.reactive.continuousTextValues + .throttle(0.5, on: QueueScheduler.main) + .on(event: { print ($0) }) // the side effect +``` + +This will print the stream's [events][Events], while preserving the original stream behaviour. Both [`SignalProducer`][SignalProducer] +and [`Signal`][Signal] provide the `logEvents` operator, that will do this automatically for you: + +```swift +let searchString = textField.reactive.continuousTextValues + .throttle(0.5, on: QueueScheduler.main) + .logEvents() +``` + +For more information and advance usage, check the [Debugging Techniques][] document. + +[SignalProducer]: Documentation/ReactivePrimitives.md#signalproducer-deferred-work-that-creates-a-stream-of-values +[Schedulers]: Documentation/FrameworkOverview.md#Schedulers +[Signal]: Documentation/ReactivePrimitives.md#signal-a-unidirectional-stream-of-events +[Events]: Documentation/ReactivePrimitives.md#event-the-basic-transfer-unit-of-an-event-stream +[Debugging Techniques]: Documentation/DebuggingTechniques.md + +[retry]: Documentation/BasicOperators.md#retrying +[flatMapLatest]: Documentation/BasicOperators.md#combining-latest-values + +[ReactiveCocoa]: https://github.com/ReactiveCocoa/ReactiveCocoa/#readme \ No newline at end of file diff --git a/Carthage/Checkouts/ReactiveSwift/Documentation/FrameworkOverview.md b/Carthage/Checkouts/ReactiveSwift/Documentation/FrameworkOverview.md new file mode 100644 index 0000000..3aad338 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Documentation/FrameworkOverview.md @@ -0,0 +1,228 @@ +# Framework Overview + +This document contains a high-level description of the different components +within the ReactiveSwift framework, and an attempt to explain how they work +together and divide responsibilities. This is meant to be a starting point for +learning about new modules and finding more specific documentation. + +For examples and help understanding how to use RAC, see the [README][] or +the [Design Guidelines][]. + +## Events + +An **event**, represented by the [`Event`][Event] type, is the formalized representation +of the fact that _something has happened_. In ReactiveSwift, events are the centerpiece +of communication. An event might represent the press of a button, a piece +of information received from an API, the occurrence of an error, or the completion +of a long-running operation. In any case, something generates the events and sends them over a +[signal](#signals) to any number of [observers](#observers). + +`Event` is an enumerated type representing either a value or one of three +terminal events: + + * The `value` event provides a new value from the source. + * The `failed` event indicates that an error occurred before the signal could + finish. Events are parameterized by an `ErrorType`, which determines the kind + of failure that’s permitted to appear in the event. If a failure is not + permitted, the event can use type `NoError` to prevent any from being + provided. + * The `completed` event indicates that the signal finished successfully, and + that no more values will be sent by the source. + * The `interrupted` event indicates that the signal has terminated due to + cancellation, meaning that the operation was neither successful nor + unsuccessful. + +## Signals + +A **signal**, represented by the [`Signal`][Signal] type, is any series of [events](#events) +over time that can be observed. + +Signals are generally used to represent event streams that are already “in progress”, +like notifications, user input, etc. As work is performed or data is received, +events are _sent_ on the signal, which pushes them out to any observers. +All observers see the events at the same time. + +Users must [observe](#observers) a signal in order to access its events. +Observing a signal does not trigger any side effects. In other words, +signals are entirely producer-driven and push-based, and consumers (observers) +cannot have any effect on their lifetime. While observing a signal, the user +can only evaluate the events in the same order as they are sent on the signal. There +is no random access to values of a signal. + +Signals can be manipulated by applying [primitives][BasicOperators] to them. +Typical primitives to manipulate a single signal like `filter`, `map` and +`reduce` are available, as well as primitives to manipulate multiple signals +at once (`zip`). Primitives operate only on the `value` events of a signal. + +The lifetime of a signal consists of any number of `value` events, followed by +one terminating event, which may be any one of `failed`, `completed`, or +`interrupted` (but not a combination). +Terminating events are not included in the signal’s values—they must be +handled specially. + +### Pipes + +A **pipe**, created by `Signal.pipe()`, is a [signal](#signals) +that can be manually controlled. + +The method returns a [signal](#signals) and an [observer](#observers). +The signal can be controlled by sending events to the observer. This +can be extremely useful for bridging non-RAC code into the world of signals. + +For example, instead of handling application logic in block callbacks, the +blocks can simply send events to the observer. Meanwhile, the signal +can be returned, hiding the implementation detail of the callbacks. + +## Signal Producers + +A **signal producer**, represented by the [`SignalProducer`][SignalProducer] type, creates +[signals](#signals) and performs side effects. + +They can be used to represent operations or tasks, like network +requests, where each invocation of `start()` will create a new underlying +operation, and allow the caller to observe the result(s). The +`startWithSignal()` variant gives access to the produced signal, allowing it to +be observed multiple times if desired. + +Because of the behavior of `start()`, each signal created from the same +producer may see a different ordering or version of events, or the stream might +even be completely different! Unlike a plain signal, no work is started (and +thus no events are generated) until an observer is attached, and the work is +restarted anew for each additional observer. + +Starting a signal producer returns a [disposable](#disposables) that can be used to +interrupt/cancel the work associated with the produced signal. + +Just like signals, signal producers can also be manipulated via primitives +like `map`, `filter`, etc. +Every signal primitive can be “lifted” to operate upon signal producers instead, +using the `lift` method. +Furthermore, there are additional primitives that control _when_ and _how_ work +is started—for example, `times`. + +## Observers + +An **observer** is anything that is waiting or capable of waiting for [events](#events) +from a [signal](#signals). Within RAC, an observer is represented as an [`Observer`][Observer] that accepts [`Event`][Event] values. + +Observers can be implicitly created by using the callback-based versions of the +`Signal.observe` or `SignalProducer.start` methods. + +## Lifetimes + +When observing a signal or starting a signal producer, it is important to consider how long the observation should last. For example, when observing a signal in order to update a UI component, it makes sense to stop observing it once the component is no longer on screen. This idea is expressed in ReactiveSwift by the `Lifetime` type. + +```swift +import Foundation + +final class SettingsController { + // Define a lifetime for instances of this class. When an instance is + // deinitialized, the lifetime ends. + private let (lifetime, token) = Lifetime.make() + + func observeDefaultsChanged(_ defaults: UserDefaults = .standard) { + // `take(during: lifetime)` ensures the observation ends when this object + // is deinitialized + NotificationCenter.default.reactive + .notifications(forName: UserDefaults.didChangeNotification, object: defaults) + .take(during: lifetime) + .observeValues { [weak self] _ in self?.defaultsChanged(defaults) } + } + + private func defaultsChanged(_ defaults: UserDefaults) { + // perform some updates + } +} +``` + +The `token` is a `Lifetime.Token`, which we need to keep a strong reference to in order for the `Lifetime` to work. +(Note: It's crucial that there is only a single strong reference to `token`, so that it is deinitialized at the same time as `self`.) + +`Lifetime` is useful any time that an observation might outlive the observer: + +- In the `NotificationCenter` example above, without a `Lifetime` the observation would never complete (leaking memory and wasting CPU cycles). +- Consider a signal producer that fires a network request — incorporating a `Lifetime` might allow the request to be automatically cancelled if the observer is deinitialized. + +## Actions + +An **action**, represented by the [`Action`][Action] type, will do some work when +executed with an input. While executing, zero or more output values and/or a +failure may be generated. + +Actions are useful for performing side-effecting work upon user interaction, like when a button is +clicked. Actions can also be automatically disabled based on a [property](#properties), and this +disabled state can be represented in a UI by disabling any controls associated +with the action. + +## Properties + +A **property**, represented by the [`PropertyProtocol`][Property], +stores a value and notifies observers about future changes to that value. + +The current value of a property can be obtained from the `value` getter. The +`producer` getter returns a [signal producer](#signal-producers) that will send +the property’s current value, followed by all changes over time. The `signal` getter returns a [signal](#signals) that will send all changes over time, but not the initial value. + +The `<~` operator can be used to bind properties in different ways. Note that in +all cases, the target has to be a binding target, represented by the [`BindingTargetProtocol`][BindingTarget]. All mutable property types, represented by the [`MutablePropertyProtocol`][MutableProperty], are inherently binding targets. + +* `property <~ signal` binds a [signal](#signals) to the property, updating the + property’s value to the latest value sent by the signal. +* `property <~ producer` starts the given [signal producer](#signal-producers), + and binds the property’s value to the latest value sent on the started signal. +* `property <~ otherProperty` binds one property to another, so that the destination + property’s value is updated whenever the source property is updated. + +Properties provide a number of transformations like `map`, `combineLatest` or `zip` for manipulation similar to [signal](#signals) and [signal producer](#signal-producers) + +## Disposables + +A **disposable**, represented by the [`Disposable`][Disposable] protocol, is a mechanism +for memory management and cancellation. + +When starting a [signal producer](#signal-producers), a disposable will be returned. +This disposable can be used by the caller to cancel the work that has been started +(e.g. background processing, network requests, etc.), clean up all temporary +resources, then send a final `interrupted` event upon the particular +[signal](#signals) that was created. + +Observing a [signal](#signals) may also return a disposable. Disposing it will +prevent the observer from receiving any future events from that signal, but it +will not have any effect on the signal itself. + +For more information about cancellation, see the RAC [Design Guidelines][]. + +## Schedulers + +A **scheduler**, represented by the [`SchedulerProtocol`][Scheduler] protocol, is a +serial execution queue to perform work or deliver results upon. + +[Signals](#signals) and [signal producers](#signal-producers) can be ordered to +deliver events on a specific scheduler. [Signal producers](#signal-producers) +can additionally be ordered to start their work on a specific scheduler. + +Schedulers are similar to Grand Central Dispatch queues, but schedulers support +cancellation (via [disposables](#disposables)), and always execute serially. +With the exception of the [`ImmediateScheduler`][Scheduler], schedulers do not +offer synchronous execution. This helps avoid deadlocks, and encourages the use +of [signal and signal producer primitives][BasicOperators] instead of blocking work. + +Schedulers are also somewhat similar to `NSOperationQueue`, but schedulers +do not allow tasks to be reordered or depend on one another. + + +[Design Guidelines]: DesignGuidelines.md +[BasicOperators]: BasicOperators.md +[README]: ../README.md +[ReactiveCocoa]: https://github.com/ReactiveCocoa/ +[Signal]: ../Sources/Signal.swift +[SignalProducer]: ../Sources/SignalProducer.swift +[Action]: ../Sources/Action.swift +[CocoaAction]: https://github.com/ReactiveCocoa/ReactiveCocoa/blob/master/ReactiveCocoa/CocoaAction.swift +[Disposable]: ../Sources/Disposable.swift +[Scheduler]: ../Sources/Scheduler.swift +[Property]: ../Sources/Property.swift +[MutableProperty]: ../Sources/Property.swift#L28 +[Event]: ../Sources/Event.swift +[Observer]: ../Sources/Observer.swift +[BindingTarget]: ../Sources/UnidirectionalBinding.swift diff --git a/Carthage/Checkouts/ReactiveSwift/Documentation/ReactivePrimitives.md b/Carthage/Checkouts/ReactiveSwift/Documentation/ReactivePrimitives.md new file mode 100644 index 0000000..19e9dc0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Documentation/ReactivePrimitives.md @@ -0,0 +1,115 @@ +# Core Reactive Primitives + +1. [`Signal`](#signal-a-unidirectional-stream-of-events) +1. [`Event`](#event-the-basic-transfer-unit-of-an-event-stream) +1. [`SignalProducer`](#signalproducer-deferred-work-that-creates-a-stream-of-values) +1. [`Property`](#property-an-observable-box-that-always-holds-a-value) +1. [`Action`](#action-a-serialized-worker-with-a-preset-action) +1. [`Lifetime`](#lifetime-limits-the-scope-of-an-observation) + +#### `Signal`: a unidirectional stream of events. +The owner of a `Signal` has unilateral control of the event stream. Observers may register their interests in the future events at any time, but the observation would have no side effect on the stream or its owner. + +It is like a live TV feed — you can observe and react to the content, but you cannot have a side effect on the live feed or the TV station. + +```swift +let channel: Signal = tvStation.channelOne +channel.observeValues { program in ... } +``` + +*See also: [The `Signal` overview](FrameworkOverview.md#signals), [The `Signal` contract](APIContracts.md#the-signal-contract), [The `Signal` API reference](http://reactivecocoa.io/reactiveswift/docs/latest/Classes/Signal.html)* + + +#### `Event`: the basic transfer unit of an event stream. +A `Signal` may have any arbitrary number of events carrying a value, following by an eventual terminal event of a specific reason. + +It is like a frame in a one-time live feed — seas of data frames carry the visual and audio data, but the feed would eventually be terminated with a special frame to indicate "end of stream". + +*See also: [The `Event` overview](FrameworkOverview.md#events), [The `Signal` contract](APIContracts.md#the-event-contract), [The `Event` API reference](http://reactivecocoa.io/reactiveswift/docs/latest/Enums/Event.html)* + +#### `SignalProducer`: deferred work that creates a stream of values. +`SignalProducer` defers work — of which the output is represented as a stream of values — until it is started. For every invocation to start the `SignalProducer`, a new `Signal` is created and the deferred work is subsequently invoked. + +It is like a on-demand streaming service — even though the episode is streamed like a live TV feed, you can choose what you watch, when to start watching and when to interrupt it. + + +```swift +let frames: SignalProducer = vidStreamer.streamAsset(id: tvShowId) +let interrupter = frames.start { frame in ... } +interrupter.dispose() +``` + +*See also: [The `SignalProducer` overview](FrameworkOverview.md#signal-producers), [The `SignalProducer` contract](APIContracts.md#the-signalproducer-contract), [The `SignalProducer` API reference](http://reactivecocoa.io/reactiveswift/docs/latest/Structs/SignalProducer.html)* + +#### `Property`: an observable box that always holds a value. +`Property` is a variable that can be observed for its changes. In other words, it is a stream of values with a stronger guarantee than `Signal` — the latest value is always available, and the stream would never fail. + +It is like the continuously updated current time offset of a video playback — the playback is always at a certain time offset at any time, and it would be updated by the playback logic as the playback continues. + +```swift +let currentTime: Property = video.currentTime +print("Current time offset: \(currentTime.value)") +currentTime.signal.observeValues { timeBar.timeLabel.text = "\($0)" } +``` + +*See also: [The `Property` overview](FrameworkOverview.md#properties), [The `Property` contract](APIContracts.md#the-property-contract), [The property API reference](http://reactivecocoa.io/reactiveswift/docs/latest/Property.html)* + +#### `Action`: a serialized worker with a preset action. +When being invoked with an input, `Action` apply the input and the latest state to the preset action, and pushes the output to any interested parties. + +It is like an automatic vending machine — after choosing an option with coins inserted, the machine would process the order and eventually output your wanted snack. Notice that the entire process is mutually exclusive — you cannot have the machine to serve two customers concurrently. + +```swift +// Purchase from the vending machine with a specific option. +vendingMachine.purchase + .apply(snackId) + .startWithResult { result + switch result { + case let .success(snack): + print("Snack: \(snack)") + + case let .failure(error): + // Out of stock? Insufficient fund? + print("Transaction aborted: \(error)") + } + } + +// The vending machine. +class VendingMachine { + let purchase: Action + let coins: MutableProperty + + // The vending machine is connected with a sales recorder. + init(_ salesRecorder: SalesRecorder) { + coins = MutableProperty(0) + purchase = Action(state: coins, enabledIf: { $0 > 0 }) { coins, snackId in + return SignalProducer { observer, _ in + // The sales magic happens here. + // Fetch a snack based on its id + } + } + + // The sales recorders are notified for any successful sales. + purchase.values.observeValues(salesRecorder.record) + } +} +``` + +*See also: [The `Action` overview](FrameworkOverview.md#actions), [The `Action` API reference](http://reactivecocoa.io/reactiveswift/docs/latest/Classes/Action.html)* + +#### `Lifetime`: limits the scope of an observation +When observing a `Signal` or `SignalProducer`, it doesn't make sense to continue emitting values if there's no longer anyone observing them. +Consider the video stream: once you stop watching the video, the stream can be automatically closed by providing a `Lifetime`: + +```swift +class VideoPlayer { + private let (lifetime, token) = Lifetime.make() + + func play() { + let frames: SignalProducer = ... + frames.take(during: lifetime).start { frame in ... } + } +} +``` + +*See also: [The `Lifetime` overview](FrameworkOverview.md#lifetimes), [The `Lifetime` API reference](http://reactivecocoa.io/reactiveswift/docs/latest/Classes/Lifetime.html)* diff --git a/Carthage/Checkouts/ReactiveSwift/Documentation/RxComparison.md b/Carthage/Checkouts/ReactiveSwift/Documentation/RxComparison.md new file mode 100644 index 0000000..55fc129 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Documentation/RxComparison.md @@ -0,0 +1,89 @@ +# How does ReactiveSwift relate to RxSwift? +RxSwift is a Swift implementation of the [ReactiveX][] (Rx) APIs. While ReactiveCocoa +was inspired and heavily influenced by Rx, ReactiveSwift is an opinionated +implementation of [functional reactive programming][], and _intentionally_ not a +direct port like [RxSwift][]. + +ReactiveSwift differs from RxSwift/ReactiveX where doing so: + +* Results in a simpler API +* Addresses common sources of confusion +* Matches closely to Swift, and sometimes Cocoa, conventions + +The following are a few important differences, along with their rationales. + +### Signals and SignalProducers (“hot” and “cold” observables) + +One of the most confusing aspects of Rx is that of [“hot”, “cold”, and “warm” + observables](http://www.introtorx.com/content/v1.0.10621.0/14_HotAndColdObservables.html) (event streams). + +In short, given just a method or function declaration like this, in C#: + +```csharp +IObservable Search(string query) +``` + +… it is **impossible to tell** whether subscribing to (observing) that +`IObservable` will involve side effects. If it _does_ involve side effects, it’s +also impossible to tell whether _each subscription_ has a side effect, or if only +the first one does. + +This example is contrived, but it demonstrates **a real, pervasive problem** +that makes it extremely hard to understand Rx code (and pre-3.0 ReactiveCocoa +code) at a glance. + +**ReactiveSwift** addresses this by distinguishing side effects with the separate +[`Signal`][Signal] and [`SignalProducer`][SignalProducer] types. Although this +means there’s another type to learn about, it improves code clarity and helps +communicate intent much better. + +In other words, **ReactiveSwift’s changes here are [simple, not +easy](http://www.infoq.com/presentations/Simple-Made-Easy)**. + +### Typed errors + +When [Signals][Signal] and [SignalProducers][SignalProducer] are allowed to [fail][Events] in ReactiveSwift, +the kind of error must be specified in the type system. For example, +`Signal` is a signal of integer values that may fail with an error +of type `AnyError`. + +More importantly, RAC allows the special type `NoError` to be used instead, +which _statically guarantees_ that an event stream is not allowed to send a +failure. **This eliminates many bugs caused by unexpected failure events.** + +In Rx systems with types, event streams only specify the type of their +values—not the type of their errors—so this sort of guarantee is impossible. + +### Naming + +In most versions of Rx, Streams over time are known as `Observable`s, which +parallels the `Enumerable` type in .NET. Additionally, most operations in Rx.NET +borrow names from [LINQ](https://msdn.microsoft.com/en-us/library/bb397926.aspx), +which uses terms reminiscent of relational databases, like `Select` and `Where`. + +**ReactiveSwift**, on the other hand, focuses on being a native Swift citizen +first and foremost, following the [Swift API Guidelines][] as appropriate. Other +naming differences are typically inspired by significantly better alternatives +from [Haskell](https://www.haskell.org) or [Elm](http://elm-lang.org) (which is the primary source for the “signal” terminology). + +### UI programming + +Rx is basically agnostic as to how it’s used. Although UI programming with Rx is +very common, it has few features tailored to that particular case. + +ReactiveSwift takes a lot of inspiration from [ReactiveUI](http://reactiveui.net/), +including the basis for [Actions][]. + +Unlike ReactiveUI, which unfortunately cannot directly change Rx to make it more +friendly for UI programming, **ReactiveSwift has been improved many times +specifically for this purpose**—even when it means diverging further from Rx. + +[Actions]: Documentation/FrameworkOverview.md#actions +[Events]: Documentation/FrameworkOverview.md#events +[Schedulers]: Documentation/FrameworkOverview.md#schedulers +[SignalProducer]: Documentation/FrameworkOverview.md#signal-producers +[Signal]: Documentation/FrameworkOverview.md#signals +[functional reactive programming]: https://en.wikipedia.org/wiki/Functional_reactive_programming +[ReactiveX]: https://reactivex.io/ +[RxSwift]: https://github.com/ReactiveX/RxSwift/#readme +[Swift API Guidelines]: https://swift.org/documentation/api-design-guidelines/ diff --git a/Carthage/Checkouts/ReactiveSwift/LICENSE.md b/Carthage/Checkouts/ReactiveSwift/LICENSE.md new file mode 100644 index 0000000..49bc374 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/LICENSE.md @@ -0,0 +1,19 @@ +**Copyright (c) 2012 - 2016, GitHub, Inc.** +**All rights reserved.** + +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/ReactiveSwift/Logo/AF/Docs.afdesign b/Carthage/Checkouts/ReactiveSwift/Logo/AF/Docs.afdesign new file mode 100644 index 0000000000000000000000000000000000000000..135f2ff4793b7fbfa2b6baa9b6bef380fd66f728 GIT binary patch literal 17668 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 literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/AF/JoinSlack.afdesign b/Carthage/Checkouts/ReactiveSwift/Logo/AF/JoinSlack.afdesign new file mode 100644 index 0000000000000000000000000000000000000000..97ce8cb9d7f2a1019f6a04e81a2e82650ced8cba GIT binary patch literal 1108845 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ℑi+z;be#F7YDf`8W8U>bwsUIvPZ~R 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 literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/AF/ReactiveSwift.afdesign b/Carthage/Checkouts/ReactiveSwift/Logo/AF/ReactiveSwift.afdesign new file mode 100644 index 0000000000000000000000000000000000000000..f82fcec0af80cf7a14cb07f6638c4d6596a04b37 GIT binary patch literal 26616 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 literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/Icons/Swift.png b/Carthage/Checkouts/ReactiveSwift/Logo/Icons/Swift.png new file mode 100644 index 0000000000000000000000000000000000000000..693f4fd9a2a70127c062c70fbf7f36183bc5dd5e GIT binary patch literal 111851 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 n>;K_B$?j(uPz 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 CC|l70 literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/Icons/docset-icon.png b/Carthage/Checkouts/ReactiveSwift/Logo/Icons/docset-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..774178cf855a9ee8b6e92782c516241860eca512 GIT binary patch literal 1438 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 literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/PNG/JoinSlack.png b/Carthage/Checkouts/ReactiveSwift/Logo/PNG/JoinSlack.png new file mode 100644 index 0000000000000000000000000000000000000000..5f720122601a45383ed0eb33520d42590ab8f4f8 GIT binary patch literal 7065 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

7!f`bBk_V`gG4SxR{-P%t3++KOGcb@MQix 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

q_yJb;ve<~>kS~7f$wP=+H%{`ZR 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 FV1f#}JsJQ2 literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/PNG/logo-Swift.png b/Carthage/Checkouts/ReactiveSwift/Logo/PNG/logo-Swift.png new file mode 100644 index 0000000000000000000000000000000000000000..2afccb19368fea1705a2726e21f40bd50a36adce GIT binary patch literal 42578 zcmY&5?W)f8FPRg}bpB*nz|g!zT=@VMW*zMta>dUm@@zA8M43-p*j!KuinkE;)P@T4h4J@l4;mu zwedc!cPW_l0IA`*+J56o z%ms6QX-)AX)2yA(nQuJj)#uU1W}==3HA?C#mTlNJ{wMt0-i~X7H=C1@yt^^o#u5+7 z6Z9=0Wf56=h1nHRUmK9KT3&kh=eoSZWz*AAY34Wz7}F^6&m@v91EJp6h1o|#83hQ- zvQ(S$lH{LgJJXatSbtsk?yd?;;^%_rvix#vULflf*YZoh)BJmH8*~TBjbj*OSLuGx8~eEB zl)i%Z(J9|UzIZQvIqWa0HpV?Y@vnY(=Qpj(ktJ()rxc(h@s})5`?jLm#0BWPB)g z9-*NvJ^@w>vJ{|7y5fl`n)D&eE$pPwd{birsvI*UQ4oFbFc8ffKj4tCrE|b~H#gIm z!8Yft&6SboI`hLo@Z6+@_7bFvVqXw8EK`pw`Bv+9B|Tks8Iy=3zV*+IA*=z~By8>Y zq4N8`vI6q(V~89cioRUfN!$(!Pu+Z_S(3;9HGcZFjf@V@>l{RV)9qw>>7`}Dvh<^g z2gk!OmgQgdV|CDBKOqm8Y?{2SDWeFJn!A~B^|s{5Hr@PDnw`htlvgI%e+5+}Ddl+g z=w2}8f`4m<=Lz1?4YW#2>3L9#-}cM#xib>blh>NP!o|9yLkZzXPOlKdQNDzPcSz2w zx$F8Oo$iOyRz;ph-2sq{P`=C6IIGwDNUY@ezBYeaITjKldn#!=9{yLOe?*+Rdd&rR zLr!v*oOcJm;YQ6|1g6Q45+q{SX!puEP?&FI++a<(am>Ac!pyCSr=j2YTe=CInYm4W zyoSc)?H`8$1se?Id2W{3>qUp&$O%Woypn9l+-zIYFS%P2Rs+7nO!WVXR`f?S%P!1- z%()>ttz|}^$x!l)^K^8XHFarCLsMW#gkQEK>GGbV`9#mdk|xRW9#d2~*2tl)vYo{0 zo0<5{@@-$7k$Dg%Y6F^a^b?tU?H|SQeb>Lk4gki^91v&j_7Q7AI1F#>Ri)Fdd#QA? zUGbse+h!%Nt#sY&M4ANjZ%gYf2pJ7D5x*y+t`-=JaL~3WLdkh8n0O1Lwp{i5ni8Yw z4vmG*nXLOY_gCx3`Y|sbqz{T{{C`X;hS^6m{Z^kFFW?P2cygpj;jyFb?T~`2GdJUY zm_HB}EQor=En55BsE1V-oLji4!O3QS7QYwHxJEyfIMx8>hHSE>a$p~(yV7~pNls2H zUDmnGG&K?{`qihb`!hnCFT#6siAnzvQTBb%Z!{v>Gd#Vno)N+#V0c=uXI@iJo%U6; zKUd>@)7f=l(+`~kz3w8$8T`n4z~SaOSGU<#*(9_pOZA!S2|}N{!fG=`PO=KFiJb&B zOeo!}ZttcW-9V;dS9~y!e%Wt{Wz^7}$WzyczRNfVtsPKg?!~D7BQ$e+dXe@c;DR9? zKm6v-@X?!*Pw!Vyq*xbCb>l7rr%VMtrVdQLtCK5}rI>iq&DD>7sKVz7hjslE%VtIj zk;S%r?+zOa+R%5$Se1=)+e>Ks7M2W%J|JhT)nQIRbHpKF5=gcV;?cQP3o_dwe0uTYRo-uAN+*kG?gWoPE9^=J@Z; z04*OX6QofphNY<`G+rN2IC^8eVH7S)^X^Hc(wB1bI?HD@bRkkAD6{e|pT?C9uR*?1 z5Jz`+@gUVT_}0|9azMZPScK-UsLkHi<+A4v^G&8a=UVxC&Pi_V$-A``gKiN5c%$g3Q$gT2C4HW5M(1pEwO3bXMo?E zcKG;C)IT&JP4b5Z+^$~~PEq(9poQPyn9xB_tGooH5=*=87`MiEsu G%BvDW9!aW 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 literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/Palette.png b/Carthage/Checkouts/ReactiveSwift/Logo/Palette.png new file mode 100644 index 0000000000000000000000000000000000000000..111199149c79942829def7342e9f20626d2b1e93 GIT binary patch literal 11112 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 Vf>Z5n;L};q3uTR`@F(V>{|9988L$8V literal 0 HcmV?d00001 diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/README.md b/Carthage/Checkouts/ReactiveSwift/Logo/README.md new file mode 100644 index 0000000..e18b32e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Logo/README.md @@ -0,0 +1,24 @@ +This folder contains brand assets. + +# Logo + +Four horizontal variations that include both the mark and the logotype. When +using the logo in contexts where it's surrounded by other elements, leave +a padding of about 10% of its height on each side. + +# Icon + +Four icon variations to be used on social media and other contexts where the +horizontal logo wouldn't fit. + +# Colors + +Primary color: `#88CD79` +Secondary color: `#41AD71` +Tertiary color: `#4F6B97` + +![](Palette.png) + +# Type + +Avenir Next, designed by Adrian Frutiger and Akira Kobayashi for Linotype. diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/SVG/logo-Swift.svg b/Carthage/Checkouts/ReactiveSwift/Logo/SVG/logo-Swift.svg new file mode 100644 index 0000000..10dc503 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Logo/SVG/logo-Swift.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + S + + w + + i + f + t + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Logo/header.png b/Carthage/Checkouts/ReactiveSwift/Logo/header.png new file mode 100644 index 0000000000000000000000000000000000000000..95b4dece8faea25b18a1d2e7cd9e4020adf07485 GIT binary patch literal 43393 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%0AJUi*4yQp_&AEPSBWS<2TrSsNA=m8 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 + ReactiveSwift

+ Streams of values over time. Tailored for Swift.

+ Latest ReactiveSwift Documentation Join the ReactiveSwift Slack community. +

+
+ +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](#carthage) [![CocoaPods compatible](https://img.shields.io/cocoapods/v/ReactiveSwift.svg)](#cocoapods) [![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-orange.svg)](#swift-package-manager) [![GitHub release](https://img.shields.io/github/release/ReactiveCocoa/ReactiveSwift.svg)](https://github.com/ReactiveCocoa/ReactiveSwift/releases) ![Swift 3.0.x](https://img.shields.io/badge/Swift-3.0.x-orange.svg) ![platforms](https://img.shields.io/badge/platform-iOS%20%7C%20macOS%20%7C%20tvOS%20%7C%20watchOS%20%7C%20Linux-lightgrey.svg) + +☕️ [Looking for Cocoa extensions?][ReactiveCocoa] +🎉 [Getting Started](#getting-started) +⚠️ [Still using Swift 2.x?][] + + +🚄 [Release Roadmap](#release-roadmap) +## What is ReactiveSwift? +__ReactiveSwift__ offers composable, declarative and flexible primitives that are built around the grand concept of ___streams of values over time___. + +These primitives can be used to uniformly represent common Cocoa and generic programming patterns that are fundamentally an act of observation, e.g. delegate pattern, callback closures, notifications, control actions, responder chain events, [futures/promises](https://en.wikipedia.org/wiki/Futures_and_promises) and [key-value observing](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html) (KVO). + +Because all of these different mechanisms can be represented in the _same_ way, +it’s easy to declaratively compose them together, with less spaghetti +code and state to bridge the gap. + +## Getting Started + +1. **[Core Reactive Primitives][]** + + An overview of the semantics and example use cases of the ReactiveSwift primitives, including [`Signal`][], [`SignalProducer`][], [`Property`][] and [`Action`][]. + +1. **[Basic Operators][]** + + An overview of the operators provided to compose and transform streams of values. + +1. **[How does ReactiveSwift relate to RxSwift?][]** + + An overview of how ReactiveSwift differs from RxSwift for Swift idiomaticity. + +## Examples + +1. **Interactive Form UI** + + ReactiveSwift includes a [_UI Examples_ playground][], which demonstrates: + * how to build an interactive form UI with bindings, properties and `Action`s, with a live view in action. + * how to use reactive primitives to implement the Model-View-ViewModel architectural pattern, with the View Model being the source of truth for the View. + +1. **[Online Searching][]** + +## Advanced Topics + +1. **[ReactiveCocoa][]** + + Bindings and reactive extensions for Cocoa and Cocoa Touch frameworks are offered separately as ReactiveCocoa. + +1. **[API Reference][]** + +1. **[API Contracts][]** + + Contracts of the ReactiveSwift primitives, Best Practices with ReactiveSwift, and Guidelines on implementing custom operators. + +1. **[Debugging Techniques][]** + +## Installation + +ReactiveSwift supports macOS 10.9+, iOS 8.0+, watchOS 2.0+, tvOS 9.0+ and Linux. + +#### Carthage + +If you use [Carthage][] to manage your dependencies, simply add +ReactiveSwift to your `Cartfile`: + +``` +github "ReactiveCocoa/ReactiveSwift" ~> 1.1 +``` + +If you use Carthage to build your dependencies, make sure you have added `ReactiveSwift.framework`, and `Result.framework` to the "_Linked Frameworks and Libraries_" section of your target, and have included them in your Carthage framework copying build phase. + +#### CocoaPods + +If you use [CocoaPods][] to manage your dependencies, simply add +ReactiveSwift to your `Podfile`: + +``` +pod 'ReactiveSwift', '~> 1.1' +``` + +#### Swift Package Manager + +If you use Swift Package Manager, simply add ReactiveSwift as a dependency +of your package in `Package.swift`: + +``` +.Package(url: "https://github.com/ReactiveCocoa/ReactiveSwift.git", majorVersion: 1) +``` + +#### Git submodule + + 1. Add the ReactiveSwift repository as a [submodule][] of your + application’s repository. + 1. Run `git submodule update --init --recursive` from within the ReactiveCocoa folder. + 1. Drag and drop `ReactiveSwift.xcodeproj` and + `Carthage/Checkouts/Result/Result.xcodeproj` into your application’s Xcode + project or workspace. + 1. On the “General” tab of your application target’s settings, add + `ReactiveSwift.framework`, and `Result.framework` + to the “Embedded Binaries” section. + 1. If your application target does not contain Swift code at all, you should also + set the `EMBEDDED_CONTENT_CONTAINS_SWIFT` build setting to “Yes”. + +## Playground + +We also provide a great Playground, so you can get used to ReactiveCocoa's operators. In order to start using it: + + 1. Clone the ReactiveSwift repository. + 1. Retrieve the project dependencies using one of the following terminal commands from the ReactiveSwift project root directory: + - `git submodule update --init --recursive` **OR**, if you have [Carthage][] installed + - `carthage checkout` + 1. Open `ReactiveSwift.xcworkspace` + 1. Build `Result-Mac` scheme + 1. Build `ReactiveSwift-macOS` scheme + 1. Finally open the `ReactiveSwift.playground` + 1. Choose `View > Show Debug Area` + +## Have a question? +If you need any help, please visit our [GitHub issues][] or [Stack Overflow][]. Feel free to file an issue if you do not manage to find any solution from the archives. + +## Release Roadmap +**Current Stable Release:**
[![GitHub release](https://img.shields.io/github/release/ReactiveCocoa/ReactiveSwift.svg)](https://github.com/ReactiveCocoa/ReactiveSwift/releases) + +### In Development +#### ReactiveSwift 2.0 +It targets Swift 3.1. The estimated schedule is WWDC 2017. + +The primary goal of ReactiveSwift 2.0 is to take advantage of **concrete same-type requirements** introduced in Swift 3.1. As a result: + +1. A few single-implementation protocols were removed; and +2. `Signal` and `SignalProducer` operators were moved from the protocols to the concrete types. + +These changes are source breaking, but are automatically or trivially migratable. + +ReactiveSwift 2.0 has continued the work in polishing the APIs, preparing for the eventual API freeze for library resilience. + +#### Swift 3.2 and Swift 4.0 compatibility +While the development would be Swift 3.2 and Swift 4.0 aware, ReactiveSwift 2.0 would not declare official support until Swift 3.2 and Swift 4.0 launch. + +The official release for Swift 3.2 and Swift 4.0 is expected to be a minor 2.x release with full API compatibility. + +### Plan of Record +#### ReactiveSwift 3.0 +ReactiveSwift 3.0 is expected to declare library ABI stability as it adopts generics features arriving in a later Swift 4 release, e.g. conditional conformance. There is no ETA for now. + +[Core Reactive Primitives]: Documentation/ReactivePrimitives.md +[Basic Operators]: Documentation/BasicOperators.md +[How does ReactiveSwift relate to RxSwift?]: Documentation/RxComparison.md +[API Contracts]: Documentation/APIContracts.md +[API Reference]: http://reactivecocoa.io/reactiveswift/docs/latest/ +[Debugging Techniques]: Documentation/DebuggingTechniques.md +[Online Searching]: Documentation/Example.OnlineSearch.md +[_UI Examples_ playground]: https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Contents.swift + +[`Action`]: Documentation/ReactivePrimitives.md#action-a-serialized-worker-with-a-preset-action +[`SignalProducer`]: Documentation/ReactivePrimitives.md#signalproducer-deferred-work-that-creates-a-stream-of-values +[`Signal`]: Documentation/ReactivePrimitives.md#signal-a-unidirectional-stream-of-events +[`Property`]: Documentation/ReactivePrimitives.md#property-an-observable-box-that-always-holds-a-value + +[ReactiveCocoa]: https://github.com/ReactiveCocoa/ReactiveCocoa/#readme + +[Carthage]: https://github.com/Carthage/Carthage/#readme +[CocoaPods]: https://cocoapods.org/ +[submodule]: https://git-scm.com/docs/git-submodule + +[GitHub issues]: https://github.com/ReactiveCocoa/ReactiveSwift/issues?q=is%3Aissue+label%3Aquestion+ +[Stack Overflow]: http://stackoverflow.com/questions/tagged/reactive-cocoa + +[Looking for the Objective-C API?]: https://github.com/ReactiveCocoa/ReactiveObjC/#readme +[Still using Swift 2.x?]: https://github.com/ReactiveCocoa/ReactiveCocoa/tree/v4.0.0 diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Contents.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..659cf7a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Contents.swift @@ -0,0 +1,154 @@ +import ReactiveSwift +import Result +import UIKit +import PlaygroundSupport + +final class ViewModel { + struct FormError: Error { + let reason: String + + static let invalidEmail = FormError(reason: "The address must end with `@reactivecocoa.io`.") + static let mismatchEmail = FormError(reason: "The e-mail addresses do not match.") + static let usernameUnavailable = FormError(reason: "The username has been taken.") + } + + let email: ValidatingProperty + let emailConfirmation: ValidatingProperty + let termsAccepted: MutableProperty + + let submit: Action<(), (), FormError> + + let reasons: Signal + + init(userService: UserService) { + email = ValidatingProperty("") { input in + return input.hasSuffix("@reactivecocoa.io") ? .valid : .invalid(.invalidEmail) + } + + emailConfirmation = ValidatingProperty("", with: email) { input, email in + return input == email ? .valid : .invalid(.mismatchEmail) + } + + termsAccepted = MutableProperty(false) + + // `validatedEmail` is a property which holds the validated email address if + // the entire form is valid, or it holds `nil` otherwise. + // + // The condition used in the `map` transform is: + // 1. `emailConfirmation` passes validation: `!email.isInvalid`; and + // 2. `termsAccepted` is asserted: `accepted`. + let validatedEmail: Property = Property.combineLatest(emailConfirmation.result, + termsAccepted) + .map { (email: ValidationResult, accepted: Bool) -> String? in + return !email.isInvalid && accepted ? email.value! : nil + } + + // The action to be invoked when the submit button is pressed. + // + // Recall that `submit` is an `Action` with no input, i.e. `Input == ()`. + // `Action` provides a special initializer in this case: `init(state:)`. + // It takes a property of optionals — in our case, `validatedEmail` — and + // would disable whenever the property holds `nil`. + submit = Action(state: validatedEmail) { (email: String) in + let username = email.stripSuffix("@reactivecocoa.io")! + + return userService.canUseUsername(username) + .promoteErrors(FormError.self) + .attemptMap { Result<(), FormError>($0 ? () : nil, failWith: .usernameUnavailable) } + } + + // `reason` is an aggregate of latest validation error for the UI to display. + reasons = Property.combineLatest(email.result, emailConfirmation.result) + .signal + .debounce(0.1, on: QueueScheduler.main) + .map { [$0, $1].flatMap { $0.error?.reason }.joined(separator: "\n") } + } +} + +final class ViewController: UIViewController { + private let viewModel: ViewModel + private var formView: FormView! + + override func viewDidLoad() { + super.viewDidLoad() + + // Initialize the interactive controls. + formView.emailField.text = viewModel.email.value + formView.emailConfirmationField.text = viewModel.emailConfirmation.value + formView.termsSwitch.isOn = false + + // Setup bindings with the interactive controls. + viewModel.email <~ formView.emailField.reactive + .continuousTextValues.skipNil() + + viewModel.emailConfirmation <~ formView.emailConfirmationField.reactive + .continuousTextValues.skipNil() + + viewModel.termsAccepted <~ formView.termsSwitch.reactive + .isOnValues + + // Setup bindings with the invalidation reason label. + formView.reasonLabel.reactive.text <~ viewModel.reasons + + // Setup the Action binding with the submit button. + formView.submitButton.reactive.pressed = CocoaAction(viewModel.submit) + } + + override func loadView() { + formView = FormView() + view = formView + } + + init(_ viewModel: ViewModel) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + } + + required init?(coder aDecoder: NSCoder) { + fatalError() + } +} + +final class UserService { + let (requestSignal, requestObserver) = Signal.pipe() + + func canUseUsername(_ string: String) -> SignalProducer { + return SignalProducer { observer, disposable in + self.requestObserver.send(value: string) + observer.send(value: true) + observer.sendCompleted() + } + } +} + +func main() { + let userService = UserService() + let viewModel = ViewModel(userService: userService) + let viewController = ViewController(viewModel) + let window = UIWindow(frame: CGRect(x: 0, y: 0, width: 300, height: 350)) + window.rootViewController = viewController + + PlaygroundPage.current.liveView = window + PlaygroundPage.current.needsIndefiniteExecution = true + + window.makeKeyAndVisible() + + // Setup console messages. + userService.requestSignal.observeValues { + print("UserService.requestSignal: Username `\($0)`.") + } + + viewModel.submit.completed.observeValues { + print("ViewModel.submit: execution producer has completed.") + } + + viewModel.email.result.signal.observeValues { + print("ViewModel.email: Validation result - \($0 != nil ? "\($0!)" : "No validation has ever been performed.")") + } + + viewModel.emailConfirmation.result.signal.observeValues { + print("ViewModel.emailConfirmation: Validation result - \($0 != nil ? "\($0!)" : "No validation has ever been performed.")") + } +} + +main() diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/FormView.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/FormView.swift new file mode 100644 index 0000000..6248538 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/FormView.swift @@ -0,0 +1,88 @@ +import UIKit +import ReactiveSwift +import Result + +public class FormView: UIView { + let _lifetime = Lifetime.Token() + lazy var lifetime: Lifetime = Lifetime(self._lifetime) + + private let disposable = SerialDisposable() + + public let emailField = UITextField() + public let emailConfirmationField = UITextField() + public let termsSwitch = UISwitch() + public let submitButton = UIButton(type: .system) + public let reasonLabel = UILabel() + + convenience init() { + self.init(frame: CGRect(x: 0, y: 0, width: 300, height: 350)) + + backgroundColor = .white + + addSubview(emailField) + addSubview(emailConfirmationField) + addSubview(termsSwitch) + addSubview(submitButton) + addSubview(reasonLabel) + + let labelFont = UIFont.systemFont(ofSize: UIFont.smallSystemFontSize) + + // Email Field. + let emailLabel = UILabel(frame: CGRect(x: 20, y: 20, width: 260, height: 20)) + emailLabel.font = labelFont + emailLabel.text = "E-mail" + addSubview(emailLabel) + + emailField.borderStyle = .roundedRect + emailField.frame.origin = CGPoint(x: 20, y: 40) + emailField.frame.size = CGSize(width: 260, height: 30) + emailField.autocapitalizationType = .none + + // Email Confirmation Field. + let emailConfirmationLabel = UILabel(frame: CGRect(x: 20, y: 80, width: 260, height: 20)) + emailConfirmationLabel.font = labelFont + emailConfirmationLabel.text = "Confirm E-mail" + addSubview(emailConfirmationLabel) + + emailConfirmationField.borderStyle = .roundedRect + emailConfirmationField.frame.origin = CGPoint(x: 20, y: 100) + emailConfirmationField.frame.size = CGSize(width: 260, height: 30) + emailConfirmationField.autocapitalizationType = .none + + // Accept Terms Switch + let termsSwitchLabel = UILabel(frame: CGRect(x: 80, y: 155, width: 200, height: 20)) + termsSwitchLabel.font = labelFont + termsSwitchLabel.text = "Accept Terms and Conditions" + addSubview(termsSwitchLabel) + + termsSwitch.frame.origin = CGPoint(x: 20, y: 150) + + // Submit Button + submitButton.titleLabel!.font = labelFont + submitButton.setBackgroundColor(submitButton.tintColor, for: .normal) + submitButton.setBackgroundColor(UIColor(white: 0.85, alpha: 1.0), for: .disabled) + submitButton.setTitleColor(.white, for: .normal) + submitButton.setTitle("Submit", for: .normal) + submitButton.frame.origin = CGPoint(x: 20, y: 200) + submitButton.frame.size = CGSize(width: 260, height: 30) + + // Reason Label + reasonLabel.frame.origin = CGPoint(x: 20, y: 250) + reasonLabel.frame.size = CGSize(width: 260, height: 80) + reasonLabel.numberOfLines = 0 + reasonLabel.font = labelFont + } +} + +// http://stackoverflow.com/questions/26600980/how-do-i-set-uibutton-background-color-forstate-uicontrolstate-highlighted-in-s +extension UIButton { + func setBackgroundColor(_ color: UIColor, for state: UIControlState) { + UIGraphicsBeginImageContext(CGSize(width: 1, height: 1)) + let context = UIGraphicsGetCurrentContext()! + context.setFillColor(color.cgColor) + context.fill(CGRect(x: 0, y: 0, width: 1, height: 1)) + let colorImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + self.setBackgroundImage(colorImage, for: state) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/StdlibExtensions.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/StdlibExtensions.swift new file mode 100644 index 0000000..1e30426 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/StdlibExtensions.swift @@ -0,0 +1,10 @@ +import Foundation + +extension String { + public func stripSuffix(_ suffix: String) -> String? { + if let range = range(of: suffix) { + return substring(with: startIndex ..< range.lowerBound) + } + return nil + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/UIKitExtensions.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/UIKitExtensions.swift new file mode 100644 index 0000000..39ce937 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Pages/ValidatingProperty.xcplaygroundpage/Sources/UIKitExtensions.swift @@ -0,0 +1,123 @@ +import Foundation +import UIKit +import ReactiveSwift +import enum Result.NoError + +// These extensions mimics the ReactiveCocoa API, but not in a complete way. +// +// For production use, check the ReactiveCocoa framework: +// https://github.com/ReactiveCocoa/ReactiveCocoa/ + +private let lifetimeKey = UnsafeMutablePointer.allocate(capacity: 1) +private let pressedKey = UnsafeMutablePointer.allocate(capacity: 1) + +public final class CocoaTarget { + let _execute: (Any) -> Void + + init(_ body: @escaping (Any) -> Void) { + _execute = body + } + + @objc func execute(_ sender: Any) { + _execute(sender) + } +} + +public final class CocoaAction { + let _execute: () -> Void + let isEnabled: Property + + public init(_ action: Action<(), Output, Error>) { + _execute = { action.apply().start() } + isEnabled = action.isEnabled + } + + @objc func execute(_ sender: Any) { + _execute() + } +} + +extension NSObject: ReactiveExtensionsProvider {} + +extension Reactive where Base: NSObject { + public var lifetime: Lifetime { + if let (lifetime, _) = objc_getAssociatedObject(base, lifetimeKey) as! (Lifetime, Lifetime.Token)? { + return lifetime + } + + let token = Lifetime.Token() + let lifetime = Lifetime(token) + objc_setAssociatedObject(base, lifetimeKey, (lifetime, token), .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + + return lifetime + } +} + +extension Reactive where Base: UILabel { + public var text: BindingTarget { + return BindingTarget(lifetime: lifetime) { [weak base] value in + base?.text = value + } + } +} + +extension Reactive where Base: UISwitch { + public var isOnValues: Signal { + return Signal { observer in + let target = CocoaTarget { observer.send(value: ($0 as! UISwitch).isOn) } + base.addTarget(target, action: #selector(target.execute), for: .valueChanged) + return ActionDisposable { _ = target } + } + } +} + +extension Reactive where Base: UITextField { + public var continuousTextValues: Signal { + return Signal { observer in + let target = CocoaTarget { observer.send(value: ($0 as! UITextField).text) } + base.addTarget(target, action: #selector(target.execute), for: .editingChanged) + return ActionDisposable { _ = target } + } + } +} + +extension Reactive where Base: UIControl { + public var isEnabled: BindingTarget { + return BindingTarget(lifetime: lifetime) { [weak base] value in + base?.isEnabled = value + } + } +} + +extension Reactive where Base: UIButton { + public var pressed: CocoaAction? { + get { + if let (action, _) = objc_getAssociatedObject(base, pressedKey) as! (CocoaAction?, SerialDisposable)? { + return action + } + return nil + } + + nonmutating set { + let disposable: SerialDisposable = { + if let (_, disposable) = objc_getAssociatedObject(base, pressedKey) as! (CocoaAction?, SerialDisposable)? { + return disposable + } + + let d = SerialDisposable() + objc_setAssociatedObject(base, pressedKey, (nil, d) as (CocoaAction?, SerialDisposable), .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + return d + }() + + if let newAction = newValue { + base.addTarget(newAction, action: #selector(newAction.execute), for: .touchUpInside) + let d = CompositeDisposable() + d += isEnabled <~ newAction.isEnabled.producer + d += { _ = newAction } + disposable.inner = d + } else { + disposable.inner = nil + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Sources/PlaygroundUtility.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Sources/PlaygroundUtility.swift new file mode 100644 index 0000000..282b07f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/Sources/PlaygroundUtility.swift @@ -0,0 +1,10 @@ +import Foundation + +public func scopedExample(_ exampleDescription: String, _ action: () -> Void) { + print("\n--- \(exampleDescription) ---\n") + action() +} + +public enum PlaygroundError: Error { + case example(String) +} diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/contents.xcplayground b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/contents.xcplayground new file mode 100644 index 0000000..5ed2911 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift-UIExamples.playground/contents.xcplayground @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Property.xcplaygroundpage/Contents.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Property.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..8f7f606 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Property.xcplaygroundpage/Contents.swift @@ -0,0 +1,273 @@ +/*: + > # IMPORTANT: To use `ReactiveSwift.playground`, please: + + 1. Retrieve the project dependencies using one of the following terminal commands from the ReactiveSwift project root directory: + - `git submodule update --init` + **OR**, if you have [Carthage](https://github.com/Carthage/Carthage) installed + - `carthage checkout` + 1. Open `ReactiveSwift.xcworkspace` + 1. Build `Result-Mac` scheme + 1. Build `ReactiveSwift-macOS` scheme + 1. Finally open the `ReactiveSwift.playground` + 1. Choose `View > Show Debug Area` + */ +import Result +import ReactiveSwift +import Foundation +/*: + ## Property + + A **property**, represented by the [`PropertyProtocol`](https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/Sources/Property.swift) , + stores a value and notifies observers about future changes to that value. + + - The current value of a property can be obtained from the `value` getter. + - The `producer` getter returns a [signal producer](SignalProducer) that will send the property’s current value, followed by all changes over time. + - The `signal` getter returns a [signal](Signal) that will send all changes over time, but not the initial value. + + */ +scopedExample("Creation") { + let mutableProperty = MutableProperty(1) + + // The value of the property can be accessed via its `value` attribute + print("Property has initial value \(mutableProperty.value)") + // The properties value can be observed via its `producer` or `signal attribute` + // Note, how the `producer` immediately sends the initial value, but the `signal` only sends new values + mutableProperty.producer.startWithValues { + print("mutableProperty.producer received \($0)") + } + mutableProperty.signal.observeValues { + print("mutableProperty.signal received \($0)") + } + + print("---") + print("Setting new value for mutableProperty: 2") + mutableProperty.value = 2 + + print("---") + // If a property should be exposed for readonly access, it can be wrapped in a Property + let property = Property(mutableProperty) + + print("Reading value of readonly property: \(property.value)") + property.signal.observeValues { + print("property.signal received \($0)") + } + + // Its not possible to set the value of a Property +// readonlyProperty.value = 3 + // But you can still change the value of the mutableProperty and observe its change on the property + print("---") + print("Setting new value for mutableProperty: 3") + mutableProperty.value = 3 + + // Constant properties can be created by using the `Property(value:)` initializer + let constant = Property(value: 1) +// constant.value = 2 // The value of a constant property can not be changed +} +/*: + ### Binding + + The `<~` operator can be used to bind properties in different ways. Note that in + all cases, the target has to be a binding target, represented by the [`BindingTargetProtocol`](https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/Sources/UnidirectionalBinding.swift). All mutable property types, represented by the [`MutablePropertyProtocol`](https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/Sources/Property.swift#L28), are inherently binding targets. + + * `property <~ signal` binds a [signal](#signals) to the property, updating the + property’s value to the latest value sent by the signal. + * `property <~ producer` starts the given [signal producer](#signal-producers), + and binds the property’s value to the latest value sent on the started signal. + * `property <~ otherProperty` binds one property to another, so that the destination + property’s value is updated whenever the source property is updated. + */ +scopedExample("Binding from SignalProducer") { + let producer = SignalProducer { observer, _ in + print("New subscription, starting operation") + observer.send(value: 1) + observer.send(value: 2) + } + let property = MutableProperty(0) + property.producer.startWithValues { + print("Property received \($0)") + } + + // Notice how the producer will start the work as soon it is bound to the property + property <~ producer +} + +scopedExample("Binding from Signal") { + let (signal, observer) = Signal.pipe() + let property = MutableProperty(0) + property.producer.startWithValues { + print("Property received \($0)") + } + + property <~ signal + + print("Sending new value on signal: 1") + observer.send(value: 1) + + print("Sending new value on signal: 2") + observer.send(value: 2) +} + +scopedExample("Binding from other Property") { + let property = MutableProperty(0) + property.producer.startWithValues { + print("Property received \($0)") + } + + let otherProperty = MutableProperty(0) + + // Notice how property receives another value of 0 as soon as the binding is established + property <~ otherProperty + + print("Setting new value for otherProperty: 1") + otherProperty.value = 1 + + print("Setting new value for otherProperty: 2") + otherProperty.value = 2 +} +/*: + ### Transformations + + Properties provide a number of transformations like `map`, `combineLatest` or `zip` for manipulation similar to [signal](Signal) and [signal producer](SignalProducer) + */ +scopedExample("`map`") { + let property = MutableProperty(0) + let mapped = property.map { $0 * 2 } + mapped.producer.startWithValues { + print("Mapped property received \($0)") + } + + print("Setting new value for property: 1") + property.value = 1 + + print("Setting new value for property: 2") + property.value = 2 +} + +scopedExample("`skipRepeats`") { + let property = MutableProperty(0) + let skipRepeatsProperty = property.skipRepeats() + + property.producer.startWithValues { + print("Property received \($0)") + } + skipRepeatsProperty.producer.startWithValues { + print("Skip-Repeats property received \($0)") + } + + print("Setting new value for property: 0") + property.value = 0 + print("Setting new value for property: 1") + property.value = 1 + print("Setting new value for property: 1") + property.value = 1 + print("Setting new value for property: 0") + property.value = 0 +} + +scopedExample("`uniqueValues`") { + let property = MutableProperty(0) + let unique = property.uniqueValues() + property.producer.startWithValues { + print("Property received \($0)") + } + unique.producer.startWithValues { + print("Unique values property received \($0)") + } + + print("Setting new value for property: 0") + property.value = 0 + print("Setting new value for property: 1") + property.value = 1 + print("Setting new value for property: 1") + property.value = 1 + print("Setting new value for property: 0") + property.value = 0 + +} + +scopedExample("`combineLatest`") { + let propertyA = MutableProperty(0) + let propertyB = MutableProperty("A") + let combined = propertyA.combineLatest(with: propertyB) + combined.producer.startWithValues { + print("Combined property received \($0)") + } + + print("Setting new value for propertyA: 1") + propertyA.value = 1 + + print("Setting new value for propertyB: 'B'") + propertyB.value = "B" + + print("Setting new value for propertyB: 'C'") + propertyB.value = "C" + + print("Setting new value for propertyB: 'D'") + propertyB.value = "D" + + print("Setting new value for propertyA: 2") + propertyA.value = 2 +} + +scopedExample("`zip`") { + let propertyA = MutableProperty(0) + let propertyB = MutableProperty("A") + let zipped = propertyA.zip(with: propertyB) + zipped.producer.startWithValues { + print("Zipped property received \($0)") + } + + print("Setting new value for propertyA: 1") + propertyA.value = 1 + + print("Setting new value for propertyB: 'B'") + propertyB.value = "B" + + // Observe that, in contrast to `combineLatest`, setting a new value for propertyB does not cause a new value for the zipped property until propertyA has a new value as well + print("Setting new value for propertyB: 'C'") + propertyB.value = "C" + + print("Setting new value for propertyB: 'D'") + propertyB.value = "D" + + print("Setting new value for propertyA: 2") + propertyA.value = 2 +} + +scopedExample("`flatten`") { + let property1 = MutableProperty("0") + let property2 = MutableProperty("A") + let property3 = MutableProperty("!") + let property = MutableProperty(property1) + // Try different merge strategies and see how the results change + property.flatten(.latest).producer.startWithValues { + print("Flattened property receive \($0)") + } + + print("Sending new value on property1: 1") + property1.value = "1" + + print("Sending new value on property: property2") + property.value = property2 + + print("Sending new value on property1: 2") + property1.value = "2" + + print("Sending new value on property2: B") + property2.value = "B" + + print("Sending new value on property1: 3") + property1.value = "3" + + print("Sending new value on property: property3") + property.value = property3 + + print("Sending new value on property3: ?") + property3.value = "?" + + print("Sending new value on property2: C") + property2.value = "C" + + print("Sending new value on property1: 4") + property1.value = "4" +} diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Sandbox.xcplaygroundpage/Contents.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Sandbox.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..ede2832 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Sandbox.xcplaygroundpage/Contents.swift @@ -0,0 +1,25 @@ +/*: + > # IMPORTANT: To use `ReactiveSwift.playground`, please: + + 1. Retrieve the project dependencies using one of the following terminal commands from the ReactiveSwift project root directory: + - `git submodule update --init` + **OR**, if you have [Carthage](https://github.com/Carthage/Carthage) installed + - `carthage checkout --no-use-binaries` + 1. Open `ReactiveSwift.xcworkspace` + 1. Build `Result-Mac` scheme + 1. Build `ReactiveSwift-macOS` scheme + 1. Finally open the `ReactiveSwift.playground` + 1. Choose `View > Show Debug Area` + */ + +import Result +import ReactiveSwift +import Foundation + +/*: + ## Sandbox + + A place where you can build your sand castles 🏖. +*/ + + diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Signal.xcplaygroundpage/Contents.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Signal.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..e3a401a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/Signal.xcplaygroundpage/Contents.swift @@ -0,0 +1,240 @@ +/*: +> # IMPORTANT: To use `ReactiveSwift.playground`, please: + +1. Retrieve the project dependencies using one of the following terminal commands from the ReactiveSwift project root directory: + - `git submodule update --init` + **OR**, if you have [Carthage](https://github.com/Carthage/Carthage) installed + - `carthage checkout` +1. Open `ReactiveSwift.xcworkspace` +1. Build `Result-Mac` scheme +1. Build `ReactiveSwift-macOS` scheme +1. Finally open the `ReactiveSwift.playground` +1. Choose `View > Show Debug Area` +*/ + +import Result +import ReactiveSwift +import Foundation + +/*: +## Signal + +A **signal**, represented by the [`Signal`](https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/ReactiveSwift/Signal.swift) type, is any series of [`Event`](https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/ReactiveSwift/Event.swift) values +over time that can be observed. + +Signals are generally used to represent event streams that are already “in progress”, +like notifications, user input, etc. As work is performed or data is received, +events are _sent_ on the signal, which pushes them out to any observers. +All observers see the events at the same time. + +Users must observe a signal in order to access its events. +Observing a signal does not trigger any side effects. In other words, +signals are entirely producer-driven and push-based, and consumers (observers) +cannot have any effect on their lifetime. While observing a signal, the user +can only evaluate the events in the same order as they are sent on the signal. There +is no random access to values of a signal. + +Signals can be manipulated by applying [primitives](https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/Documentation/BasicOperators.md) to them. +Typical primitives to manipulate a single signal like `filter`, `map` and +`reduce` are available, as well as primitives to manipulate multiple signals +at once (`zip`). Primitives operate only on the `value` events of a signal. + +The lifetime of a signal consists of any number of `value` events, followed by +one terminating event, which may be any one of `failed`, `completed`, or +`interrupted` (but not a combination). +Terminating events are not included in the signal’s values—they must be +handled specially. +*/ + +/*: +### `Subscription` +A Signal represents and event stream that is already "in progress", sometimes also called "hot". This means, that a subscriber may miss events that have been sent before the subscription. +Furthermore, the subscription to a signal does not trigger any side effects +*/ +scopedExample("Subscription") { + // Signal.pipe is a way to manually control a signal. the returned observer can be used to send values to the signal + let (signal, observer) = Signal.pipe() + + let subscriber1 = Signal.Observer(value: { print("Subscriber 1 received \($0)") } ) + let subscriber2 = Signal.Observer(value: { print("Subscriber 2 received \($0)") } ) + + print("Subscriber 1 subscribes to the signal") + signal.observe(subscriber1) + + print("Send value `10` on the signal") + // subscriber1 will receive the value + observer.send(value: 10) + + print("Subscriber 2 subscribes to the signal") + // Notice how nothing happens at this moment, i.e. subscriber2 does not receive the previously sent value + signal.observe(subscriber2) + + print("Send value `20` on the signal") + // Notice that now, subscriber1 and subscriber2 will receive the value + observer.send(value: 20) +} + +/*: +### `empty` +A Signal that completes immediately without emitting any value. +*/ +scopedExample("`empty`") { + let emptySignal = Signal.empty + + let observer = Signal.Observer( + value: { _ in print("value not called") }, + failed: { _ in print("error not called") }, + completed: { print("completed not called") }, + interrupted: { print("interrupted called") } + ) + + emptySignal.observe(observer) +} + +/*: +### `never` +A Signal that never sends any events to its observers. +*/ +scopedExample("`never`") { + let neverSignal = Signal.never + + let observer = Signal.Observer( + value: { _ in print("value not called") }, + failed: { _ in print("error not called") }, + completed: { print("completed not called") }, + interrupted: { print("interrupted not called") } + ) + + neverSignal.observe(observer) +} + +/*: +## `Operators` +### `uniqueValues` +Forwards only those values from `self` that are unique across the set of +all values that have been seen. + +Note: This causes the values to be retained to check for uniqueness. Providing +a function that returns a unique value for each sent value can help you reduce +the memory footprint. +*/ +scopedExample("`uniqueValues`") { + let (signal, observer) = Signal.pipe() + let subscriber = Signal.Observer(value: { print("Subscriber received \($0)") } ) + let uniqueSignal = signal.uniqueValues() + + uniqueSignal.observe(subscriber) + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) + observer.send(value: 3) + observer.send(value: 3) + observer.send(value: 5) +} + +/*: +### `map` +Maps each value in the signal to a new value. +*/ +scopedExample("`map`") { + let (signal, observer) = Signal.pipe() + let subscriber = Signal.Observer(value: { print("Subscriber received \($0)") } ) + let mappedSignal = signal.map { $0 * 2 } + + mappedSignal.observe(subscriber) + print("Send value `10` on the signal") + observer.send(value: 10) +} + +/*: +### `mapError` +Maps errors in the signal to a new error. +*/ +scopedExample("`mapError`") { + let (signal, observer) = Signal.pipe() + let subscriber = Signal.Observer(failed: { print("Subscriber received error: \($0)") } ) + let mappedErrorSignal = signal.mapError { (error:NSError) -> NSError in + let userInfo = [NSLocalizedDescriptionKey: "🔥"] + let code = error.code + 10000 + let mappedError = NSError(domain: "com.reactivecocoa.errordomain", code: code, userInfo: userInfo) + return mappedError + } + + mappedErrorSignal.observe(subscriber) + print("Send error `NSError(domain: \"com.reactivecocoa.errordomain\", code: 4815, userInfo: nil)` on the signal") + observer.send(error: NSError(domain: "com.reactivecocoa.errordomain", code: 4815, userInfo: nil)) +} + +/*: +### `filter` +Preserves only the values of the signal that pass the given predicate. +*/ +scopedExample("`filter`") { + let (signal, observer) = Signal.pipe() + let subscriber = Signal.Observer(value: { print("Subscriber received \($0)") } ) + // subscriber will only receive events with values greater than 12 + let filteredSignal = signal.filter { $0 > 12 ? true : false } + + filteredSignal.observe(subscriber) + observer.send(value: 10) + observer.send(value: 11) + observer.send(value: 12) + observer.send(value: 13) + observer.send(value: 14) +} + +/*: +### `skipNil` +Unwraps non-`nil` values and forwards them on the returned signal, `nil` +values are dropped. +*/ +scopedExample("`skipNil`") { + let (signal, observer) = Signal.pipe() + // note that the signal is of type `Int?` and observer is of type `Int`, given we're unwrapping + // non-`nil` values + let subscriber = Signal.Observer(value: { print("Subscriber received \($0)") } ) + let skipNilSignal = signal.skipNil() + + skipNilSignal.observe(subscriber) + observer.send(value: 1) + observer.send(value: nil) + observer.send(value: 3) +} + +/*: +### `take(first:)` +Returns a signal that will yield the first `count` values from `self` +*/ +scopedExample("`take(first:)`") { + let (signal, observer) = Signal.pipe() + let subscriber = Signal.Observer(value: { print("Subscriber received \($0)") } ) + let takeSignal = signal.take(first: 2) + + takeSignal.observe(subscriber) + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) +} + +/*: +### `collect` +Returns a signal that will yield an array of values when `self` completes. +- Note: When `self` completes without collecting any value, it will send +an empty array of values. +*/ +scopedExample("`collect`") { + let (signal, observer) = Signal.pipe() + // note that the signal is of type `Int` and observer is of type `[Int]` given we're "collecting" + // `Int` values for the lifetime of the signal + let subscriber = Signal<[Int], NoError>.Observer(value: { print("Subscriber received \($0)") } ) + let collectSignal = signal.collect() + + collectSignal.observe(subscriber) + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) + observer.sendCompleted() +} diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/SignalProducer.xcplaygroundpage/Contents.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/SignalProducer.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..b14cdeb --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Pages/SignalProducer.xcplaygroundpage/Contents.swift @@ -0,0 +1,767 @@ +/*: +> # IMPORTANT: To use `ReactiveSwift.playground`, please: + +1. Retrieve the project dependencies using one of the following terminal commands from the ReactiveSwift project root directory: + - `git submodule update --init` + **OR**, if you have [Carthage](https://github.com/Carthage/Carthage) installed + - `carthage checkout` +1. Open `ReactiveSwift.xcworkspace` +1. Build `Result-Mac` scheme +1. Build `ReactiveSwift-macOS` scheme +1. Finally open the `ReactiveSwift.playground` +1. Choose `View > Show Debug Area` +*/ + +import Result +import ReactiveSwift +import Foundation + +/*: +## SignalProducer + +A **signal producer**, represented by the [`SignalProducer`](https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/ReactiveSwift/SignalProducer.swift) type, creates +[signals](https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/ReactiveSwift/Signal.swift) and performs side effects. + +They can be used to represent operations or tasks, like network +requests, where each invocation of `start()` will create a new underlying +operation, and allow the caller to observe the result(s). The +`startWithSignal()` variant gives access to the produced signal, allowing it to +be observed multiple times if desired. + +Because of the behavior of `start()`, each signal created from the same +producer may see a different ordering or version of events, or the stream might +even be completely different! Unlike a plain signal, no work is started (and +thus no events are generated) until an observer is attached, and the work is +restarted anew for each additional observer. + +Starting a signal producer returns a [disposable](#disposables) that can be used to +interrupt/cancel the work associated with the produced signal. + +Just like signals, signal producers can also be manipulated via primitives +like `map`, `filter`, etc. +Every signal primitive can be “lifted” to operate upon signal producers instead, +using the `lift` method. +Furthermore, there are additional primitives that control _when_ and _how_ work +is started—for example, `times`. +*/ + +/*: +### `Subscription` +A SignalProducer represents an operation that can be started on demand. Starting the operation returns a Signal on which the result(s) of the operation can be observed. This behavior is sometimes also called "cold". +This means that a subscriber will never miss any values sent by the SignalProducer. +*/ +scopedExample("Subscription") { + let producer = SignalProducer { observer, _ in + print("New subscription, starting operation") + observer.send(value: 1) + observer.send(value: 2) + } + + let subscriber1 = Signal.Observer(value: { print("Subscriber 1 received \($0)") }) + let subscriber2 = Signal.Observer(value: { print("Subscriber 2 received \($0)") }) + + print("Subscriber 1 subscribes to producer") + producer.start(subscriber1) + + print("Subscriber 2 subscribes to producer") + // Notice, how the producer will start the work again + producer.start(subscriber2) +} + +/*: +### `empty` +A producer for a Signal that will immediately complete without sending +any values. +*/ +scopedExample("`empty`") { + let emptyProducer = SignalProducer.empty + + let observer = Signal.Observer( + value: { _ in print("value not called") }, + failed: { _ in print("error not called") }, + completed: { print("completed called") } + ) + + emptyProducer.start(observer) +} + +/*: +### `never` +A producer for a Signal that never sends any events to its observers. +*/ +scopedExample("`never`") { + let neverProducer = SignalProducer.never + + let observer = Signal.Observer( + value: { _ in print("value not called") }, + failed: { _ in print("error not called") }, + completed: { print("completed not called") } + ) + + neverProducer.start(observer) +} + +/*: +### `startWithSignal` +Creates a Signal from the producer, passes it into the given closure, +then starts sending events on the Signal when the closure has returned. + +The closure will also receive a disposable which can be used to +interrupt the work associated with the signal and immediately send an +`Interrupted` event. +*/ +scopedExample("`startWithSignal`") { + var started = false + var value: Int? + + SignalProducer(value: 42) + .on(value: { + value = $0 + }) + .startWithSignal { signal, disposable in + print(value) + } + + print(value) +} + +/*: +### `startWithResult` +Creates a Signal from the producer, then adds exactly one observer to +the Signal, which will invoke the given callback when `value` or `failed` +events are received. + +Returns a Disposable which can be used to interrupt the work associated +with the Signal, and prevent any future callbacks from being invoked. +*/ +scopedExample("`startWithResult`") { + SignalProducer(value: 42) + .startWithResult { result in + print(result.value) + } +} + +/*: +### `startWithValues` +Creates a Signal from the producer, then adds exactly one observer to +the Signal, which will invoke the given callback when `value` events are +received. + +This method is available only if the producer never emits error, or in +other words, has an error type of `NoError`. + +Returns a Disposable which can be used to interrupt the work associated +with the Signal, and prevent any future callbacks from being invoked. +*/ +scopedExample("`startWithValues`") { + SignalProducer(value: 42) + .startWithValues { value in + print(value) + } +} + +/*: +### `startWithCompleted` +Creates a Signal from the producer, then adds exactly one observer to +the Signal, which will invoke the given callback when a `completed` event is +received. + +Returns a Disposable which can be used to interrupt the work associated +with the Signal. +*/ +scopedExample("`startWithCompleted`") { + SignalProducer(value: 42) + .startWithCompleted { + print("completed called") + } +} + +/*: +### `startWithFailed` +Creates a Signal from the producer, then adds exactly one observer to +the Signal, which will invoke the given callback when a `failed` event is +received. + +Returns a Disposable which can be used to interrupt the work associated +with the Signal. +*/ +scopedExample("`startWithFailed`") { + SignalProducer(error: NSError(domain: "example", code: 42, userInfo: nil)) + .startWithFailed { error in + print(error) + } +} + +/*: +### `startWithInterrupted` +Creates a Signal from the producer, then adds exactly one observer to +the Signal, which will invoke the given callback when an `interrupted` event +is received. + +Returns a Disposable which can be used to interrupt the work associated +with the Signal. +*/ +scopedExample("`startWithInterrupted`") { + let disposable = SignalProducer.never + .startWithInterrupted { + print("interrupted called") + } + + disposable.dispose() +} + + +/*: +### `lift` +Lifts an unary Signal operator to operate upon SignalProducers instead. + +In other words, this will create a new SignalProducer which will apply +the given Signal operator to _every_ created Signal, just as if the +operator had been applied to each Signal yielded from start(). +*/ +scopedExample("`lift`") { + var counter = 0 + let transform: (Signal) -> Signal = { signal in + counter = 42 + return signal + } + + SignalProducer(value: 0) + .lift(transform) + .startWithValues { _ in + print(counter) + } +} + +/*: +### `map` +Maps each value in the producer to a new value. +*/ +scopedExample("`map`") { + SignalProducer(value: 1) + .map { $0 + 41 } + .startWithValues { value in + print(value) + } +} + +/*: +### `mapError` +Maps errors in the producer to a new error. +*/ +scopedExample("`mapError`") { + SignalProducer(error: NSError(domain: "mapError", code: 42, userInfo: nil)) + .mapError { PlaygroundError.example($0.description) } + .startWithFailed { error in + print(error) + } +} + +/*: +### `filter` +Preserves only the values of the producer that pass the given predicate. +*/ +scopedExample("`filter`") { + SignalProducer([ 1, 2, 3, 4 ]) + .filter { $0 > 3 } + .startWithValues { value in + print(value) + } +} + +/*: +### `take(first:)` +Returns a producer that will yield the first `count` values from the +input producer. +*/ +scopedExample("`take(first:)`") { + SignalProducer([ 1, 2, 3, 4 ]) + .take(first: 2) + .startWithValues { value in + print(value) + } +} + +/*: +### `observe(on:)` +Forwards all events onto the given scheduler, instead of whichever +scheduler they originally arrived upon. +*/ +scopedExample("`observe(on:)`") { + let baseProducer = SignalProducer([ 1, 2, 3, 4 ]) + let completion = { print("is main thread? \(Thread.current.isMainThread)") } + + baseProducer + .observe(on: QueueScheduler(qos: .default, name: "test")) + .startWithCompleted(completion) + + baseProducer + .startWithCompleted(completion) +} + +/*: +### `collect` +Returns a producer that will yield an array of values until it completes. +*/ +scopedExample("`collect`") { + SignalProducer { observer, disposable in + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) + observer.sendCompleted() + } + .collect() + .startWithValues { value in + print(value) + } +} + +/*: +### `collect(count:)` +Returns a producer that will yield an array of values until it reaches a certain count. +*/ +scopedExample("`collect(count:)`") { + SignalProducer { observer, disposable in + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) + observer.sendCompleted() + } + .collect(count: 2) + .startWithValues { value in + print(value) + } +} + +/*: +### `collect(_:)` matching values inclusively +Returns a producer that will yield an array of values based on a predicate +which matches the values collected. + +When producer completes any remaining values will be sent, the last values +array may not match `predicate`. Alternatively, if were not collected any +values will sent an empty array of values. +*/ +scopedExample("`collect(_:)` matching values inclusively") { + SignalProducer { observer, disposable in + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) + observer.sendCompleted() + } + .collect { values in values.reduce(0, +) == 3 } + .startWithValues { value in + print(value) + } +} + +/*: +### `collect(_:)` matching values exclusively +Returns a producer that will yield an array of values based on a predicate +which matches the values collected and the next value. + +When producer completes any remaining values will be sent, the last values +array may not match `predicate`. Alternatively, if were not collected any +values will sent an empty array of values. +*/ +scopedExample("`collect(_:)` matching values exclusively") { + SignalProducer { observer, disposable in + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) + observer.sendCompleted() + } + .collect { values, next in next == 3 } + .startWithValues { value in + print(value) + } +} + +/*: +### `combineLatest(with:)` +Combines the latest value of the receiver with the latest value from +the given producer. + +The returned producer will not send a value until both inputs have sent at +least one value each. If either producer is interrupted, the returned producer +will also be interrupted. +*/ +scopedExample("`combineLatest(with:)`") { + let producer1 = SignalProducer([ 1, 2, 3, 4 ]) + let producer2 = SignalProducer([ 1, 2 ]) + + producer1 + .combineLatest(with: producer2) + .startWithValues { value in + print("\(value)") + } +} + +/*: +### `skip(first:)` +Returns a producer that will skip the first `count` values, then forward +everything afterward. +*/ +scopedExample("`skip(first:)`") { + SignalProducer([ 1, 2, 3, 4 ]) + .skip(first: 2) + .startWithValues { value in + print(value) + } +} + +/*: +### `materialize` + +Treats all Events from the input producer as plain values, allowing them to be +manipulated just like any other value. + +In other words, this brings Events “into the monad.” + +When a Completed or Failed event is received, the resulting producer will send +the Event itself and then complete. When an Interrupted event is received, +the resulting producer will send the Event itself and then interrupt. +*/ +scopedExample("`materialize`") { + SignalProducer([ 1, 2, 3, 4 ]) + .materialize() + .startWithValues { value in + print(value) + } +} + +/*: +### `sample(on:)` +Forwards the latest value from `self` whenever `sampler` sends a `value` +event. + +If `sampler` fires before a value has been observed on `self`, nothing +happens. + +Returns a producer that will send values from `self`, sampled (possibly +multiple times) by `sampler`, then complete once both input producers have +completed, or interrupt if either input producer is interrupted. +*/ +scopedExample("`sample(on:)`") { + let baseProducer = SignalProducer([ 1, 2, 3, 4 ]) + let sampledOnProducer = SignalProducer([ 1, 2 ]) + .map { _ in () } + + baseProducer + .sample(on: sampledOnProducer) + .startWithValues { value in + print(value) + } +} + +/*: +### `combinePrevious` +Forwards events from `self` with history: values of the returned producer +are a tuple whose first member is the previous value and whose second member +is the current value. `initial` is supplied as the first member when `self` +sends its first value. +*/ +scopedExample("`combinePrevious`") { + SignalProducer([ 1, 2, 3, 4 ]) + .combinePrevious(42) + .startWithValues { value in + print("\(value)") + } +} + +/*: +### `scan` +Aggregates `self`'s values into a single combined value. When `self` emits +its first value, `combine` is invoked with `initial` as the first argument and +that emitted value as the second argument. The result is emitted from the +producer returned from `scan`. That result is then passed to `combine` as the +first argument when the next value is emitted, and so on. +*/ +scopedExample("`scan`") { + SignalProducer([ 1, 2, 3, 4 ]) + .scan(0, +) + .startWithValues { value in + print(value) + } +} + +/*: +### `reduce` +Like `scan`, but sends only the final value and then immediately completes. +*/ +scopedExample("`reduce`") { + SignalProducer([ 1, 2, 3, 4 ]) + .reduce(0, +) + .startWithValues { value in + print(value) + } +} + +/*: +### `skipRepeats` +Forwards only those values from `self` which do not pass `isRepeat` with +respect to the previous value. The first value is always forwarded. +*/ +scopedExample("`skipRepeats`") { + SignalProducer([ 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 2, 2, 2, 4 ]) + .skipRepeats(==) + .startWithValues { value in + print(value) + } +} + +/*: +### `skip(while:)` +Does not forward any values from `self` until `predicate` returns false, +at which point the returned signal behaves exactly like `self`. +*/ +scopedExample("`skip(while:)`") { + // Note that trailing closure is used for `skip(while:)`. + SignalProducer([ 3, 3, 3, 3, 1, 2, 3, 4 ]) + .skip { $0 > 2 } + .startWithValues { value in + print(value) + } +} + +/*: +### `take(untilReplacement:)` +Forwards events from `self` until `replacement` begins sending events. + +Returns a producer which passes through `value`, `failed`, and `interrupted` +events from `self` until `replacement` sends an event, at which point the +returned producer will send that event and switch to passing through events +from `replacement` instead, regardless of whether `self` has sent events +already. +*/ +scopedExample("`take(untilReplacement:)`") { + let (replacementSignal, incomingReplacementObserver) = Signal.pipe() + + let baseProducer = SignalProducer { incomingObserver, _ in + incomingObserver.send(value: 1) + incomingObserver.send(value: 2) + incomingObserver.send(value: 3) + + incomingReplacementObserver.send(value: 42) + + incomingObserver.send(value: 4) + + incomingReplacementObserver.send(value: 42) + } + + baseProducer + .take(untilReplacement: replacementSignal) + .startWithValues { value in + print(value) + } +} + +/*: +### `take(last:)` +Waits until `self` completes and then forwards the final `count` values +on the returned producer. +*/ +scopedExample("`take(last:)`") { + SignalProducer([ 1, 2, 3, 4 ]) + .take(last: 2) + .startWithValues { value in + print(value) + } +} + +/*: +### `skipNil` +Unwraps non-`nil` values and forwards them on the returned signal, `nil` +values are dropped. +*/ +scopedExample("`skipNil`") { + SignalProducer([ nil, 1, 2, nil, 3, 4, nil ]) + .skipNil() + .startWithValues { value in + print(value) + } +} + + +/*: +### `zip(with:)` +Zips elements of two producers into pairs. The elements of any Nth pair +are the Nth elements of the two input producers. +*/ +scopedExample("`zip(with:)`") { + let baseProducer = SignalProducer([ 1, 2, 3, 4 ]) + let zippedProducer = SignalProducer([ 42, 43 ]) + + baseProducer + .zip(with: zippedProducer) + .startWithValues { value in + print("\(value)") + } +} + +/*: +### `repeat` +Repeats `self` a total of `count` times. Repeating `1` times results in +an equivalent signal producer. +*/ +scopedExample("`repeat`") { + var counter = 0 + + SignalProducer<(), NoError> { observer, disposable in + counter += 1 + observer.sendCompleted() + } + .repeat(42) + .start() + + print(counter) +} + +/*: +### `retry(upTo:)` +Ignores failures up to `count` times. +*/ +scopedExample("`retry(upTo:)`") { + var tries = 0 + + SignalProducer { observer, disposable in + if tries == 0 { + tries += 1 + observer.send(error: NSError(domain: "retry", code: 0, userInfo: nil)) + } else { + observer.send(value: 42) + observer.sendCompleted() + } + } + .retry(upTo: 1) + .startWithResult { result in + print(result) + } +} + +/*: +### `then` +Waits for completion of `producer`, *then* forwards all events from +`replacement`. Any failure sent from `producer` is forwarded immediately, in +which case `replacement` will not be started, and none of its events will be +be forwarded. All values sent from `producer` are ignored. +*/ +scopedExample("`then`") { + let baseProducer = SignalProducer([ 1, 2, 3, 4 ]) + let thenProducer = SignalProducer(value: 42) + + baseProducer + .then(thenProducer) + .startWithValues { value in + print(value) + } +} + +/*: +### `replayLazily(upTo:)` +Creates a new `SignalProducer` that will multicast values emitted by +the underlying producer, up to `capacity`. +This means that all clients of this `SignalProducer` will see the same version +of the emitted values/errors. + +The underlying `SignalProducer` will not be started until `self` is started +for the first time. When subscribing to this producer, all previous values +(up to `capacity`) will be emitted, followed by any new values. + +If you find yourself needing *the current value* (the last buffered value) +you should consider using `PropertyType` instead, which, unlike this operator, +will guarantee at compile time that there's always a buffered value. +This operator is not recommended in most cases, as it will introduce an implicit +relationship between the original client and the rest, so consider alternatives +like `PropertyType`, `SignalProducer.buffer`, or representing your stream using +a `Signal` instead. + +This operator is only recommended when you absolutely need to introduce +a layer of caching in front of another `SignalProducer`. + +This operator has the same semantics as `SignalProducer.buffer`. +*/ +scopedExample("`replayLazily(upTo:)`") { + let baseProducer = SignalProducer([ 1, 2, 3, 4, 42 ]) + .replayLazily(upTo: 2) + + baseProducer.startWithValues { value in + print(value) + } + + baseProducer.startWithValues { value in + print(value) + } + + baseProducer.startWithValues { value in + print(value) + } +} + +/*: +### `flatMap(.latest)` +Maps each event from `self` to a new producer, then flattens the +resulting producers (into a producer of values), according to the +semantics of the given strategy. + +If `self` or any of the created producers fail, the returned producer +will forward that failure immediately. +*/ +scopedExample("`flatMap(.latest)`") { + SignalProducer([ 1, 2, 3, 4 ]) + .flatMap(.latest) { SignalProducer(value: $0 + 3) } + .startWithValues { value in + print(value) + } +} + +/*: +### `flatMapError` +Catches any failure that may occur on the input producer, mapping to a new producer +that starts in its place. +*/ +scopedExample("`flatMapError`") { + SignalProducer(error: NSError(domain: "flatMapError", code: 42, userInfo: nil)) + .flatMapError { SignalProducer(value: $0.code) } + .startWithValues { value in + print(value) + } +} + +/*: +### `sample(with:)` +Forwards the latest value from `self` with the value from `sampler` as a tuple, +only when `sampler` sends a `value` event. + +If `sampler` fires before a value has been observed on `self`, nothing happens. +Returns a producer that will send values from `self` and `sampler`, +sampled (possibly multiple times) by `sampler`, then complete once both +input producers have completed, or interrupt if either input producer is interrupted. +*/ +scopedExample("`sample(with:)`") { + let producer = SignalProducer([ 1, 2, 3, 4 ]) + let sampler = SignalProducer([ "a", "b" ]) + + let result = producer.sample(with: sampler) + + result.startWithValues { left, right in + print("\(left) \(right)") + } +} + +/*: +### `logEvents` +Logs all events that the receiver sends. +By default, it will print to the standard output. +*/ +scopedExample("`log events`") { + let baseProducer = SignalProducer([ 1, 2, 3, 4, 42 ]) + + baseProducer + .logEvents(identifier: "Playground is fun!") + .start() +} diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Sources/PlaygroundUtility.swift b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Sources/PlaygroundUtility.swift new file mode 100644 index 0000000..282b07f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/Sources/PlaygroundUtility.swift @@ -0,0 +1,10 @@ +import Foundation + +public func scopedExample(_ exampleDescription: String, _ action: () -> Void) { + print("\n--- \(exampleDescription) ---\n") + action() +} + +public enum PlaygroundError: Error { + case example(String) +} diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/contents.xcplayground b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/contents.xcplayground new file mode 100644 index 0000000..a5cb2af --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.playground/contents.xcplayground @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.podspec b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.podspec new file mode 100644 index 0000000..8e6169d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.podspec @@ -0,0 +1,23 @@ +Pod::Spec.new do |s| + s.name = "ReactiveSwift" + # Version goes here and will be used to access the git tag later on, once we have a first release. + s.version = "2.0.0-alpha.2" + s.summary = "Streams of values over time" + s.description = <<-DESC + ReactiveSwift is a Swift framework inspired by Functional Reactive Programming. It provides APIs for composing and transforming streams of values over time. + DESC + s.homepage = "https://github.com/ReactiveCocoa/ReactiveSwift" + s.license = { :type => "MIT", :file => "LICENSE.md" } + s.author = "ReactiveCocoa" + + 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.source = { :git => "https://github.com/ReactiveCocoa/ReactiveSwift.git", :tag => "#{s.version}" } + # Directory glob for all Swift files + s.source_files = "Sources/*.{swift}" + s.dependency 'Result', '~> 3.2' + + s.pod_target_xcconfig = {"OTHER_SWIFT_FLAGS[config=Release]" => "-suppress-warnings" } +end diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.xcodeproj/project.pbxproj b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ea40858 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.xcodeproj/project.pbxproj @@ -0,0 +1,1620 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 02D2602A1C1D6DAF003ACC61 /* SignalLifetimeSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D260291C1D6DAF003ACC61 /* SignalLifetimeSpec.swift */; }; + 02D2602B1C1D6DB8003ACC61 /* SignalLifetimeSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D260291C1D6DAF003ACC61 /* SignalLifetimeSpec.swift */; }; + 4A0AB6721DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0AB6711DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift */; }; + 4A0AB6731DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0AB6711DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift */; }; + 4A0AB6741DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0AB6711DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift */; }; + 4A0E10FF1D2A92720065D310 /* Lifetime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0E10FE1D2A92720065D310 /* Lifetime.swift */; }; + 4A0E11001D2A92720065D310 /* Lifetime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0E10FE1D2A92720065D310 /* Lifetime.swift */; }; + 4A0E11011D2A92720065D310 /* Lifetime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0E10FE1D2A92720065D310 /* Lifetime.swift */; }; + 4A0E11021D2A92720065D310 /* Lifetime.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0E10FE1D2A92720065D310 /* Lifetime.swift */; }; + 4A0E11041D2A95200065D310 /* LifetimeSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0E11031D2A95200065D310 /* LifetimeSpec.swift */; }; + 4A0E11051D2A95200065D310 /* LifetimeSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0E11031D2A95200065D310 /* LifetimeSpec.swift */; }; + 4A0E11061D2A95200065D310 /* LifetimeSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0E11031D2A95200065D310 /* LifetimeSpec.swift */; }; + 4AC73ECB1DF273570004EC4F /* ResultExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC73ECA1DF273570004EC4F /* ResultExtensions.swift */; }; + 4AC73ECC1DF273570004EC4F /* ResultExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC73ECA1DF273570004EC4F /* ResultExtensions.swift */; }; + 4AC73ECD1DF273570004EC4F /* ResultExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC73ECA1DF273570004EC4F /* ResultExtensions.swift */; }; + 4AC73ECE1DF273570004EC4F /* ResultExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC73ECA1DF273570004EC4F /* ResultExtensions.swift */; }; + 579504331BB8A34200A5E482 /* BagSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312EF19EF2A7700984962 /* BagSpec.swift */; }; + 579504341BB8A34300A5E482 /* BagSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312EF19EF2A7700984962 /* BagSpec.swift */; }; + 57A4D1B11BA13D7A00F7D4B1 /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = D871D69E1B3B29A40070F16C /* Optional.swift */; }; + 57A4D1B41BA13D7A00F7D4B1 /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BE19EF2A5800984962 /* Disposable.swift */; }; + 57A4D1B61BA13D7A00F7D4B1 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B51A69A3DB00AD8286 /* Event.swift */; }; + 57A4D1B81BA13D7A00F7D4B1 /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312C819EF2A5800984962 /* Scheduler.swift */; }; + 57A4D1B91BA13D7A00F7D4B1 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54AF1A69A2AC00AD8286 /* Action.swift */; }; + 57A4D1BA1BA13D7A00F7D4B1 /* Property.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B01A69A2AC00AD8286 /* Property.swift */; }; + 57A4D1BB1BA13D7A00F7D4B1 /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B11A69A2AC00AD8286 /* Signal.swift */; }; + 57A4D1BC1BA13D7A00F7D4B1 /* SignalProducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B21A69A2AC00AD8286 /* SignalProducer.swift */; }; + 57A4D1BD1BA13D7A00F7D4B1 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BB19EF2A5800984962 /* Atomic.swift */; }; + 57A4D1BE1BA13D7A00F7D4B1 /* Bag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BC19EF2A5800984962 /* Bag.swift */; }; + 57A4D1C01BA13D7A00F7D4B1 /* FoundationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B4A3C19F4C39A009E02AC /* FoundationExtensions.swift */; }; + 57A4D2081BA13D7A00F7D4B1 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC42E2E1AE7AB8B00965373 /* Result.framework */; }; + 57A4D20A1BA13D7A00F7D4B1 /* ReactiveSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = D04725EF19E49ED7006002AA /* ReactiveSwift.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7DFBED081CDB8C9500EE435B /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57A4D2411BA13D7A00F7D4B1 /* ReactiveSwift.framework */; }; + 7DFBED1E1CDB8D7000EE435B /* ReactiveSwift.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 57A4D2411BA13D7A00F7D4B1 /* ReactiveSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 7DFBED1F1CDB8D7800EE435B /* Quick.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D037672B19EDA75D00A782A9 /* Quick.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 7DFBED201CDB8D7D00EE435B /* Nimble.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D05E662419EDD82000904ACA /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 7DFBED211CDB8D8300EE435B /* Result.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = CDC42E2E1AE7AB8B00965373 /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 7DFBED221CDB8DE300EE435B /* ActionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021671C1A6CD50500987861 /* ActionSpec.swift */; }; + 7DFBED231CDB8DE300EE435B /* AtomicSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312EE19EF2A7700984962 /* AtomicSpec.swift */; }; + 7DFBED241CDB8DE300EE435B /* BagSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312EF19EF2A7700984962 /* BagSpec.swift */; }; + 7DFBED251CDB8DE300EE435B /* DisposableSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312F019EF2A7700984962 /* DisposableSpec.swift */; }; + 7DFBED261CDB8DE300EE435B /* FoundationExtensionsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8170FC01B100EBC004192AD /* FoundationExtensionsSpec.swift */; }; + 7DFBED281CDB8DE300EE435B /* PropertySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A2260D1A72F16D00D33B74 /* PropertySpec.swift */; }; + 7DFBED291CDB8DE300EE435B /* SchedulerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312F219EF2A7700984962 /* SchedulerSpec.swift */; }; + 7DFBED2A1CDB8DE300EE435B /* SignalLifetimeSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D260291C1D6DAF003ACC61 /* SignalLifetimeSpec.swift */; }; + 7DFBED2B1CDB8DE300EE435B /* SignalProducerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A2260A1A72E6C500D33B74 /* SignalProducerSpec.swift */; }; + 7DFBED2C1CDB8DE300EE435B /* SignalProducerLiftingSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8024DB11B2E1BB0005E6B9A /* SignalProducerLiftingSpec.swift */; }; + 7DFBED2D1CDB8DE300EE435B /* SignalSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A226071A72E0E900D33B74 /* SignalSpec.swift */; }; + 7DFBED2E1CDB8DE300EE435B /* FlattenSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA6F284F1C52626B001879D2 /* FlattenSpec.swift */; }; + 7DFBED2F1CDB8DE300EE435B /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B696FB801A7640C00075236D /* TestError.swift */; }; + 7DFBED301CDB8DE300EE435B /* TestLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79B64731CD38B2B003F2376 /* TestLogger.swift */; }; + 7DFBED6D1CDB8F7D00EE435B /* SignalProducerNimbleMatchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA6B94A1A76044800C846D1 /* SignalProducerNimbleMatchers.swift */; }; + 9A090C141DA0309E00EE97CA /* Reactive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A090C131DA0309E00EE97CA /* Reactive.swift */; }; + 9A090C151DA0309E00EE97CA /* Reactive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A090C131DA0309E00EE97CA /* Reactive.swift */; }; + 9A090C161DA0309E00EE97CA /* Reactive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A090C131DA0309E00EE97CA /* Reactive.swift */; }; + 9A090C171DA0309E00EE97CA /* Reactive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A090C131DA0309E00EE97CA /* Reactive.swift */; }; + 9A1A4F9D1E16AE50006F3039 /* ValidatingPropertySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1A4F981E16961C006F3039 /* ValidatingPropertySpec.swift */; }; + 9A1A4F9E1E16AE50006F3039 /* ValidatingPropertySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1A4F981E16961C006F3039 /* ValidatingPropertySpec.swift */; }; + 9A1A4F9F1E16AE55006F3039 /* ValidatingPropertySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1A4F981E16961C006F3039 /* ValidatingPropertySpec.swift */; }; + 9A1D067D1D948A2300ACF44C /* UnidirectionalBindingSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1D067C1D948A2200ACF44C /* UnidirectionalBindingSpec.swift */; }; + 9A1D067E1D948A2300ACF44C /* UnidirectionalBindingSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1D067C1D948A2200ACF44C /* UnidirectionalBindingSpec.swift */; }; + 9A1D067F1D948A2300ACF44C /* UnidirectionalBindingSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1D067C1D948A2200ACF44C /* UnidirectionalBindingSpec.swift */; }; + 9A5D93731EE5733300438925 /* InhabitableTypeGuards.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5D93721EE5733300438925 /* InhabitableTypeGuards.swift */; }; + 9A5D93741EE5733300438925 /* InhabitableTypeGuards.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5D93721EE5733300438925 /* InhabitableTypeGuards.swift */; }; + 9A5D93751EE5733300438925 /* InhabitableTypeGuards.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5D93721EE5733300438925 /* InhabitableTypeGuards.swift */; }; + 9A5D93761EE5733300438925 /* InhabitableTypeGuards.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A5D93721EE5733300438925 /* InhabitableTypeGuards.swift */; }; + 9A681A9E1E5A241B00B097CF /* DeprecationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A681A9D1E5A241B00B097CF /* DeprecationSpec.swift */; }; + 9A681A9F1E5A241B00B097CF /* DeprecationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A681A9D1E5A241B00B097CF /* DeprecationSpec.swift */; }; + 9A681AA01E5A241B00B097CF /* DeprecationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A681A9D1E5A241B00B097CF /* DeprecationSpec.swift */; }; + 9A9100DF1E0E6E620093E346 /* ValidatingProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9100DE1E0E6E620093E346 /* ValidatingProperty.swift */; }; + 9A9100E01E0E6E670093E346 /* ValidatingProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9100DE1E0E6E620093E346 /* ValidatingProperty.swift */; }; + 9A9100E11E0E6E680093E346 /* ValidatingProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9100DE1E0E6E620093E346 /* ValidatingProperty.swift */; }; + 9A9100E21E0E6E680093E346 /* ValidatingProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9100DE1E0E6E620093E346 /* ValidatingProperty.swift */; }; + 9ABCB1851D2A5B5A00BCA243 /* Deprecations+Removals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ABCB1841D2A5B5A00BCA243 /* Deprecations+Removals.swift */; }; + 9ABCB1861D2A5B5A00BCA243 /* Deprecations+Removals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ABCB1841D2A5B5A00BCA243 /* Deprecations+Removals.swift */; }; + 9ABCB1871D2A5B5A00BCA243 /* Deprecations+Removals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ABCB1841D2A5B5A00BCA243 /* Deprecations+Removals.swift */; }; + 9ABCB1881D2A5B5A00BCA243 /* Deprecations+Removals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ABCB1841D2A5B5A00BCA243 /* Deprecations+Removals.swift */; }; + A9B315BC1B3940810001CB9C /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BE19EF2A5800984962 /* Disposable.swift */; }; + A9B315BE1B3940810001CB9C /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B51A69A3DB00AD8286 /* Event.swift */; }; + A9B315C01B3940810001CB9C /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312C819EF2A5800984962 /* Scheduler.swift */; }; + A9B315C11B3940810001CB9C /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54AF1A69A2AC00AD8286 /* Action.swift */; }; + A9B315C21B3940810001CB9C /* Property.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B01A69A2AC00AD8286 /* Property.swift */; }; + A9B315C31B3940810001CB9C /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B11A69A2AC00AD8286 /* Signal.swift */; }; + A9B315C41B3940810001CB9C /* SignalProducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B21A69A2AC00AD8286 /* SignalProducer.swift */; }; + A9B315C51B3940810001CB9C /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BB19EF2A5800984962 /* Atomic.swift */; }; + A9B315C61B3940810001CB9C /* Bag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BC19EF2A5800984962 /* Bag.swift */; }; + A9B315C81B3940810001CB9C /* FoundationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B4A3C19F4C39A009E02AC /* FoundationExtensions.swift */; }; + A9B315C91B3940980001CB9C /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC42E2E1AE7AB8B00965373 /* Result.framework */; }; + A9B315CA1B3940AB0001CB9C /* ReactiveSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = D04725EF19E49ED7006002AA /* ReactiveSwift.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A9F793341B60D0140026BCBA /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = D871D69E1B3B29A40070F16C /* Optional.swift */; }; + B696FB811A7640C00075236D /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B696FB801A7640C00075236D /* TestError.swift */; }; + B696FB821A7640C00075236D /* TestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B696FB801A7640C00075236D /* TestError.swift */; }; + BE9CF3951D751B6B003AE479 /* UnidirectionalBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9CF3941D751B6B003AE479 /* UnidirectionalBinding.swift */; }; + BE9CF3961D751B70003AE479 /* UnidirectionalBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9CF3941D751B6B003AE479 /* UnidirectionalBinding.swift */; }; + BE9CF3971D751B71003AE479 /* UnidirectionalBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9CF3941D751B6B003AE479 /* UnidirectionalBinding.swift */; }; + BE9CF3981D751B71003AE479 /* UnidirectionalBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE9CF3941D751B6B003AE479 /* UnidirectionalBinding.swift */; }; + BFA6B94D1A7604D400C846D1 /* SignalProducerNimbleMatchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA6B94A1A76044800C846D1 /* SignalProducerNimbleMatchers.swift */; }; + BFA6B94E1A7604D500C846D1 /* SignalProducerNimbleMatchers.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA6B94A1A76044800C846D1 /* SignalProducerNimbleMatchers.swift */; }; + C79B64741CD38B2B003F2376 /* TestLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79B64731CD38B2B003F2376 /* TestLogger.swift */; }; + C79B64751CD38B2B003F2376 /* TestLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79B64731CD38B2B003F2376 /* TestLogger.swift */; }; + C79B647C1CD52E23003F2376 /* EventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79B647B1CD52E23003F2376 /* EventLogger.swift */; }; + C79B647D1CD52E4A003F2376 /* EventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79B647B1CD52E23003F2376 /* EventLogger.swift */; }; + C79B647F1CD52E4D003F2376 /* EventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79B647B1CD52E23003F2376 /* EventLogger.swift */; }; + C79B64801CD52E4E003F2376 /* EventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79B647B1CD52E23003F2376 /* EventLogger.swift */; }; + CA6F28501C52626B001879D2 /* FlattenSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA6F284F1C52626B001879D2 /* FlattenSpec.swift */; }; + CA6F28511C52626B001879D2 /* FlattenSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA6F284F1C52626B001879D2 /* FlattenSpec.swift */; }; + CDC42E2F1AE7AB8B00965373 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC42E2E1AE7AB8B00965373 /* Result.framework */; }; + CDC42E301AE7AB8B00965373 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC42E2E1AE7AB8B00965373 /* Result.framework */; }; + CDC42E311AE7AB8B00965373 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC42E2E1AE7AB8B00965373 /* Result.framework */; }; + CDC42E331AE7AC6D00965373 /* Result.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = CDC42E2E1AE7AB8B00965373 /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + CDCD247A1C277EEC00710AEE /* AtomicSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312EE19EF2A7700984962 /* AtomicSpec.swift */; }; + CDCD247B1C277EED00710AEE /* AtomicSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312EE19EF2A7700984962 /* AtomicSpec.swift */; }; + CDF066CA1CDC1CA200199626 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D05E662419EDD82000904ACA /* Nimble.framework */; }; + CDF066CB1CDC1CA200199626 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D037672B19EDA75D00A782A9 /* Quick.framework */; }; + D01B7B6219EDD8FE00D26E01 /* Nimble.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D05E662419EDD82000904ACA /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D01B7B6319EDD8FE00D26E01 /* Quick.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D037672B19EDA75D00A782A9 /* Quick.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D01B7B6419EDD94B00D26E01 /* ReactiveSwift.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D047260C19E49F82006002AA /* ReactiveSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D021671D1A6CD50500987861 /* ActionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021671C1A6CD50500987861 /* ActionSpec.swift */; }; + D021671E1A6CD50500987861 /* ActionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D021671C1A6CD50500987861 /* ActionSpec.swift */; }; + D037666419EDA43C00A782A9 /* ReactiveSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = D04725EF19E49ED7006002AA /* ReactiveSwift.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D037672D19EDA75D00A782A9 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D037672B19EDA75D00A782A9 /* Quick.framework */; }; + D037672F19EDA78B00A782A9 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D037672B19EDA75D00A782A9 /* Quick.framework */; }; + D03B4A3D19F4C39A009E02AC /* FoundationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B4A3C19F4C39A009E02AC /* FoundationExtensions.swift */; }; + D03B4A3E19F4C39A009E02AC /* FoundationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B4A3C19F4C39A009E02AC /* FoundationExtensions.swift */; }; + D04725F019E49ED7006002AA /* ReactiveSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = D04725EF19E49ED7006002AA /* ReactiveSwift.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D04725F619E49ED7006002AA /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04725EA19E49ED7006002AA /* ReactiveSwift.framework */; }; + D047261719E49F82006002AA /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D047260C19E49F82006002AA /* ReactiveSwift.framework */; }; + D05E662519EDD82000904ACA /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D05E662419EDD82000904ACA /* Nimble.framework */; }; + D05E662619EDD83000904ACA /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D05E662419EDD82000904ACA /* Nimble.framework */; }; + D08C54B31A69A2AE00AD8286 /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B11A69A2AC00AD8286 /* Signal.swift */; }; + D08C54B41A69A2AF00AD8286 /* Signal.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B11A69A2AC00AD8286 /* Signal.swift */; }; + D08C54B61A69A3DB00AD8286 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B51A69A3DB00AD8286 /* Event.swift */; }; + D08C54B71A69A3DB00AD8286 /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B51A69A3DB00AD8286 /* Event.swift */; }; + D08C54B81A69A9D000AD8286 /* SignalProducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B21A69A2AC00AD8286 /* SignalProducer.swift */; }; + D08C54B91A69A9D100AD8286 /* SignalProducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B21A69A2AC00AD8286 /* SignalProducer.swift */; }; + D08C54BA1A69C54300AD8286 /* Property.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B01A69A2AC00AD8286 /* Property.swift */; }; + D08C54BB1A69C54400AD8286 /* Property.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54B01A69A2AC00AD8286 /* Property.swift */; }; + D0A226081A72E0E900D33B74 /* SignalSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A226071A72E0E900D33B74 /* SignalSpec.swift */; }; + D0A226091A72E0E900D33B74 /* SignalSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A226071A72E0E900D33B74 /* SignalSpec.swift */; }; + D0A2260B1A72E6C500D33B74 /* SignalProducerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A2260A1A72E6C500D33B74 /* SignalProducerSpec.swift */; }; + D0A2260C1A72E6C500D33B74 /* SignalProducerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A2260A1A72E6C500D33B74 /* SignalProducerSpec.swift */; }; + D0A2260E1A72F16D00D33B74 /* PropertySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A2260D1A72F16D00D33B74 /* PropertySpec.swift */; }; + D0A2260F1A72F16D00D33B74 /* PropertySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A2260D1A72F16D00D33B74 /* PropertySpec.swift */; }; + D0C312CD19EF2A5800984962 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BB19EF2A5800984962 /* Atomic.swift */; }; + D0C312CE19EF2A5800984962 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BB19EF2A5800984962 /* Atomic.swift */; }; + D0C312CF19EF2A5800984962 /* Bag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BC19EF2A5800984962 /* Bag.swift */; }; + D0C312D019EF2A5800984962 /* Bag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BC19EF2A5800984962 /* Bag.swift */; }; + D0C312D319EF2A5800984962 /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BE19EF2A5800984962 /* Disposable.swift */; }; + D0C312D419EF2A5800984962 /* Disposable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312BE19EF2A5800984962 /* Disposable.swift */; }; + D0C312E719EF2A5800984962 /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312C819EF2A5800984962 /* Scheduler.swift */; }; + D0C312E819EF2A5800984962 /* Scheduler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312C819EF2A5800984962 /* Scheduler.swift */; }; + D0C3130C19EF2B1F00984962 /* DisposableSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312F019EF2A7700984962 /* DisposableSpec.swift */; }; + D0C3130E19EF2B1F00984962 /* SchedulerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312F219EF2A7700984962 /* SchedulerSpec.swift */; }; + D0C3131219EF2B2000984962 /* DisposableSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312F019EF2A7700984962 /* DisposableSpec.swift */; }; + D0C3131419EF2B2000984962 /* SchedulerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C312F219EF2A7700984962 /* SchedulerSpec.swift */; }; + D0D11AB91A6AE87700C1F8B1 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54AF1A69A2AC00AD8286 /* Action.swift */; }; + D0D11ABA1A6AE87700C1F8B1 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08C54AF1A69A2AC00AD8286 /* Action.swift */; }; + D8024DB21B2E1BB0005E6B9A /* SignalProducerLiftingSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8024DB11B2E1BB0005E6B9A /* SignalProducerLiftingSpec.swift */; }; + D8024DB31B2E1BB0005E6B9A /* SignalProducerLiftingSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8024DB11B2E1BB0005E6B9A /* SignalProducerLiftingSpec.swift */; }; + D8170FC11B100EBC004192AD /* FoundationExtensionsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8170FC01B100EBC004192AD /* FoundationExtensionsSpec.swift */; }; + D8170FC21B100EBC004192AD /* FoundationExtensionsSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8170FC01B100EBC004192AD /* FoundationExtensionsSpec.swift */; }; + D85C652A1C0D84C7005A77AD /* Flatten.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85C65291C0D84C7005A77AD /* Flatten.swift */; }; + D85C652B1C0E70E3005A77AD /* Flatten.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85C65291C0D84C7005A77AD /* Flatten.swift */; }; + D85C652C1C0E70E4005A77AD /* Flatten.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85C65291C0D84C7005A77AD /* Flatten.swift */; }; + D85C652D1C0E70E5005A77AD /* Flatten.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85C65291C0D84C7005A77AD /* Flatten.swift */; }; + D871D69F1B3B29A40070F16C /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = D871D69E1B3B29A40070F16C /* Optional.swift */; }; + D8E84A671B3B32FB00C3E831 /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = D871D69E1B3B29A40070F16C /* Optional.swift */; }; + EBCC7DBC1BBF010C00A2AE92 /* Observer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBCC7DBB1BBF010C00A2AE92 /* Observer.swift */; }; + EBCC7DBD1BBF01E100A2AE92 /* Observer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBCC7DBB1BBF010C00A2AE92 /* Observer.swift */; }; + EBCC7DBE1BBF01E200A2AE92 /* Observer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBCC7DBB1BBF010C00A2AE92 /* Observer.swift */; }; + EBCC7DBF1BBF01E200A2AE92 /* Observer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBCC7DBB1BBF010C00A2AE92 /* Observer.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 7DFBED091CDB8C9500EE435B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D04725E119E49ED7006002AA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 57A4D1AF1BA13D7A00F7D4B1; + remoteInfo = "ReactiveCocoa-tvOS"; + }; + D04725F719E49ED7006002AA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D04725E119E49ED7006002AA /* Project object */; + proxyType = 1; + remoteGlobalIDString = D04725E919E49ED7006002AA; + remoteInfo = ReactiveCocoa; + }; + D047261819E49F82006002AA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D04725E119E49ED7006002AA /* Project object */; + proxyType = 1; + remoteGlobalIDString = D047260B19E49F82006002AA; + remoteInfo = ReactiveCocoa; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 7DFBED151CDB8CEC00EE435B /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 7DFBED211CDB8D8300EE435B /* Result.framework in Copy Frameworks */, + 7DFBED201CDB8D7D00EE435B /* Nimble.framework in Copy Frameworks */, + 7DFBED1F1CDB8D7800EE435B /* Quick.framework in Copy Frameworks */, + 7DFBED1E1CDB8D7000EE435B /* ReactiveSwift.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + D01B7B6119EDD8F600D26E01 /* Copy Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + CDC42E331AE7AC6D00965373 /* Result.framework in Copy Frameworks */, + D01B7B6219EDD8FE00D26E01 /* Nimble.framework in Copy Frameworks */, + D01B7B6319EDD8FE00D26E01 /* Quick.framework in Copy Frameworks */, + D01B7B6419EDD94B00D26E01 /* ReactiveSwift.framework in Copy Frameworks */, + ); + name = "Copy Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 02D260291C1D6DAF003ACC61 /* SignalLifetimeSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalLifetimeSpec.swift; sourceTree = ""; }; + 4A0AB6711DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReactiveExtensionsSpec.swift; sourceTree = ""; }; + 4A0E10FE1D2A92720065D310 /* Lifetime.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lifetime.swift; sourceTree = ""; }; + 4A0E11031D2A95200065D310 /* LifetimeSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LifetimeSpec.swift; sourceTree = ""; }; + 4AC73ECA1DF273570004EC4F /* ResultExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultExtensions.swift; sourceTree = ""; }; + 57A4D2411BA13D7A00F7D4B1 /* ReactiveSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 57A4D2441BA13F9700F7D4B1 /* tvOS-Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "tvOS-Application.xcconfig"; sourceTree = ""; }; + 57A4D2451BA13F9700F7D4B1 /* tvOS-Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "tvOS-Base.xcconfig"; sourceTree = ""; }; + 57A4D2461BA13F9700F7D4B1 /* tvOS-Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "tvOS-Framework.xcconfig"; sourceTree = ""; }; + 57A4D2471BA13F9700F7D4B1 /* tvOS-StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "tvOS-StaticLibrary.xcconfig"; sourceTree = ""; }; + 7DFBED031CDB8C9500EE435B /* ReactiveSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactiveSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 9A090C131DA0309E00EE97CA /* Reactive.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reactive.swift; sourceTree = ""; }; + 9A1A4F981E16961C006F3039 /* ValidatingPropertySpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidatingPropertySpec.swift; sourceTree = ""; }; + 9A1D067C1D948A2200ACF44C /* UnidirectionalBindingSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnidirectionalBindingSpec.swift; sourceTree = ""; }; + 9A5D93721EE5733300438925 /* InhabitableTypeGuards.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InhabitableTypeGuards.swift; sourceTree = ""; }; + 9A681A9D1E5A241B00B097CF /* DeprecationSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeprecationSpec.swift; sourceTree = ""; }; + 9A9100DE1E0E6E620093E346 /* ValidatingProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidatingProperty.swift; sourceTree = ""; }; + 9ABCB1841D2A5B5A00BCA243 /* Deprecations+Removals.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Deprecations+Removals.swift"; sourceTree = ""; }; + A97451331B3A935E00F48E55 /* watchOS-Application.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "watchOS-Application.xcconfig"; sourceTree = ""; }; + A97451341B3A935E00F48E55 /* watchOS-Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "watchOS-Base.xcconfig"; sourceTree = ""; }; + A97451351B3A935E00F48E55 /* watchOS-Framework.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "watchOS-Framework.xcconfig"; sourceTree = ""; }; + A97451361B3A935E00F48E55 /* watchOS-StaticLibrary.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "watchOS-StaticLibrary.xcconfig"; sourceTree = ""; }; + A9B315541B3940610001CB9C /* ReactiveSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B696FB801A7640C00075236D /* TestError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestError.swift; sourceTree = ""; }; + BE9CF3941D751B6B003AE479 /* UnidirectionalBinding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnidirectionalBinding.swift; sourceTree = ""; }; + BFA6B94A1A76044800C846D1 /* SignalProducerNimbleMatchers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalProducerNimbleMatchers.swift; sourceTree = ""; }; + C79B64731CD38B2B003F2376 /* TestLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestLogger.swift; sourceTree = ""; }; + C79B647B1CD52E23003F2376 /* EventLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventLogger.swift; sourceTree = ""; }; + CA6F284F1C52626B001879D2 /* FlattenSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlattenSpec.swift; sourceTree = ""; }; + CDC42E2E1AE7AB8B00965373 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D021671C1A6CD50500987861 /* ActionSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ActionSpec.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + D037672B19EDA75D00A782A9 /* Quick.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Quick.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D03B4A3C19F4C39A009E02AC /* FoundationExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationExtensions.swift; sourceTree = ""; }; + D04725EA19E49ED7006002AA /* ReactiveSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D04725EE19E49ED7006002AA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D04725EF19E49ED7006002AA /* ReactiveSwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactiveSwift.h; sourceTree = ""; }; + D04725F519E49ED7006002AA /* ReactiveSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactiveSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + D04725FB19E49ED7006002AA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D047260C19E49F82006002AA /* ReactiveSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D047261619E49F82006002AA /* ReactiveSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactiveSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + D047262719E49FE8006002AA /* Common.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Common.xcconfig; sourceTree = ""; }; + D047262919E49FE8006002AA /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + D047262A19E49FE8006002AA /* Profile.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Profile.xcconfig; sourceTree = ""; }; + D047262B19E49FE8006002AA /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + D047262C19E49FE8006002AA /* Test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Test.xcconfig; sourceTree = ""; }; + D047262E19E49FE8006002AA /* Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Application.xcconfig; sourceTree = ""; }; + D047262F19E49FE8006002AA /* Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Framework.xcconfig; sourceTree = ""; }; + D047263019E49FE8006002AA /* StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = StaticLibrary.xcconfig; sourceTree = ""; }; + D047263219E49FE8006002AA /* iOS-Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-Application.xcconfig"; sourceTree = ""; }; + D047263319E49FE8006002AA /* iOS-Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-Base.xcconfig"; sourceTree = ""; }; + D047263419E49FE8006002AA /* iOS-Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-Framework.xcconfig"; sourceTree = ""; }; + D047263519E49FE8006002AA /* iOS-StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "iOS-StaticLibrary.xcconfig"; sourceTree = ""; }; + D047263719E49FE8006002AA /* Mac-Application.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-Application.xcconfig"; sourceTree = ""; }; + D047263819E49FE8006002AA /* Mac-Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-Base.xcconfig"; sourceTree = ""; }; + D047263919E49FE8006002AA /* Mac-DynamicLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-DynamicLibrary.xcconfig"; sourceTree = ""; }; + D047263A19E49FE8006002AA /* Mac-Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-Framework.xcconfig"; sourceTree = ""; }; + D047263B19E49FE8006002AA /* Mac-StaticLibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Mac-StaticLibrary.xcconfig"; sourceTree = ""; }; + D047263C19E49FE8006002AA /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + D05E662419EDD82000904ACA /* Nimble.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Nimble.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D08C54AF1A69A2AC00AD8286 /* Action.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Action.swift; sourceTree = ""; }; + D08C54B01A69A2AC00AD8286 /* Property.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Property.swift; sourceTree = ""; }; + D08C54B11A69A2AC00AD8286 /* Signal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Signal.swift; sourceTree = ""; }; + D08C54B21A69A2AC00AD8286 /* SignalProducer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalProducer.swift; sourceTree = ""; }; + D08C54B51A69A3DB00AD8286 /* Event.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = ""; }; + D0A226071A72E0E900D33B74 /* SignalSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SignalSpec.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + D0A2260A1A72E6C500D33B74 /* SignalProducerSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SignalProducerSpec.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + D0A2260D1A72F16D00D33B74 /* PropertySpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = PropertySpec.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + D0C312BB19EF2A5800984962 /* Atomic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = ""; }; + D0C312BC19EF2A5800984962 /* Bag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bag.swift; sourceTree = ""; }; + D0C312BE19EF2A5800984962 /* Disposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Disposable.swift; sourceTree = ""; }; + D0C312C819EF2A5800984962 /* Scheduler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scheduler.swift; sourceTree = ""; }; + D0C312EE19EF2A7700984962 /* AtomicSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AtomicSpec.swift; sourceTree = ""; }; + D0C312EF19EF2A7700984962 /* BagSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BagSpec.swift; sourceTree = ""; }; + D0C312F019EF2A7700984962 /* DisposableSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisposableSpec.swift; sourceTree = ""; }; + D0C312F219EF2A7700984962 /* SchedulerSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchedulerSpec.swift; sourceTree = ""; }; + D8024DB11B2E1BB0005E6B9A /* SignalProducerLiftingSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SignalProducerLiftingSpec.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + D8170FC01B100EBC004192AD /* FoundationExtensionsSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationExtensionsSpec.swift; sourceTree = ""; }; + D85C65291C0D84C7005A77AD /* Flatten.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Flatten.swift; sourceTree = ""; }; + D871D69E1B3B29A40070F16C /* Optional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Optional.swift; sourceTree = ""; }; + EBCC7DBB1BBF010C00A2AE92 /* Observer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Observer.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 57A4D2071BA13D7A00F7D4B1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 57A4D2081BA13D7A00F7D4B1 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7DFBED001CDB8C9500EE435B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CDF066CA1CDC1CA200199626 /* Nimble.framework in Frameworks */, + CDF066CB1CDC1CA200199626 /* Quick.framework in Frameworks */, + 7DFBED081CDB8C9500EE435B /* ReactiveSwift.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A9B315501B3940610001CB9C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A9B315C91B3940980001CB9C /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D04725E619E49ED7006002AA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CDC42E2F1AE7AB8B00965373 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D04725F219E49ED7006002AA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CDC42E301AE7AB8B00965373 /* Result.framework in Frameworks */, + D05E662519EDD82000904ACA /* Nimble.framework in Frameworks */, + D037672D19EDA75D00A782A9 /* Quick.framework in Frameworks */, + D04725F619E49ED7006002AA /* ReactiveSwift.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D047260819E49F82006002AA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + CDC42E311AE7AB8B00965373 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D047261319E49F82006002AA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D05E662619EDD83000904ACA /* Nimble.framework in Frameworks */, + D037672F19EDA78B00A782A9 /* Quick.framework in Frameworks */, + D047261719E49F82006002AA /* ReactiveSwift.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 57A4D2431BA13F9700F7D4B1 /* tvOS */ = { + isa = PBXGroup; + children = ( + 57A4D2441BA13F9700F7D4B1 /* tvOS-Application.xcconfig */, + 57A4D2451BA13F9700F7D4B1 /* tvOS-Base.xcconfig */, + 57A4D2461BA13F9700F7D4B1 /* tvOS-Framework.xcconfig */, + 57A4D2471BA13F9700F7D4B1 /* tvOS-StaticLibrary.xcconfig */, + ); + path = tvOS; + sourceTree = ""; + }; + A97451321B3A935E00F48E55 /* watchOS */ = { + isa = PBXGroup; + children = ( + A97451331B3A935E00F48E55 /* watchOS-Application.xcconfig */, + A97451341B3A935E00F48E55 /* watchOS-Base.xcconfig */, + A97451351B3A935E00F48E55 /* watchOS-Framework.xcconfig */, + A97451361B3A935E00F48E55 /* watchOS-StaticLibrary.xcconfig */, + ); + path = watchOS; + sourceTree = ""; + }; + D03B4A3919F4C25F009E02AC /* Signals */ = { + isa = PBXGroup; + children = ( + D08C54AF1A69A2AC00AD8286 /* Action.swift */, + D85C65291C0D84C7005A77AD /* Flatten.swift */, + 4A0E10FE1D2A92720065D310 /* Lifetime.swift */, + D08C54B01A69A2AC00AD8286 /* Property.swift */, + 9A9100DE1E0E6E620093E346 /* ValidatingProperty.swift */, + D08C54B11A69A2AC00AD8286 /* Signal.swift */, + D08C54B21A69A2AC00AD8286 /* SignalProducer.swift */, + BE9CF3941D751B6B003AE479 /* UnidirectionalBinding.swift */, + 9A5D93721EE5733300438925 /* InhabitableTypeGuards.swift */, + ); + name = Signals; + sourceTree = ""; + }; + D03B4A3B19F4C281009E02AC /* Extensions */ = { + isa = PBXGroup; + children = ( + 4AC73ECA1DF273570004EC4F /* ResultExtensions.swift */, + D03B4A3C19F4C39A009E02AC /* FoundationExtensions.swift */, + ); + name = Extensions; + sourceTree = ""; + }; + D04725E019E49ED7006002AA = { + isa = PBXGroup; + children = ( + D04725EC19E49ED7006002AA /* ReactiveSwift */, + D04725F919E49ED7006002AA /* ReactiveSwiftTests */, + D047262519E49FE8006002AA /* Configuration */, + D04725EB19E49ED7006002AA /* Products */, + ); + sourceTree = ""; + usesTabs = 1; + }; + D04725EB19E49ED7006002AA /* Products */ = { + isa = PBXGroup; + children = ( + D04725EA19E49ED7006002AA /* ReactiveSwift.framework */, + D04725F519E49ED7006002AA /* ReactiveSwiftTests.xctest */, + D047260C19E49F82006002AA /* ReactiveSwift.framework */, + D047261619E49F82006002AA /* ReactiveSwiftTests.xctest */, + A9B315541B3940610001CB9C /* ReactiveSwift.framework */, + 57A4D2411BA13D7A00F7D4B1 /* ReactiveSwift.framework */, + 7DFBED031CDB8C9500EE435B /* ReactiveSwiftTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + D04725EC19E49ED7006002AA /* ReactiveSwift */ = { + isa = PBXGroup; + children = ( + D04725EF19E49ED7006002AA /* ReactiveSwift.h */, + D0C312BB19EF2A5800984962 /* Atomic.swift */, + D0C312BC19EF2A5800984962 /* Bag.swift */, + D0C312BE19EF2A5800984962 /* Disposable.swift */, + D08C54B51A69A3DB00AD8286 /* Event.swift */, + EBCC7DBB1BBF010C00A2AE92 /* Observer.swift */, + D871D69E1B3B29A40070F16C /* Optional.swift */, + 9A090C131DA0309E00EE97CA /* Reactive.swift */, + D0C312C819EF2A5800984962 /* Scheduler.swift */, + C79B647B1CD52E23003F2376 /* EventLogger.swift */, + D03B4A3919F4C25F009E02AC /* Signals */, + D03B4A3B19F4C281009E02AC /* Extensions */, + 9ABCB1841D2A5B5A00BCA243 /* Deprecations+Removals.swift */, + D04725ED19E49ED7006002AA /* Supporting Files */, + ); + name = ReactiveSwift; + path = Sources; + sourceTree = ""; + }; + D04725ED19E49ED7006002AA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + CDC42E2E1AE7AB8B00965373 /* Result.framework */, + D04725EE19E49ED7006002AA /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + D04725F919E49ED7006002AA /* ReactiveSwiftTests */ = { + isa = PBXGroup; + children = ( + D021671C1A6CD50500987861 /* ActionSpec.swift */, + D0C312EE19EF2A7700984962 /* AtomicSpec.swift */, + D0C312EF19EF2A7700984962 /* BagSpec.swift */, + D0C312F019EF2A7700984962 /* DisposableSpec.swift */, + CA6F284F1C52626B001879D2 /* FlattenSpec.swift */, + D8170FC01B100EBC004192AD /* FoundationExtensionsSpec.swift */, + 4A0E11031D2A95200065D310 /* LifetimeSpec.swift */, + D0A2260D1A72F16D00D33B74 /* PropertySpec.swift */, + 4A0AB6711DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift */, + D0C312F219EF2A7700984962 /* SchedulerSpec.swift */, + 02D260291C1D6DAF003ACC61 /* SignalLifetimeSpec.swift */, + D8024DB11B2E1BB0005E6B9A /* SignalProducerLiftingSpec.swift */, + D0A2260A1A72E6C500D33B74 /* SignalProducerSpec.swift */, + D0A226071A72E0E900D33B74 /* SignalSpec.swift */, + B696FB801A7640C00075236D /* TestError.swift */, + C79B64731CD38B2B003F2376 /* TestLogger.swift */, + 9A1D067C1D948A2200ACF44C /* UnidirectionalBindingSpec.swift */, + 9A1A4F981E16961C006F3039 /* ValidatingPropertySpec.swift */, + 9A681A9D1E5A241B00B097CF /* DeprecationSpec.swift */, + D04725FA19E49ED7006002AA /* Supporting Files */, + ); + name = ReactiveSwiftTests; + path = Tests/ReactiveSwiftTests; + sourceTree = ""; + }; + D04725FA19E49ED7006002AA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D05E662419EDD82000904ACA /* Nimble.framework */, + D037672B19EDA75D00A782A9 /* Quick.framework */, + BFA6B94A1A76044800C846D1 /* SignalProducerNimbleMatchers.swift */, + D04725FB19E49ED7006002AA /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + D047262519E49FE8006002AA /* Configuration */ = { + isa = PBXGroup; + children = ( + D047262619E49FE8006002AA /* Base */, + D047263119E49FE8006002AA /* iOS */, + D047263619E49FE8006002AA /* Mac OS X */, + A97451321B3A935E00F48E55 /* watchOS */, + 57A4D2431BA13F9700F7D4B1 /* tvOS */, + D047263C19E49FE8006002AA /* README.md */, + ); + name = Configuration; + path = Carthage/Checkouts/xcconfigs; + sourceTree = ""; + }; + D047262619E49FE8006002AA /* Base */ = { + isa = PBXGroup; + children = ( + D047262719E49FE8006002AA /* Common.xcconfig */, + D047262819E49FE8006002AA /* Configurations */, + D047262D19E49FE8006002AA /* Targets */, + ); + path = Base; + sourceTree = ""; + }; + D047262819E49FE8006002AA /* Configurations */ = { + isa = PBXGroup; + children = ( + D047262919E49FE8006002AA /* Debug.xcconfig */, + D047262A19E49FE8006002AA /* Profile.xcconfig */, + D047262B19E49FE8006002AA /* Release.xcconfig */, + D047262C19E49FE8006002AA /* Test.xcconfig */, + ); + path = Configurations; + sourceTree = ""; + }; + D047262D19E49FE8006002AA /* Targets */ = { + isa = PBXGroup; + children = ( + D047262E19E49FE8006002AA /* Application.xcconfig */, + D047262F19E49FE8006002AA /* Framework.xcconfig */, + D047263019E49FE8006002AA /* StaticLibrary.xcconfig */, + ); + path = Targets; + sourceTree = ""; + }; + D047263119E49FE8006002AA /* iOS */ = { + isa = PBXGroup; + children = ( + D047263219E49FE8006002AA /* iOS-Application.xcconfig */, + D047263319E49FE8006002AA /* iOS-Base.xcconfig */, + D047263419E49FE8006002AA /* iOS-Framework.xcconfig */, + D047263519E49FE8006002AA /* iOS-StaticLibrary.xcconfig */, + ); + path = iOS; + sourceTree = ""; + }; + D047263619E49FE8006002AA /* Mac OS X */ = { + isa = PBXGroup; + children = ( + D047263719E49FE8006002AA /* Mac-Application.xcconfig */, + D047263819E49FE8006002AA /* Mac-Base.xcconfig */, + D047263919E49FE8006002AA /* Mac-DynamicLibrary.xcconfig */, + D047263A19E49FE8006002AA /* Mac-Framework.xcconfig */, + D047263B19E49FE8006002AA /* Mac-StaticLibrary.xcconfig */, + ); + path = "Mac OS X"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 57A4D2091BA13D7A00F7D4B1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 57A4D20A1BA13D7A00F7D4B1 /* ReactiveSwift.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A9B315511B3940610001CB9C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A9B315CA1B3940AB0001CB9C /* ReactiveSwift.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D04725E719E49ED7006002AA /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D04725F019E49ED7006002AA /* ReactiveSwift.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D047260919E49F82006002AA /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + D037666419EDA43C00A782A9 /* ReactiveSwift.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 57A4D1AF1BA13D7A00F7D4B1 /* ReactiveSwift-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 57A4D23C1BA13D7A00F7D4B1 /* Build configuration list for PBXNativeTarget "ReactiveSwift-tvOS" */; + buildPhases = ( + 57A4D1B01BA13D7A00F7D4B1 /* Sources */, + 57A4D2071BA13D7A00F7D4B1 /* Frameworks */, + 57A4D2091BA13D7A00F7D4B1 /* Headers */, + 57A4D23B1BA13D7A00F7D4B1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ReactiveSwift-tvOS"; + productName = ReactiveCocoa; + productReference = 57A4D2411BA13D7A00F7D4B1 /* ReactiveSwift.framework */; + productType = "com.apple.product-type.framework"; + }; + 7DFBED021CDB8C9500EE435B /* ReactiveSwift-tvOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7DFBED0F1CDB8C9500EE435B /* Build configuration list for PBXNativeTarget "ReactiveSwift-tvOSTests" */; + buildPhases = ( + 7DFBECFF1CDB8C9500EE435B /* Sources */, + 7DFBED001CDB8C9500EE435B /* Frameworks */, + 7DFBED011CDB8C9500EE435B /* Resources */, + 7DFBED151CDB8CEC00EE435B /* Copy Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 7DFBED0A1CDB8C9500EE435B /* PBXTargetDependency */, + ); + name = "ReactiveSwift-tvOSTests"; + productName = "ReactiveCocoa-tvOSTests"; + productReference = 7DFBED031CDB8C9500EE435B /* ReactiveSwiftTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + A9B315531B3940610001CB9C /* ReactiveSwift-watchOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = A9B3155D1B3940610001CB9C /* Build configuration list for PBXNativeTarget "ReactiveSwift-watchOS" */; + buildPhases = ( + A9B3154F1B3940610001CB9C /* Sources */, + A9B315501B3940610001CB9C /* Frameworks */, + A9B315511B3940610001CB9C /* Headers */, + A9B315521B3940610001CB9C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ReactiveSwift-watchOS"; + productName = ReactiveCocoa; + productReference = A9B315541B3940610001CB9C /* ReactiveSwift.framework */; + productType = "com.apple.product-type.framework"; + }; + D04725E919E49ED7006002AA /* ReactiveSwift-macOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = D047260019E49ED7006002AA /* Build configuration list for PBXNativeTarget "ReactiveSwift-macOS" */; + buildPhases = ( + D04725E519E49ED7006002AA /* Sources */, + D04725E619E49ED7006002AA /* Frameworks */, + D04725E719E49ED7006002AA /* Headers */, + D04725E819E49ED7006002AA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ReactiveSwift-macOS"; + productName = ReactiveCocoa; + productReference = D04725EA19E49ED7006002AA /* ReactiveSwift.framework */; + productType = "com.apple.product-type.framework"; + }; + D04725F419E49ED7006002AA /* ReactiveSwift-macOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D047260319E49ED7006002AA /* Build configuration list for PBXNativeTarget "ReactiveSwift-macOSTests" */; + buildPhases = ( + D04725F119E49ED7006002AA /* Sources */, + D04725F219E49ED7006002AA /* Frameworks */, + D04725F319E49ED7006002AA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + D04725F819E49ED7006002AA /* PBXTargetDependency */, + ); + name = "ReactiveSwift-macOSTests"; + productName = ReactiveCocoaTests; + productReference = D04725F519E49ED7006002AA /* ReactiveSwiftTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + D047260B19E49F82006002AA /* ReactiveSwift-iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = D047261F19E49F82006002AA /* Build configuration list for PBXNativeTarget "ReactiveSwift-iOS" */; + buildPhases = ( + D047260719E49F82006002AA /* Sources */, + D047260819E49F82006002AA /* Frameworks */, + D047260919E49F82006002AA /* Headers */, + D047260A19E49F82006002AA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "ReactiveSwift-iOS"; + productName = ReactiveCocoa; + productReference = D047260C19E49F82006002AA /* ReactiveSwift.framework */; + productType = "com.apple.product-type.framework"; + }; + D047261519E49F82006002AA /* ReactiveSwift-iOSTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = D047262219E49F82006002AA /* Build configuration list for PBXNativeTarget "ReactiveSwift-iOSTests" */; + buildPhases = ( + D047261219E49F82006002AA /* Sources */, + D047261319E49F82006002AA /* Frameworks */, + D047261419E49F82006002AA /* Resources */, + D01B7B6119EDD8F600D26E01 /* Copy Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D047261919E49F82006002AA /* PBXTargetDependency */, + ); + name = "ReactiveSwift-iOSTests"; + productName = ReactiveCocoaTests; + productReference = D047261619E49F82006002AA /* ReactiveSwiftTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D04725E119E49ED7006002AA /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0730; + LastUpgradeCheck = 0710; + ORGANIZATIONNAME = GitHub; + TargetAttributes = { + 57A4D1AF1BA13D7A00F7D4B1 = { + LastSwiftMigration = 0800; + }; + 7DFBED021CDB8C9500EE435B = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 0800; + }; + A9B315531B3940610001CB9C = { + CreatedOnToolsVersion = 7.0; + LastSwiftMigration = 0800; + }; + D04725E919E49ED7006002AA = { + CreatedOnToolsVersion = 6.1; + LastSwiftMigration = 0800; + }; + D04725F419E49ED7006002AA = { + CreatedOnToolsVersion = 6.1; + LastSwiftMigration = 0800; + }; + D047260B19E49F82006002AA = { + CreatedOnToolsVersion = 6.1; + LastSwiftMigration = 0800; + }; + D047261519E49F82006002AA = { + CreatedOnToolsVersion = 6.1; + LastSwiftMigration = 0800; + }; + }; + }; + buildConfigurationList = D04725E419E49ED7006002AA /* Build configuration list for PBXProject "ReactiveSwift" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = D04725E019E49ED7006002AA; + productRefGroup = D04725EB19E49ED7006002AA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D04725E919E49ED7006002AA /* ReactiveSwift-macOS */, + D04725F419E49ED7006002AA /* ReactiveSwift-macOSTests */, + D047260B19E49F82006002AA /* ReactiveSwift-iOS */, + D047261519E49F82006002AA /* ReactiveSwift-iOSTests */, + A9B315531B3940610001CB9C /* ReactiveSwift-watchOS */, + 57A4D1AF1BA13D7A00F7D4B1 /* ReactiveSwift-tvOS */, + 7DFBED021CDB8C9500EE435B /* ReactiveSwift-tvOSTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 57A4D23B1BA13D7A00F7D4B1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7DFBED011CDB8C9500EE435B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A9B315521B3940610001CB9C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D04725E819E49ED7006002AA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D04725F319E49ED7006002AA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D047260A19E49F82006002AA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D047261419E49F82006002AA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 57A4D1B01BA13D7A00F7D4B1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 57A4D1B11BA13D7A00F7D4B1 /* Optional.swift in Sources */, + 57A4D1B41BA13D7A00F7D4B1 /* Disposable.swift in Sources */, + 57A4D1B61BA13D7A00F7D4B1 /* Event.swift in Sources */, + 57A4D1B81BA13D7A00F7D4B1 /* Scheduler.swift in Sources */, + 4AC73ECE1DF273570004EC4F /* ResultExtensions.swift in Sources */, + 9A9100E21E0E6E680093E346 /* ValidatingProperty.swift in Sources */, + 57A4D1B91BA13D7A00F7D4B1 /* Action.swift in Sources */, + 57A4D1BA1BA13D7A00F7D4B1 /* Property.swift in Sources */, + 9A090C171DA0309E00EE97CA /* Reactive.swift in Sources */, + 57A4D1BB1BA13D7A00F7D4B1 /* Signal.swift in Sources */, + 57A4D1BC1BA13D7A00F7D4B1 /* SignalProducer.swift in Sources */, + 9A5D93761EE5733300438925 /* InhabitableTypeGuards.swift in Sources */, + 57A4D1BD1BA13D7A00F7D4B1 /* Atomic.swift in Sources */, + 57A4D1BE1BA13D7A00F7D4B1 /* Bag.swift in Sources */, + 57A4D1C01BA13D7A00F7D4B1 /* FoundationExtensions.swift in Sources */, + D85C652D1C0E70E5005A77AD /* Flatten.swift in Sources */, + 9ABCB1881D2A5B5A00BCA243 /* Deprecations+Removals.swift in Sources */, + EBCC7DBF1BBF01E200A2AE92 /* Observer.swift in Sources */, + C79B64801CD52E4E003F2376 /* EventLogger.swift in Sources */, + 4A0E11021D2A92720065D310 /* Lifetime.swift in Sources */, + BE9CF3981D751B71003AE479 /* UnidirectionalBinding.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7DFBECFF1CDB8C9500EE435B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7DFBED221CDB8DE300EE435B /* ActionSpec.swift in Sources */, + 7DFBED231CDB8DE300EE435B /* AtomicSpec.swift in Sources */, + 7DFBED241CDB8DE300EE435B /* BagSpec.swift in Sources */, + 7DFBED251CDB8DE300EE435B /* DisposableSpec.swift in Sources */, + 7DFBED261CDB8DE300EE435B /* FoundationExtensionsSpec.swift in Sources */, + 7DFBED281CDB8DE300EE435B /* PropertySpec.swift in Sources */, + 7DFBED291CDB8DE300EE435B /* SchedulerSpec.swift in Sources */, + 7DFBED2A1CDB8DE300EE435B /* SignalLifetimeSpec.swift in Sources */, + 7DFBED2B1CDB8DE300EE435B /* SignalProducerSpec.swift in Sources */, + 9A681AA01E5A241B00B097CF /* DeprecationSpec.swift in Sources */, + 7DFBED2C1CDB8DE300EE435B /* SignalProducerLiftingSpec.swift in Sources */, + 7DFBED2D1CDB8DE300EE435B /* SignalSpec.swift in Sources */, + 7DFBED2E1CDB8DE300EE435B /* FlattenSpec.swift in Sources */, + 7DFBED2F1CDB8DE300EE435B /* TestError.swift in Sources */, + 7DFBED301CDB8DE300EE435B /* TestLogger.swift in Sources */, + 9A1D067F1D948A2300ACF44C /* UnidirectionalBindingSpec.swift in Sources */, + 9A1A4F9F1E16AE55006F3039 /* ValidatingPropertySpec.swift in Sources */, + 4A0E11061D2A95200065D310 /* LifetimeSpec.swift in Sources */, + 7DFBED6D1CDB8F7D00EE435B /* SignalProducerNimbleMatchers.swift in Sources */, + 4A0AB6741DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A9B3154F1B3940610001CB9C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A9F793341B60D0140026BCBA /* Optional.swift in Sources */, + A9B315BC1B3940810001CB9C /* Disposable.swift in Sources */, + A9B315BE1B3940810001CB9C /* Event.swift in Sources */, + A9B315C01B3940810001CB9C /* Scheduler.swift in Sources */, + 4AC73ECD1DF273570004EC4F /* ResultExtensions.swift in Sources */, + 9A9100E11E0E6E680093E346 /* ValidatingProperty.swift in Sources */, + A9B315C11B3940810001CB9C /* Action.swift in Sources */, + A9B315C21B3940810001CB9C /* Property.swift in Sources */, + 9A090C161DA0309E00EE97CA /* Reactive.swift in Sources */, + A9B315C31B3940810001CB9C /* Signal.swift in Sources */, + A9B315C41B3940810001CB9C /* SignalProducer.swift in Sources */, + 9A5D93751EE5733300438925 /* InhabitableTypeGuards.swift in Sources */, + A9B315C51B3940810001CB9C /* Atomic.swift in Sources */, + A9B315C61B3940810001CB9C /* Bag.swift in Sources */, + A9B315C81B3940810001CB9C /* FoundationExtensions.swift in Sources */, + D85C652C1C0E70E4005A77AD /* Flatten.swift in Sources */, + 9ABCB1871D2A5B5A00BCA243 /* Deprecations+Removals.swift in Sources */, + EBCC7DBE1BBF01E200A2AE92 /* Observer.swift in Sources */, + C79B647F1CD52E4D003F2376 /* EventLogger.swift in Sources */, + 4A0E11011D2A92720065D310 /* Lifetime.swift in Sources */, + BE9CF3971D751B71003AE479 /* UnidirectionalBinding.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D04725E519E49ED7006002AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D871D69F1B3B29A40070F16C /* Optional.swift in Sources */, + D08C54B61A69A3DB00AD8286 /* Event.swift in Sources */, + D0C312D319EF2A5800984962 /* Disposable.swift in Sources */, + 4AC73ECB1DF273570004EC4F /* ResultExtensions.swift in Sources */, + 9A9100DF1E0E6E620093E346 /* ValidatingProperty.swift in Sources */, + EBCC7DBC1BBF010C00A2AE92 /* Observer.swift in Sources */, + D03B4A3D19F4C39A009E02AC /* FoundationExtensions.swift in Sources */, + 9A090C141DA0309E00EE97CA /* Reactive.swift in Sources */, + D08C54B31A69A2AE00AD8286 /* Signal.swift in Sources */, + D85C652A1C0D84C7005A77AD /* Flatten.swift in Sources */, + D0C312CF19EF2A5800984962 /* Bag.swift in Sources */, + 9A5D93731EE5733300438925 /* InhabitableTypeGuards.swift in Sources */, + 4A0E10FF1D2A92720065D310 /* Lifetime.swift in Sources */, + D0C312E719EF2A5800984962 /* Scheduler.swift in Sources */, + D0C312CD19EF2A5800984962 /* Atomic.swift in Sources */, + D08C54BA1A69C54300AD8286 /* Property.swift in Sources */, + D0D11AB91A6AE87700C1F8B1 /* Action.swift in Sources */, + C79B647C1CD52E23003F2376 /* EventLogger.swift in Sources */, + 9ABCB1851D2A5B5A00BCA243 /* Deprecations+Removals.swift in Sources */, + D08C54B81A69A9D000AD8286 /* SignalProducer.swift in Sources */, + BE9CF3951D751B6B003AE479 /* UnidirectionalBinding.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D04725F119E49ED7006002AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D0A2260E1A72F16D00D33B74 /* PropertySpec.swift in Sources */, + B696FB811A7640C00075236D /* TestError.swift in Sources */, + D021671D1A6CD50500987861 /* ActionSpec.swift in Sources */, + D0C3130E19EF2B1F00984962 /* SchedulerSpec.swift in Sources */, + BFA6B94D1A7604D400C846D1 /* SignalProducerNimbleMatchers.swift in Sources */, + D8170FC11B100EBC004192AD /* FoundationExtensionsSpec.swift in Sources */, + C79B64741CD38B2B003F2376 /* TestLogger.swift in Sources */, + CA6F28501C52626B001879D2 /* FlattenSpec.swift in Sources */, + 4A0E11041D2A95200065D310 /* LifetimeSpec.swift in Sources */, + 9A681A9E1E5A241B00B097CF /* DeprecationSpec.swift in Sources */, + CDCD247A1C277EEC00710AEE /* AtomicSpec.swift in Sources */, + 579504331BB8A34200A5E482 /* BagSpec.swift in Sources */, + D0A226081A72E0E900D33B74 /* SignalSpec.swift in Sources */, + 02D2602B1C1D6DB8003ACC61 /* SignalLifetimeSpec.swift in Sources */, + D0C3130C19EF2B1F00984962 /* DisposableSpec.swift in Sources */, + 9A1D067D1D948A2300ACF44C /* UnidirectionalBindingSpec.swift in Sources */, + 9A1A4F9D1E16AE50006F3039 /* ValidatingPropertySpec.swift in Sources */, + D0A2260B1A72E6C500D33B74 /* SignalProducerSpec.swift in Sources */, + D8024DB21B2E1BB0005E6B9A /* SignalProducerLiftingSpec.swift in Sources */, + 4A0AB6721DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D047260719E49F82006002AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D08C54B41A69A2AF00AD8286 /* Signal.swift in Sources */, + D8E84A671B3B32FB00C3E831 /* Optional.swift in Sources */, + D0C312D419EF2A5800984962 /* Disposable.swift in Sources */, + D08C54B91A69A9D100AD8286 /* SignalProducer.swift in Sources */, + 4AC73ECC1DF273570004EC4F /* ResultExtensions.swift in Sources */, + 9A9100E01E0E6E670093E346 /* ValidatingProperty.swift in Sources */, + 9ABCB1861D2A5B5A00BCA243 /* Deprecations+Removals.swift in Sources */, + EBCC7DBD1BBF01E100A2AE92 /* Observer.swift in Sources */, + 9A090C151DA0309E00EE97CA /* Reactive.swift in Sources */, + D85C652B1C0E70E3005A77AD /* Flatten.swift in Sources */, + 4A0E11001D2A92720065D310 /* Lifetime.swift in Sources */, + 9A5D93741EE5733300438925 /* InhabitableTypeGuards.swift in Sources */, + D08C54BB1A69C54400AD8286 /* Property.swift in Sources */, + D03B4A3E19F4C39A009E02AC /* FoundationExtensions.swift in Sources */, + D08C54B71A69A3DB00AD8286 /* Event.swift in Sources */, + C79B647D1CD52E4A003F2376 /* EventLogger.swift in Sources */, + D0C312CE19EF2A5800984962 /* Atomic.swift in Sources */, + D0C312E819EF2A5800984962 /* Scheduler.swift in Sources */, + D0C312D019EF2A5800984962 /* Bag.swift in Sources */, + D0D11ABA1A6AE87700C1F8B1 /* Action.swift in Sources */, + BE9CF3961D751B70003AE479 /* UnidirectionalBinding.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D047261219E49F82006002AA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D0A2260C1A72E6C500D33B74 /* SignalProducerSpec.swift in Sources */, + D0A2260F1A72F16D00D33B74 /* PropertySpec.swift in Sources */, + D0A226091A72E0E900D33B74 /* SignalSpec.swift in Sources */, + CDCD247B1C277EED00710AEE /* AtomicSpec.swift in Sources */, + D021671E1A6CD50500987861 /* ActionSpec.swift in Sources */, + D8024DB31B2E1BB0005E6B9A /* SignalProducerLiftingSpec.swift in Sources */, + BFA6B94E1A7604D500C846D1 /* SignalProducerNimbleMatchers.swift in Sources */, + B696FB821A7640C00075236D /* TestError.swift in Sources */, + D8170FC21B100EBC004192AD /* FoundationExtensionsSpec.swift in Sources */, + 9A681A9F1E5A241B00B097CF /* DeprecationSpec.swift in Sources */, + D0C3131419EF2B2000984962 /* SchedulerSpec.swift in Sources */, + C79B64751CD38B2B003F2376 /* TestLogger.swift in Sources */, + D0C3131219EF2B2000984962 /* DisposableSpec.swift in Sources */, + CA6F28511C52626B001879D2 /* FlattenSpec.swift in Sources */, + 579504341BB8A34300A5E482 /* BagSpec.swift in Sources */, + 9A1D067E1D948A2300ACF44C /* UnidirectionalBindingSpec.swift in Sources */, + 9A1A4F9E1E16AE50006F3039 /* ValidatingPropertySpec.swift in Sources */, + 4A0E11051D2A95200065D310 /* LifetimeSpec.swift in Sources */, + 02D2602A1C1D6DAF003ACC61 /* SignalLifetimeSpec.swift in Sources */, + 4A0AB6731DC28EFF00AA1E81 /* ReactiveExtensionsSpec.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 7DFBED0A1CDB8C9500EE435B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 57A4D1AF1BA13D7A00F7D4B1 /* ReactiveSwift-tvOS */; + targetProxy = 7DFBED091CDB8C9500EE435B /* PBXContainerItemProxy */; + }; + D04725F819E49ED7006002AA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D04725E919E49ED7006002AA /* ReactiveSwift-macOS */; + targetProxy = D04725F719E49ED7006002AA /* PBXContainerItemProxy */; + }; + D047261919E49F82006002AA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D047260B19E49F82006002AA /* ReactiveSwift-iOS */; + targetProxy = D047261819E49F82006002AA /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 57A4D23D1BA13D7A00F7D4B1 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 57A4D2461BA13F9700F7D4B1 /* tvOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DTRACE_PROBES_DISABLED=1", + ); + INFOPLIST_FILE = Sources/Info.plist; + }; + name = Debug; + }; + 57A4D23E1BA13D7A00F7D4B1 /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 57A4D2461BA13F9700F7D4B1 /* tvOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DTRACE_PROBES_DISABLED=1", + ); + INFOPLIST_FILE = Sources/Info.plist; + }; + name = Test; + }; + 57A4D23F1BA13D7A00F7D4B1 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 57A4D2461BA13F9700F7D4B1 /* tvOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DTRACE_PROBES_DISABLED=1", + ); + INFOPLIST_FILE = Sources/Info.plist; + }; + name = Release; + }; + 57A4D2401BA13D7A00F7D4B1 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 57A4D2461BA13F9700F7D4B1 /* tvOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DTRACE_PROBES_DISABLED=1", + ); + INFOPLIST_FILE = Sources/Info.plist; + }; + name = Profile; + }; + 7DFBED0B1CDB8C9500EE435B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 57A4D2441BA13F9700F7D4B1 /* tvOS-Application.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Debug; + }; + 7DFBED0C1CDB8C9500EE435B /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 57A4D2441BA13F9700F7D4B1 /* tvOS-Application.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Test; + }; + 7DFBED0D1CDB8C9500EE435B /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 57A4D2441BA13F9700F7D4B1 /* tvOS-Application.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Release; + }; + 7DFBED0E1CDB8C9500EE435B /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 57A4D2441BA13F9700F7D4B1 /* tvOS-Application.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Profile; + }; + A9B315591B3940610001CB9C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A97451351B3A935E00F48E55 /* watchOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DTRACE_PROBES_DISABLED=1", + ); + INFOPLIST_FILE = Sources/Info.plist; + }; + name = Debug; + }; + A9B3155A1B3940610001CB9C /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A97451351B3A935E00F48E55 /* watchOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DTRACE_PROBES_DISABLED=1", + ); + INFOPLIST_FILE = Sources/Info.plist; + }; + name = Test; + }; + A9B3155B1B3940610001CB9C /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A97451351B3A935E00F48E55 /* watchOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DTRACE_PROBES_DISABLED=1", + ); + INFOPLIST_FILE = Sources/Info.plist; + }; + name = Release; + }; + A9B3155C1B3940610001CB9C /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A97451351B3A935E00F48E55 /* watchOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DTRACE_PROBES_DISABLED=1", + ); + INFOPLIST_FILE = Sources/Info.plist; + }; + name = Profile; + }; + D04725FE19E49ED7006002AA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047262919E49FE8006002AA /* Debug.xcconfig */; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CODE_SIGNING_REQUIRED = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_TESTABILITY = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactivecocoa.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(PROJECT_NAME)"; + SWIFT_VERSION = 3.0; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Debug; + }; + D04725FF19E49ED7006002AA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047262B19E49FE8006002AA /* Release.xcconfig */; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CODE_SIGNING_REQUIRED = NO; + CURRENT_PROJECT_VERSION = 1; + GCC_OPTIMIZATION_LEVEL = 0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactivecocoa.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(PROJECT_NAME)"; + SWIFT_VERSION = 3.0; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Release; + }; + D047260119E49ED7006002AA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263A19E49FE8006002AA /* Mac-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + }; + name = Debug; + }; + D047260219E49ED7006002AA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263A19E49FE8006002AA /* Mac-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + }; + name = Release; + }; + D047260419E49ED7006002AA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263719E49FE8006002AA /* Mac-Application.xcconfig */; + buildSettings = { + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Debug; + }; + D047260519E49ED7006002AA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263719E49FE8006002AA /* Mac-Application.xcconfig */; + buildSettings = { + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Release; + }; + D047262019E49F82006002AA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263419E49FE8006002AA /* iOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + INFOPLIST_FILE = Sources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + }; + name = Debug; + }; + D047262119E49F82006002AA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263419E49FE8006002AA /* iOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + INFOPLIST_FILE = Sources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + }; + name = Release; + }; + D047262319E49F82006002AA /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263219E49FE8006002AA /* iOS-Application.xcconfig */; + buildSettings = { + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Debug; + }; + D047262419E49F82006002AA /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263219E49FE8006002AA /* iOS-Application.xcconfig */; + buildSettings = { + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Release; + }; + D047263D19E4A008006002AA /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047262A19E49FE8006002AA /* Profile.xcconfig */; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CODE_SIGNING_REQUIRED = NO; + CURRENT_PROJECT_VERSION = 1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactivecocoa.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(PROJECT_NAME)"; + SWIFT_VERSION = 3.0; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Profile; + }; + D047263E19E4A008006002AA /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263A19E49FE8006002AA /* Mac-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + }; + name = Profile; + }; + D047263F19E4A008006002AA /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263719E49FE8006002AA /* Mac-Application.xcconfig */; + buildSettings = { + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Profile; + }; + D047264019E4A008006002AA /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263419E49FE8006002AA /* iOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + INFOPLIST_FILE = Sources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + }; + name = Profile; + }; + D047264119E4A008006002AA /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263219E49FE8006002AA /* iOS-Application.xcconfig */; + buildSettings = { + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Profile; + }; + D047264219E4A00B006002AA /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047262C19E49FE8006002AA /* Test.xcconfig */; + buildSettings = { + BITCODE_GENERATION_MODE = bitcode; + CODE_SIGNING_REQUIRED = NO; + CURRENT_PROJECT_VERSION = 1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactivecocoa.$(PRODUCT_NAME:rfc1034identifier)-Tests"; + PRODUCT_NAME = "$(PROJECT_NAME)"; + SWIFT_VERSION = 3.0; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + WATCHOS_DEPLOYMENT_TARGET = 2.0; + }; + name = Test; + }; + D047264319E4A00B006002AA /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263A19E49FE8006002AA /* Mac-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = Sources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + }; + name = Test; + }; + D047264419E4A00B006002AA /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263719E49FE8006002AA /* Mac-Application.xcconfig */; + buildSettings = { + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Test; + }; + D047264519E4A00B006002AA /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263419E49FE8006002AA /* iOS-Framework.xcconfig */; + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_BITCODE = YES; + INFOPLIST_FILE = Sources/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + }; + name = Test; + }; + D047264619E4A00B006002AA /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D047263219E49FE8006002AA /* iOS-Application.xcconfig */; + buildSettings = { + INFOPLIST_FILE = Tests/ReactiveSwiftTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(PROJECT_NAME)Tests"; + }; + name = Test; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 57A4D23C1BA13D7A00F7D4B1 /* Build configuration list for PBXNativeTarget "ReactiveSwift-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 57A4D23D1BA13D7A00F7D4B1 /* Debug */, + 57A4D23E1BA13D7A00F7D4B1 /* Test */, + 57A4D23F1BA13D7A00F7D4B1 /* Release */, + 57A4D2401BA13D7A00F7D4B1 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7DFBED0F1CDB8C9500EE435B /* Build configuration list for PBXNativeTarget "ReactiveSwift-tvOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7DFBED0B1CDB8C9500EE435B /* Debug */, + 7DFBED0C1CDB8C9500EE435B /* Test */, + 7DFBED0D1CDB8C9500EE435B /* Release */, + 7DFBED0E1CDB8C9500EE435B /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A9B3155D1B3940610001CB9C /* Build configuration list for PBXNativeTarget "ReactiveSwift-watchOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A9B315591B3940610001CB9C /* Debug */, + A9B3155A1B3940610001CB9C /* Test */, + A9B3155B1B3940610001CB9C /* Release */, + A9B3155C1B3940610001CB9C /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D04725E419E49ED7006002AA /* Build configuration list for PBXProject "ReactiveSwift" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D04725FE19E49ED7006002AA /* Debug */, + D047264219E4A00B006002AA /* Test */, + D04725FF19E49ED7006002AA /* Release */, + D047263D19E4A008006002AA /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D047260019E49ED7006002AA /* Build configuration list for PBXNativeTarget "ReactiveSwift-macOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D047260119E49ED7006002AA /* Debug */, + D047264319E4A00B006002AA /* Test */, + D047260219E49ED7006002AA /* Release */, + D047263E19E4A008006002AA /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D047260319E49ED7006002AA /* Build configuration list for PBXNativeTarget "ReactiveSwift-macOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D047260419E49ED7006002AA /* Debug */, + D047264419E4A00B006002AA /* Test */, + D047260519E49ED7006002AA /* Release */, + D047263F19E4A008006002AA /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D047261F19E49F82006002AA /* Build configuration list for PBXNativeTarget "ReactiveSwift-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D047262019E49F82006002AA /* Debug */, + D047264519E4A00B006002AA /* Test */, + D047262119E49F82006002AA /* Release */, + D047264019E4A008006002AA /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D047262219E49F82006002AA /* Build configuration list for PBXNativeTarget "ReactiveSwift-iOSTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D047262319E49F82006002AA /* Debug */, + D047264619E4A00B006002AA /* Test */, + D047262419E49F82006002AA /* Release */, + D047264119E4A008006002AA /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D04725E119E49ED7006002AA /* Project object */; +} diff --git a/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..aed1085 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/ReactiveSwift.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Action.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Action.swift new file mode 100644 index 0000000..05c8ebc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Action.swift @@ -0,0 +1,299 @@ +import Dispatch +import Foundation +import Result + +/// `Action` represents a repeatable work like `SignalProducer`. But on top of the +/// isolation of produced `Signal`s from a `SignalProducer`, `Action` provides +/// higher-order features like availability and mutual exclusion. +/// +/// Similar to a produced `Signal` from a `SignalProducer`, each unit of the repreatable +/// work may output zero or more values, and terminate with or without an error at some +/// point. +/// +/// The core of `Action` is the `execute` closure it created with. For every execution +/// attempt with a varying input, if the `Action` is enabled, it would request from the +/// `execute` closure a customized unit of work — represented by a `SignalProducer`. +/// Specifically, the `execute` closure would be supplied with the latest state of +/// `Action` and the external input from `apply()`. +/// +/// `Action` enforces serial execution, and disables the `Action` during the execution. +public final class Action { + private struct ActionState { + var isEnabled: Bool { + return isUserEnabled && !isExecuting + } + + var isUserEnabled: Bool + var isExecuting: Bool + var value: Value + } + + private let execute: (Action, Input) -> SignalProducer> + private let eventsObserver: Signal.Event, NoError>.Observer + private let disabledErrorsObserver: Signal<(), NoError>.Observer + + private let deinitToken: Lifetime.Token + + /// The lifetime of the `Action`. + public let lifetime: Lifetime + + /// A signal of all events generated from all units of work of the `Action`. + /// + /// In other words, this sends every `Event` from every unit of work that the `Action` + /// executes. + public let events: Signal.Event, NoError> + + /// A signal of all values generated from all units of work of the `Action`. + /// + /// In other words, this sends every value from every unit of work that the `Action` + /// executes. + public let values: Signal + + /// A signal of all errors generated from all units of work of the `Action`. + /// + /// In other words, this sends every error from every unit of work that the `Action` + /// executes. + public let errors: Signal + + /// A signal of all failed attempts to start a unit of work of the `Action`. + public let disabledErrors: Signal<(), NoError> + + /// A signal of all completed events generated from applications of the action. + /// + /// In other words, this will send completed events from every signal generated + /// by each SignalProducer returned from apply(). + public let completed: Signal<(), NoError> + + /// Whether the action is currently executing. + public let isExecuting: Property + + /// Whether the action is currently enabled. + public let isEnabled: Property + + /// Initializes an `Action` that would be conditionally enabled depending on its + /// state. + /// + /// When the `Action` is asked to start the execution with an input value, a unit of + /// work — represented by a `SignalProducer` — would be created by invoking + /// `execute` with the latest state and the input value. + /// + /// - note: `Action` guarantees that changes to `state` are observed in a + /// thread-safe way. Thus, the value passed to `isEnabled` will + /// always be identical to the value passed to `execute`, for each + /// application of the action. + /// + /// - note: This initializer should only be used if you need to provide + /// custom input can also influence whether the action is enabled. + /// The various convenience initializers should cover most use cases. + /// + /// - parameters: + /// - state: A property to be the state of the `Action`. + /// - isEnabled: A predicate which determines the availability of the `Action`, + /// given the latest `Action` state. + /// - execute: A closure that produces a unit of work, as `SignalProducer`, to be + /// executed by the `Action`. + public init(state: State, enabledIf isEnabled: @escaping (State.Value) -> Bool, execute: @escaping (State.Value, Input) -> SignalProducer) { + let isUserEnabled = isEnabled + + deinitToken = Lifetime.Token() + lifetime = Lifetime(deinitToken) + + let actionState = MutableProperty(ActionState(isUserEnabled: true, isExecuting: false, value: state.value)) + self.isEnabled = actionState.map { $0.isEnabled } + + // `isExecuting` has its own backing so that when the observer of `isExecuting` + // synchronously affects the action state, the signal of the action state does not + // deadlock due to the recursion. + let isExecuting = MutableProperty(false) + self.isExecuting = Property(capturing: isExecuting) + + // `Action` retains its state property. + lifetime.observeEnded { _ = state } + + (events, eventsObserver) = Signal.Event, NoError>.pipe() + (disabledErrors, disabledErrorsObserver) = Signal<(), NoError>.pipe() + + values = events.filterMap { $0.value } + errors = events.filterMap { $0.error } + completed = events.filterMap { $0.isCompleted ? () : nil } + + let disposable = state.producer.startWithValues { value in + actionState.modify { state in + state.value = value + state.isUserEnabled = isUserEnabled(value) + } + } + + lifetime.observeEnded(disposable.dispose) + + self.execute = { action, input in + return SignalProducer { observer, lifetime in + var notifiesExecutionState = false + + func didSet() { + if notifiesExecutionState { + isExecuting.value = true + } + } + + let latestState: State.Value? = actionState.modify(didSet: didSet) { state in + guard state.isEnabled else { + return nil + } + + state.isExecuting = true + notifiesExecutionState = true + return state.value + } + + guard let state = latestState else { + observer.send(error: .disabled) + action.disabledErrorsObserver.send(value: ()) + return + } + + let interruptHandle = execute(state, input).start { event in + observer.action(event.mapError(ActionError.producerFailed)) + action.eventsObserver.send(value: event) + } + + lifetime.observeEnded { + interruptHandle.dispose() + + actionState.modify(didSet: { isExecuting.value = false }) { state in + state.isExecuting = false + } + } + } + } + } + + /// Initializes an `Action` that would be conditionally enabled. + /// + /// When the `Action` is asked to start the execution with an input value, a unit of + /// work — represented by a `SignalProducer` — would be created by invoking + /// `execute` with the input value. + /// + /// - parameters: + /// - isEnabled: A property which determines the availability of the `Action`. + /// - execute: A closure that produces a unit of work, as `SignalProducer`, to be + /// executed by the `Action`. + public convenience init(enabledIf isEnabled: P, execute: @escaping (Input) -> SignalProducer) where P.Value == Bool { + self.init(state: isEnabled, enabledIf: { $0 }) { _, input in + execute(input) + } + } + + /// Initializes an `Action` that would always be enabled. + /// + /// When the `Action` is asked to start the execution with an input value, a unit of + /// work — represented by a `SignalProducer` — would be created by invoking + /// `execute` with the input value. + /// + /// - parameters: + /// - execute: A closure that produces a unit of work, as `SignalProducer`, to be + /// executed by the `Action`. + public convenience init(execute: @escaping (Input) -> SignalProducer) { + self.init(enabledIf: Property(value: true), execute: execute) + } + + deinit { + eventsObserver.sendCompleted() + disabledErrorsObserver.sendCompleted() + } + + /// Create a `SignalProducer` that would attempt to create and start a unit of work of + /// the `Action`. The `SignalProducer` would forward only events generated by the unit + /// of work it created. + /// + /// If the execution attempt is failed, the producer would fail with + /// `ActionError.disabled`. + /// + /// - parameters: + /// - input: A value to be used to create the unit of work. + /// + /// - returns: A producer that forwards events generated by its started unit of work, + /// or emits `ActionError.disabled` if the execution attempt is failed. + public func apply(_ input: Input) -> SignalProducer> { + return execute(self, input) + } +} + +extension Action: BindingTargetProvider { + public var bindingTarget: BindingTarget { + return BindingTarget(lifetime: lifetime) { [weak self] in self?.apply($0).start() } + } +} + +extension Action where Input == Void { + /// Create a `SignalProducer` that would attempt to create and start a unit of work of + /// the `Action`. The `SignalProducer` would forward only events generated by the unit + /// of work it created. + /// + /// If the execution attempt is failed, the producer would fail with + /// `ActionError.disabled`. + /// + /// - returns: A producer that forwards events generated by its started unit of work, + /// or emits `ActionError.disabled` if the execution attempt is failed. + public func apply() -> SignalProducer> { + return apply(()) + } + + /// Initializes an `Action` that uses a property of optional as its state. + /// + /// When the `Action` is asked to start the execution, a unit of work — represented by + /// a `SignalProducer` — would be created by invoking `execute` with the latest value + /// of the state. + /// + /// If the property holds a `nil`, the `Action` would be disabled until it is not + /// `nil`. + /// + /// - parameters: + /// - state: A property of optional to be the state of the `Action`. + /// - execute: A closure that produces a unit of work, as `SignalProducer`, to + /// be executed by the `Action`. + public convenience init(state: P, execute: @escaping (T) -> SignalProducer) where P.Value == T? { + self.init(state: state, enabledIf: { $0 != nil }) { state, _ in + execute(state!) + } + } + + /// Initializes an `Action` that uses a property as its state. + /// + /// When the `Action` is asked to start the execution, a unit of work — represented by + /// a `SignalProducer` — would be created by invoking `execute` with the latest value + /// of the state. + /// + /// - parameters: + /// - state: A property to be the state of the `Action`. + /// - execute: A closure that produces a unit of work, as `SignalProducer`, to + /// be executed by the `Action`. + public convenience init(state: P, execute: @escaping (T) -> SignalProducer) where P.Value == T { + self.init(state: state.map(Optional.some), execute: execute) + } +} + +/// `ActionError` represents the error that could be emitted by a unit of work of a +/// certain `Action`. +public enum ActionError: Swift.Error { + /// The execution attempt was failed, since the `Action` was disabled. + case disabled + + /// The unit of work emitted an error. + case producerFailed(Error) +} + +extension ActionError where Error: Equatable { + public static func == (lhs: ActionError, rhs: ActionError) -> Bool { + switch (lhs, rhs) { + case (.disabled, .disabled): + return true + + case let (.producerFailed(left), .producerFailed(right)): + return left == right + + default: + return false + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Atomic.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Atomic.swift new file mode 100644 index 0000000..0f75d19 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Atomic.swift @@ -0,0 +1,289 @@ +// +// Atomic.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-06-10. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +import Foundation +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) +import MachO +#endif + +/// A simple, generic lock-free finite state machine. +/// +/// - warning: `deinitialize` must be called to dispose of the consumed memory. +internal struct UnsafeAtomicState where State.RawValue == Int32 { + internal typealias Transition = (expected: State, next: State) +#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + private let value: UnsafeMutablePointer + + /// Create a finite state machine with the specified initial state. + /// + /// - parameters: + /// - initial: The desired initial state. + internal init(_ initial: State) { + value = UnsafeMutablePointer.allocate(capacity: 1) + value.initialize(to: initial.rawValue) + } + + /// Deinitialize the finite state machine. + internal func deinitialize() { + value.deinitialize() + value.deallocate(capacity: 1) + } + + /// Compare the current state with the specified state. + /// + /// - parameters: + /// - expected: The expected state. + /// + /// - returns: `true` if the current state matches the expected state. + /// `false` otherwise. + internal func `is`(_ expected: State) -> Bool { + return OSAtomicCompareAndSwap32Barrier(expected.rawValue, + expected.rawValue, + value) + } + + /// Try to transition from the expected current state to the specified next + /// state. + /// + /// - parameters: + /// - expected: The expected state. + /// - next: The state to transition to. + /// + /// - returns: `true` if the transition succeeds. `false` otherwise. + internal func tryTransition(from expected: State, to next: State) -> Bool { + return OSAtomicCompareAndSwap32Barrier(expected.rawValue, + next.rawValue, + value) + } +#else + private let value: Atomic + + /// Create a finite state machine with the specified initial state. + /// + /// - parameters: + /// - initial: The desired initial state. + internal init(_ initial: State) { + value = Atomic(initial.rawValue) + } + + /// Deinitialize the finite state machine. + internal func deinitialize() {} + + /// Compare the current state with the specified state. + /// + /// - parameters: + /// - expected: The expected state. + /// + /// - returns: `true` if the current state matches the expected state. + /// `false` otherwise. + internal func `is`(_ expected: State) -> Bool { + return value.modify { $0 == expected.rawValue } + } + + /// Try to transition from the expected current state to the specified next + /// state. + /// + /// - parameters: + /// - expected: The expected state. + /// + /// - returns: `true` if the transition succeeds. `false` otherwise. + internal func tryTransition(from expected: State, to next: State) -> Bool { + return value.modify { value in + if value == expected.rawValue { + value = next.rawValue + return true + } + return false + } + } +#endif +} + +/// `Lock` exposes `os_unfair_lock` on supported platforms, with pthread mutex as the +// fallback. +internal class Lock { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + @available(iOS 10.0, *) + @available(macOS 10.12, *) + @available(tvOS 10.0, *) + @available(watchOS 3.0, *) + internal final class UnfairLock: Lock { + private let _lock: os_unfair_lock_t + + override init() { + _lock = .allocate(capacity: 1) + _lock.initialize(to: os_unfair_lock()) + super.init() + } + + override func lock() { + os_unfair_lock_lock(_lock) + } + + override func unlock() { + os_unfair_lock_unlock(_lock) + } + + override func `try`() -> Bool { + return os_unfair_lock_trylock(_lock) + } + + deinit { + _lock.deinitialize() + _lock.deallocate(capacity: 1) + } + } + #endif + + internal final class PthreadLock: Lock { + private let _lock: UnsafeMutablePointer + + init(recursive: Bool = false) { + _lock = .allocate(capacity: 1) + _lock.initialize(to: pthread_mutex_t()) + + let attr = UnsafeMutablePointer.allocate(capacity: 1) + attr.initialize(to: pthread_mutexattr_t()) + pthread_mutexattr_init(attr) + + defer { + pthread_mutexattr_destroy(attr) + attr.deinitialize() + attr.deallocate(capacity: 1) + } + + #if DEBUG + pthread_mutexattr_settype(attr, Int32(recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_ERRORCHECK)) + #else + pthread_mutexattr_settype(attr, Int32(recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL)) + #endif + + let status = pthread_mutex_init(_lock, attr) + assert(status == 0, "Unexpected pthread mutex error code: \(status)") + + super.init() + } + + override func lock() { + let status = pthread_mutex_lock(_lock) + assert(status == 0, "Unexpected pthread mutex error code: \(status)") + } + + override func unlock() { + let status = pthread_mutex_unlock(_lock) + assert(status == 0, "Unexpected pthread mutex error code: \(status)") + } + + override func `try`() -> Bool { + let status = pthread_mutex_trylock(_lock) + switch status { + case 0: + return true + case EBUSY: + return false + default: + assertionFailure("Unexpected pthread mutex error code: \(status)") + return false + } + } + + deinit { + let status = pthread_mutex_destroy(_lock) + assert(status == 0, "Unexpected pthread mutex error code: \(status)") + + _lock.deinitialize() + _lock.deallocate(capacity: 1) + } + } + + static func make() -> Lock { + #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) + if #available(*, iOS 10.0, macOS 10.12, tvOS 10.0, watchOS 3.0) { + return UnfairLock() + } + #endif + + return PthreadLock() + } + + private init() {} + + func lock() { fatalError() } + func unlock() { fatalError() } + func `try`() -> Bool { fatalError() } +} + +/// An atomic variable. +public final class Atomic { + private let lock: Lock + private var _value: Value + + /// Atomically get or set the value of the variable. + public var value: Value { + get { + return withValue { $0 } + } + + set(newValue) { + swap(newValue) + } + } + + /// Initialize the variable with the given initial value. + /// + /// - parameters: + /// - value: Initial value for `self`. + public init(_ value: Value) { + _value = value + lock = Lock.make() + } + + /// Atomically modifies the variable. + /// + /// - parameters: + /// - action: A closure that takes the current value. + /// + /// - returns: The result of the action. + @discardableResult + public func modify(_ action: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + + return try action(&_value) + } + + /// Atomically perform an arbitrary action using the current value of the + /// variable. + /// + /// - parameters: + /// - action: A closure that takes the current value. + /// + /// - returns: The result of the action. + @discardableResult + public func withValue(_ action: (Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + + return try action(_value) + } + + /// Atomically replace the contents of the variable. + /// + /// - parameters: + /// - newValue: A new value for the variable. + /// + /// - returns: The old value. + @discardableResult + public func swap(_ newValue: Value) -> Value { + return modify { (value: inout Value) in + let oldValue = value + value = newValue + return oldValue + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Bag.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Bag.swift new file mode 100644 index 0000000..882e2d0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Bag.swift @@ -0,0 +1,102 @@ +// +// Bag.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-07-10. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +/// An unordered, non-unique collection of values of type `Element`. +public struct Bag { + /// A uniquely identifying token for removing a value that was inserted into a + /// Bag. + public struct Token { + fileprivate let value: UInt64 + } + + fileprivate var elements: ContiguousArray = [] + fileprivate var tokens: ContiguousArray = [] + + private var nextToken: Token = Token(value: 0) + + public init() {} + + /// Insert the given value into `self`, and return a token that can + /// later be passed to `remove(using:)`. + /// + /// - parameters: + /// - value: A value that will be inserted. + @discardableResult + public mutating func insert(_ value: Element) -> Token { + let token = nextToken + + // Practically speaking, this would overflow only if we have 101% uptime and we + // manage to call `insert(_:)` every 1 ns for 500+ years non-stop. + nextToken = Token(value: token.value + 1) + + elements.append(value) + tokens.append(token.value) + + return token + } + + /// Remove a value, given the token returned from `insert()`. + /// + /// - note: If the value has already been removed, nothing happens. + /// + /// - parameters: + /// - token: A token returned from a call to `insert()`. + @discardableResult + public mutating func remove(using token: Token) -> Element? { + for i in (elements.startIndex ..< elements.endIndex).reversed() { + if tokens[i] == token.value { + tokens.remove(at: i) + return elements.remove(at: i) + } + } + + return nil + } +} + +extension Bag: RandomAccessCollection { + public var startIndex: Int { + return elements.startIndex + } + + public var endIndex: Int { + return elements.endIndex + } + + public subscript(index: Int) -> Element { + return elements[index] + } + + public func makeIterator() -> Iterator { + return Iterator(elements) + } + + /// An iterator of `Bag`. + public struct Iterator: IteratorProtocol { + private let base: ContiguousArray + private var nextIndex: Int + private let endIndex: Int + + fileprivate init(_ base: ContiguousArray) { + self.base = base + nextIndex = base.startIndex + endIndex = base.endIndex + } + + public mutating func next() -> Element? { + let currentIndex = nextIndex + + if currentIndex < endIndex { + nextIndex = currentIndex + 1 + return base[currentIndex] + } + + return nil + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Deprecations+Removals.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Deprecations+Removals.swift new file mode 100644 index 0000000..2b96010 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Deprecations+Removals.swift @@ -0,0 +1,195 @@ +import Foundation +import Dispatch +import Result + +// MARK: Unavailable methods in ReactiveSwift 2.0. +extension AnyDisposable { + @available(*, unavailable, renamed:"init(_:)") + public convenience init(action: @escaping () -> Void) { fatalError() } +} + +extension Signal { + @available(*, unavailable, renamed:"promoteError") + public func promoteErrors(_: F.Type) -> Signal { fatalError() } +} + +extension SignalProducer { + @available(*, unavailable, renamed:"promoteError") + public func promoteErrors(_: F.Type) -> SignalProducer { fatalError() } +} + +extension Lifetime { + @available(*, unavailable, renamed:"hasEnded") + public var isDisposed: Bool { fatalError() } + + @discardableResult + @available(*, unavailable, renamed:"observeEnded(_:)") + public func add(_ action: () -> Void) -> Disposable? { fatalError() } + + @discardableResult + @available(*, unavailable, message:"Use `observeEnded(_:)` instead.") + public static func += (left: Lifetime, right: () -> Void) -> Disposable? { fatalError() } + + @discardableResult + @available(*, deprecated, message:"Use `observeEnded(_:)` with a method reference to `dispose()` instead. This method is subject to removal in a future release.") + public func add(_ d: Disposable?) -> Disposable? { + return d.flatMap { observeEnded($0.dispose) } + } + + @discardableResult + @available(*, deprecated, message:"Use `observeEnded(_:)` with a method reference to `dispose()` instead. This operator overload is subject to removal in a future release.") + public static func += (left: Lifetime, right: Disposable?) -> Disposable? { + return right.flatMap { left.observeEnded($0.dispose) } + } +} + +extension SignalProducer { + @available(*, unavailable, renamed:"init(_:)") + public static func attempt(_ operation: @escaping () -> Result) -> SignalProducer { fatalError() } +} + +extension SignalProducer where Error == AnyError { + @available(*, unavailable, renamed:"init(_:)") + public static func attempt(_ operation: @escaping () throws -> Value) -> SignalProducer { fatalError() } +} + +extension PropertyProtocol { + @available(*, unavailable, renamed:"flatMap(_:_:)") + public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> P) -> Property { fatalError() } +} + +extension Signal { + @available(*, unavailable, renamed:"flatMap(_:_:)") + public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> Inner) -> Signal where Error == Inner.Error { fatalError() } + + @available(*, unavailable, renamed:"flatMap(_:_:)") + public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> Inner) -> Signal where Inner.Error == NoError { fatalError() } +} + +extension Signal where Error == NoError { + @available(*, unavailable, renamed:"flatMap(_:_:)") + public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> Inner) -> Signal where Error == Inner.Error { fatalError() } + + @available(*, unavailable, renamed:"flatMap(_:_:)") + public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> Inner) -> Signal { fatalError() } +} + +extension SignalProducer { + @available(*, unavailable, renamed:"flatMap(_:_:)") + public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> Inner) -> SignalProducer where Error == Inner.Error { fatalError() } + + @available(*, unavailable, renamed:"flatMap(_:_:)") + public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> Inner) -> SignalProducer where Inner.Error == NoError { fatalError() } +} + +extension SignalProducer where Error == NoError { + @available(*, unavailable, renamed:"flatMap(_:_:)") + public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> Inner) -> SignalProducer where Error == Inner.Error { fatalError() } + + @available(*, unavailable, renamed:"flatMap(_:_:)") + public func flatMap(_ strategy: FlattenStrategy, transform: @escaping (Value) -> Inner) -> SignalProducer { fatalError() } +} + +extension ComposableMutablePropertyProtocol { + @available(*, unavailable, renamed:"withValue(_:)") + public func withValue(action: (Value) throws -> Result) rethrows -> Result { fatalError() } +} + +extension SignalProducer { + @available(*, unavailable, renamed:"attempt(_:)") + public func attempt(action: @escaping (Value) -> Result<(), Error>) -> SignalProducer { fatalError() } +} + +extension CompositeDisposable { + @available(*, unavailable, message:"Use `Disposable?` instead.") + public typealias DisposableHandle = Disposable? +} + +extension Optional where Wrapped == Disposable { + @available(*, unavailable, renamed:"dispose") + public func remove() { fatalError() } +} + +@available(*, unavailable, renamed:"SignalProducer.timer") +public func timer(interval: DispatchTimeInterval, on scheduler: DateScheduler) -> SignalProducer { fatalError() } + +@available(*, unavailable, renamed:"SignalProducer.timer") +public func timer(interval: DispatchTimeInterval, on scheduler: DateScheduler, leeway: DispatchTimeInterval) -> SignalProducer { fatalError() } + +// MARK: Obsolete types in ReactiveSwift 2.0. +@available(*, unavailable, renamed:"AnyDisposable") +public typealias SimpleDisposable = AnyDisposable + +@available(*, unavailable, renamed:"AnyDisposable") +public typealias ActionDisposable = AnyDisposable + +@available(*, unavailable, renamed:"Signal.Event") +public typealias Event = Signal.Event + +@available(*, unavailable, renamed:"Signal.Observer") +public typealias Observer = Signal.Observer + +extension Action { + @available(*, unavailable, renamed:"init(state:enabledIf:execute:)") + public convenience init(state property: State, enabledIf isEnabled: @escaping (State.Value) -> Bool, _ execute: @escaping (State.Value, Input) -> SignalProducer) { fatalError() } + + @available(*, unavailable, renamed:"init(enabledIf:execute:)") + public convenience init(enabledIf property: P, _ execute: @escaping (Input) -> SignalProducer) where P.Value == Bool { fatalError() } + + @available(*, unavailable, renamed:"init(execute:)") + public convenience init(_ execute: @escaping (Input) -> SignalProducer) { fatalError() } +} + +extension Action where Input == Void { + @available(*, unavailable, renamed:"init(state:execute:)") + public convenience init(input: P, _ execute: @escaping (T) -> SignalProducer) where P.Value == T? { fatalError() } + + @available(*, unavailable, renamed:"init(state:execute:)") + public convenience init(input: P, _ execute: @escaping (T) -> SignalProducer) where P.Value == T { fatalError() } +} + +@available(*, unavailable, renamed:"Bag.Token") +public typealias RemovalToken = Bag.Token + +@available(*, unavailable, message: "This protocol has been removed. Constrain `Action` directly instead.") +public protocol ActionProtocol {} + +@available(*, unavailable, message: "The protocol has been removed. Constrain `Observer` directly instead.") +public protocol ObserverProtocol {} + +@available(*, unavailable, message:"The protocol has been replaced by `BindingTargetProvider`.") +public protocol BindingTargetProtocol {} + +@available(*, unavailable, message:"The protocol has been removed. Constrain `Atomic` directly instead.") +public protocol AtomicProtocol {} + +// MARK: Deprecated types in ReactiveSwift 1.x. +extension Signal where Value == Bool { + @available(*, unavailable, renamed: "negate()") + public var negated: Signal { + return negate() + } +} + +extension SignalProducer where Value == Bool { + @available(*, unavailable, renamed: "negate()") + public var negated: SignalProducer { + return negate() + } +} + +extension PropertyProtocol where Value == Bool { + @available(*, unavailable, renamed: "negate()") + public var negated: Property { + return negate() + } +} + +@available(*, unavailable, renamed:"Scheduler") +public typealias SchedulerProtocol = Scheduler + +@available(*, unavailable, renamed:"DateScheduler") +public typealias DateSchedulerProtocol = DateScheduler + +@available(*, unavailable, renamed:"BindingSource") +public typealias BindingSourceProtocol = BindingSource diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Disposable.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Disposable.swift new file mode 100644 index 0000000..4b5c36e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Disposable.swift @@ -0,0 +1,364 @@ +// +// Disposable.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-06-02. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +/// Represents something that can be “disposed”, usually associated with freeing +/// resources or canceling work. +public protocol Disposable: class { + /// Whether this disposable has been disposed already. + var isDisposed: Bool { get } + + /// Disposing of the resources represented by `self`. If `self` has already + /// been disposed of, it does nothing. + /// + /// - note: Implementations must issue a memory barrier. + func dispose() +} + +/// Represents the state of a disposable. +private enum DisposableState: Int32 { + /// The disposable is active. + case active + + /// The disposable has been disposed. + case disposed +} + +extension UnsafeAtomicState where State == DisposableState { + /// Try to transition from `active` to `disposed`. + /// + /// - returns: `true` if the transition succeeds. `false` otherwise. + @inline(__always) + fileprivate func tryDispose() -> Bool { + return tryTransition(from: .active, to: .disposed) + } +} + +/// A type-erased disposable that forwards operations to an underlying disposable. +public final class AnyDisposable: Disposable { + private final class ActionDisposable: Disposable { + let state: UnsafeAtomicState + var action: (() -> Void)? + + var isDisposed: Bool { + return state.is(.disposed) + } + + init(_ action: (() -> Void)?) { + self.state = UnsafeAtomicState(.active) + self.action = action + } + + deinit { + state.deinitialize() + } + + func dispose() { + if state.tryDispose() { + action?() + action = nil + } + } + } + + private let base: Disposable + + public var isDisposed: Bool { + return base.isDisposed + } + + /// Create a disposable which runs the given action upon disposal. + /// + /// - parameters: + /// - action: A closure to run when calling `dispose()`. + public init(_ action: @escaping () -> Void) { + base = ActionDisposable(action) + } + + /// Create a disposable. + public init() { + base = ActionDisposable(nil) + } + + /// Create a disposable which wraps the given disposable. + /// + /// - parameters: + /// - disposable: The disposable to be wrapped. + public init(_ disposable: Disposable) { + base = disposable + } + + public func dispose() { + base.dispose() + } +} + +/// A disposable that will dispose of any number of other disposables. +public final class CompositeDisposable: Disposable { + private let disposables: Atomic?> + private var state: UnsafeAtomicState + + public var isDisposed: Bool { + return state.is(.disposed) + } + + /// Initialize a `CompositeDisposable` containing the given sequence of + /// disposables. + /// + /// - parameters: + /// - disposables: A collection of objects conforming to the `Disposable` + /// protocol + public init(_ disposables: S) + where S.Iterator.Element == Disposable + { + var bag: Bag = Bag() + + for disposable in disposables { + bag.insert(disposable) + } + + self.disposables = Atomic(bag) + self.state = UnsafeAtomicState(DisposableState.active) + } + + /// Initialize a `CompositeDisposable` containing the given sequence of + /// disposables. + /// + /// - parameters: + /// - disposables: A collection of objects conforming to the `Disposable` + /// protocol + public convenience init(_ disposables: S) + where S.Iterator.Element == Disposable? + { + self.init(disposables.flatMap { $0 }) + } + + /// Initializes an empty `CompositeDisposable`. + public convenience init() { + self.init([Disposable]()) + } + + public func dispose() { + if state.tryDispose() { + if let ds = disposables.swap(nil) { + for d in ds { + d.dispose() + } + } + } + } + + /// Add the given disposable to the composite. + /// + /// - parameters: + /// - disposable: A disposable. + /// + /// - returns: A disposable to remove `disposable` from the composite. `nil` if the + /// composite has been disposed of, `disposable` has been disposed of, or + /// `disposable` is `nil`. + @discardableResult + public func add(_ disposable: Disposable?) -> Disposable? { + guard let d = disposable, !d.isDisposed, !isDisposed else { + disposable?.dispose() + return nil + } + + return disposables.modify { disposables in + guard disposables != nil else { return nil } + + let token = disposables!.insert(d) + return AnyDisposable { [weak self] in + self?.disposables.modify { + $0?.remove(using: token) + } + } + } + } + + /// Add the given action to the composite. + /// + /// - parameters: + /// - action: A closure to be invoked when the composite is disposed of. + /// + /// - returns: A disposable to remove `disposable` from the composite. `nil` if the + /// composite has been disposed of, `disposable` has been disposed of, or + /// `disposable` is `nil`. + @discardableResult + public func add(_ action: @escaping () -> Void) -> Disposable? { + return add(AnyDisposable(action)) + } + + deinit { + state.deinitialize() + } + + /// Adds the right-hand-side disposable to the left-hand-side + /// `CompositeDisposable`. + /// + /// ```` + /// disposable += producer + /// .filter { ... } + /// .map { ... } + /// .start(observer) + /// ```` + /// + /// - parameters: + /// - lhs: Disposable to add to. + /// - rhs: Disposable to add. + /// + /// - returns: An instance of `DisposableHandle` that can be used to opaquely + /// remove the disposable later (if desired). + @discardableResult + public static func +=(lhs: CompositeDisposable, rhs: Disposable?) -> Disposable? { + return lhs.add(rhs) + } + + /// Adds the right-hand-side `ActionDisposable` to the left-hand-side + /// `CompositeDisposable`. + /// + /// ```` + /// disposable += { ... } + /// ```` + /// + /// - parameters: + /// - lhs: Disposable to add to. + /// - rhs: Closure to add as a disposable. + /// + /// - returns: An instance of `DisposableHandle` that can be used to opaquely + /// remove the disposable later (if desired). + @discardableResult + public static func +=(lhs: CompositeDisposable, rhs: @escaping () -> ()) -> Disposable? { + return lhs.add(rhs) + } +} + +/// A disposable that, upon deinitialization, will automatically dispose of +/// its inner disposable. +public final class ScopedDisposable: Disposable { + /// The disposable which will be disposed when the ScopedDisposable + /// deinitializes. + public let inner: Inner + + public var isDisposed: Bool { + return inner.isDisposed + } + + /// Initialize the receiver to dispose of the argument upon + /// deinitialization. + /// + /// - parameters: + /// - disposable: A disposable to dispose of when deinitializing. + public init(_ disposable: Inner) { + inner = disposable + } + + deinit { + dispose() + } + + public func dispose() { + return inner.dispose() + } +} + +extension ScopedDisposable where Inner == AnyDisposable { + /// Initialize the receiver to dispose of the argument upon + /// deinitialization. + /// + /// - parameters: + /// - disposable: A disposable to dispose of when deinitializing, which + /// will be wrapped in an `AnyDisposable`. + public convenience init(_ disposable: Disposable) { + self.init(Inner(disposable)) + } +} + +extension ScopedDisposable where Inner == CompositeDisposable { + /// Adds the right-hand-side disposable to the left-hand-side + /// `ScopedDisposable`. + /// + /// ```` + /// disposable += { ... } + /// ```` + /// + /// - parameters: + /// - lhs: Disposable to add to. + /// - rhs: Disposable to add. + /// + /// - returns: An instance of `DisposableHandle` that can be used to opaquely + /// remove the disposable later (if desired). + @discardableResult + public static func +=(lhs: ScopedDisposable, rhs: Disposable?) -> Disposable? { + return lhs.inner.add(rhs) + } + + /// Adds the right-hand-side disposable to the left-hand-side + /// `ScopedDisposable`. + /// + /// ```` + /// disposable += { ... } + /// ```` + /// + /// - parameters: + /// - lhs: Disposable to add to. + /// - rhs: Closure to add as a disposable. + /// + /// - returns: An instance of `DisposableHandle` that can be used to opaquely + /// remove the disposable later (if desired). + @discardableResult + public static func +=(lhs: ScopedDisposable, rhs: @escaping () -> ()) -> Disposable? { + return lhs.inner.add(rhs) + } +} + +/// A disposable that disposes of its wrapped disposable, and allows its +/// wrapped disposable to be replaced. +public final class SerialDisposable: Disposable { + private let _inner: Atomic + private var state: UnsafeAtomicState + + public var isDisposed: Bool { + return state.is(.disposed) + } + + /// The current inner disposable to dispose of. + /// + /// Whenever this property is set (even to the same value!), the previous + /// disposable is automatically disposed. + public var inner: Disposable? { + get { + return _inner.value + } + + set(d) { + _inner.swap(d)?.dispose() + if let d = d, isDisposed { + d.dispose() + } + } + } + + /// Initializes the receiver to dispose of the argument when the + /// SerialDisposable is disposed. + /// + /// - parameters: + /// - disposable: Optional disposable. + public init(_ disposable: Disposable? = nil) { + self._inner = Atomic(disposable) + self.state = UnsafeAtomicState(DisposableState.active) + } + + public func dispose() { + if state.tryDispose() { + _inner.swap(nil)?.dispose() + } + } + + deinit { + state.deinitialize() + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Event.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Event.swift new file mode 100644 index 0000000..32f604d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Event.swift @@ -0,0 +1,180 @@ +// +// Event.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2015-01-16. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +extension Signal { + /// Represents a signal event. + /// + /// Signals must conform to the grammar: + /// `value* (failed | completed | interrupted)?` + public enum Event { + /// A value provided by the signal. + case value(Value) + + /// The signal terminated because of an error. No further events will be + /// received. + case failed(Error) + + /// The signal successfully terminated. No further events will be received. + case completed + + /// Event production on the signal has been interrupted. No further events + /// will be received. + /// + /// - important: This event does not signify the successful or failed + /// completion of the signal. + case interrupted + + /// Whether this event is a completed event. + public var isCompleted: Bool { + switch self { + case .completed: + return true + + case .value, .failed, .interrupted: + return false + } + } + + /// Whether this event indicates signal termination (i.e., that no further + /// events will be received). + public var isTerminating: Bool { + switch self { + case .value: + return false + + case .failed, .completed, .interrupted: + return true + } + } + + /// Lift the given closure over the event's value. + /// + /// - important: The closure is called only on `value` type events. + /// + /// - parameters: + /// - f: A closure that accepts a value and returns a new value + /// + /// - returns: An event with function applied to a value in case `self` is a + /// `value` type of event. + public func map(_ f: (Value) -> U) -> Signal.Event { + switch self { + case let .value(value): + return .value(f(value)) + + case let .failed(error): + return .failed(error) + + case .completed: + return .completed + + case .interrupted: + return .interrupted + } + } + + /// Lift the given closure over the event's error. + /// + /// - important: The closure is called only on failed type event. + /// + /// - parameters: + /// - f: A closure that accepts an error object and returns + /// a new error object + /// + /// - returns: An event with function applied to an error object in case + /// `self` is a `.Failed` type of event. + public func mapError(_ f: (Error) -> F) -> Signal.Event { + switch self { + case let .value(value): + return .value(value) + + case let .failed(error): + return .failed(f(error)) + + case .completed: + return .completed + + case .interrupted: + return .interrupted + } + } + + /// Unwrap the contained `value` value. + public var value: Value? { + if case let .value(value) = self { + return value + } else { + return nil + } + } + + /// Unwrap the contained `Error` value. + public var error: Error? { + if case let .failed(error) = self { + return error + } else { + return nil + } + } + } +} + +extension Signal.Event where Value: Equatable, Error: Equatable { + public static func == (lhs: Signal.Event, rhs: Signal.Event) -> Bool { + switch (lhs, rhs) { + case let (.value(left), .value(right)): + return left == right + + case let (.failed(left), .failed(right)): + return left == right + + case (.completed, .completed): + return true + + case (.interrupted, .interrupted): + return true + + default: + return false + } + } +} + +extension Signal.Event: CustomStringConvertible { + public var description: String { + switch self { + case let .value(value): + return "VALUE \(value)" + + case let .failed(error): + return "FAILED \(error)" + + case .completed: + return "COMPLETED" + + case .interrupted: + return "INTERRUPTED" + } + } +} + +/// Event protocol for constraining signal extensions +public protocol EventProtocol { + /// The value type of an event. + associatedtype Value + /// The error type of an event. If errors aren't possible then `NoError` can + /// be used. + associatedtype Error: Swift.Error + /// Extracts the event from the receiver. + var event: Signal.Event { get } +} + +extension Signal.Event: EventProtocol { + public var event: Signal.Event { + return self + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/EventLogger.swift b/Carthage/Checkouts/ReactiveSwift/Sources/EventLogger.swift new file mode 100644 index 0000000..263101c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/EventLogger.swift @@ -0,0 +1,139 @@ +// +// EventLogger.swift +// ReactiveSwift +// +// Created by Rui Peres on 30/04/2016. +// Copyright © 2016 GitHub. All rights reserved. +// + +import Foundation + +/// A namespace for logging event types. +public enum LoggingEvent { + public enum Signal: String { + case value, completed, failed, terminated, disposed, interrupted + + public static let allEvents: Set = [ + .value, .completed, .failed, .terminated, .disposed, .interrupted, + ] + } + + public enum SignalProducer: String { + case starting, started, value, completed, failed, terminated, disposed, interrupted + + public static let allEvents: Set = [ + .starting, .started, .value, .completed, .failed, .terminated, .disposed, .interrupted, + ] + } +} + +public func defaultEventLog(identifier: String, event: String, fileName: String, functionName: String, lineNumber: Int) { + print("[\(identifier)] \(event) fileName: \(fileName), functionName: \(functionName), lineNumber: \(lineNumber)") +} + +/// A type that represents an event logging function. +/// Signature is: +/// - identifier +/// - event +/// - fileName +/// - functionName +/// - lineNumber +public typealias EventLogger = ( + _ identifier: String, + _ event: String, + _ fileName: String, + _ functionName: String, + _ lineNumber: Int +) -> Void + +extension Signal { + /// Logs all events that the receiver sends. By default, it will print to + /// the standard output. + /// + /// - parameters: + /// - identifier: a string to identify the Signal firing events. + /// - events: Types of events to log. + /// - fileName: Name of the file containing the code which fired the + /// event. + /// - functionName: Function where event was fired. + /// - lineNumber: Line number where event was fired. + /// - logger: Logger that logs the events. + /// + /// - returns: Signal that, when observed, logs the fired events. + public func logEvents(identifier: String = "", events: Set = LoggingEvent.Signal.allEvents, fileName: String = #file, functionName: String = #function, lineNumber: Int = #line, logger: @escaping EventLogger = defaultEventLog) -> Signal { + func log(_ event: LoggingEvent.Signal) -> ((T) -> Void)? { + return event.logIfNeeded(events: events) { event in + logger(identifier, event, fileName, functionName, lineNumber) + } + } + + return self.on( + failed: log(.failed), + completed: log(.completed) as ((()) -> Void)?, + interrupted: log(.interrupted) as ((()) -> Void)?, + terminated: log(.terminated) as ((()) -> Void)?, + disposed: log(.disposed) as ((()) -> Void)?, + value: log(.value) + ) + } +} + +extension SignalProducer { + /// Logs all events that the receiver sends. By default, it will print to + /// the standard output. + /// + /// - parameters: + /// - identifier: a string to identify the SignalProducer firing events. + /// - events: Types of events to log. + /// - fileName: Name of the file containing the code which fired the + /// event. + /// - functionName: Function where event was fired. + /// - lineNumber: Line number where event was fired. + /// - logger: Logger that logs the events. + /// + /// - returns: Signal producer that, when started, logs the fired events. + public func logEvents(identifier: String = "", + events: Set = LoggingEvent.SignalProducer.allEvents, + fileName: String = #file, + functionName: String = #function, + lineNumber: Int = #line, + logger: @escaping EventLogger = defaultEventLog + ) -> SignalProducer { + func log(_ event: LoggingEvent.SignalProducer) -> ((T) -> Void)? { + return event.logIfNeeded(events: events) { event in + logger(identifier, event, fileName, functionName, lineNumber) + } + } + + return self.on( + starting: log(.starting) as ((()) -> Void)?, + started: log(.started) as ((()) -> Void)?, + failed: log(.failed), + completed: log(.completed) as ((()) -> Void)?, + interrupted: log(.interrupted) as ((()) -> Void)?, + terminated: log(.terminated) as ((()) -> Void)?, + disposed: log(.disposed) as ((()) -> Void)?, + value: log(.value) + ) + } +} + +private protocol LoggingEventProtocol: Hashable, RawRepresentable {} +extension LoggingEvent.Signal: LoggingEventProtocol {} +extension LoggingEvent.SignalProducer: LoggingEventProtocol {} + +private extension LoggingEventProtocol { + func logIfNeeded(events: Set, logger: @escaping (String) -> Void) -> ((T) -> Void)? { + guard events.contains(self) else { + return nil + } + + return { value in + if value is Void { + logger("\(self.rawValue)") + } else { + logger("\(self.rawValue) \(value)") + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Flatten.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Flatten.swift new file mode 100644 index 0000000..9a3e8a6 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Flatten.swift @@ -0,0 +1,921 @@ +// +// Flatten.swift +// ReactiveSwift +// +// Created by Neil Pankey on 11/30/15. +// Copyright © 2015 GitHub. All rights reserved. +// + +import enum Result.NoError + +/// Describes how multiple producers should be joined together. +public enum FlattenStrategy: Equatable { + /// The producers should be merged, so that any value received on any of the + /// input producers will be forwarded immediately to the output producer. + /// + /// The resulting producer will complete only when all inputs have + /// completed. + public static let merge = FlattenStrategy.concurrent(limit: .max) + + /// The producers should be concatenated, so that their values are sent in + /// the order of the producers themselves. + /// + /// The resulting producer will complete only when all inputs have + /// completed. + public static let concat = FlattenStrategy.concurrent(limit: 1) + + /// The producers should be merged, but only up to the given limit at any + /// point of time, so that any value received on any of the input producers + /// will be forwarded immediately to the output producer. + /// + /// When the number of active producers reaches the limit, subsequent + /// producers are queued. + /// + /// The resulting producer will complete only when all inputs have + /// completed. + /// + /// - precondition: `limit > 0`. + case concurrent(limit: UInt) + + /// Only the events from the latest input producer should be considered for + /// the output. Any producers received before that point will be disposed + /// of. + /// + /// The resulting producer will complete only when the producer-of-producers + /// and the latest producer has completed. + case latest + + /// Only the events from the "first input producer to send an event" (winning producer) + /// should be considered for the output. + /// Any other producers that already started (but not sending an event yet) + /// will be disposed. + /// + /// The resulting producer will complete when: + /// 1. The producer-of-producers and the first "alive" producer has completed. + /// 2. The producer-of-producers has completed without inner producer being "alive". + case race + + public static func ==(left: FlattenStrategy, right: FlattenStrategy) -> Bool { + switch (left, right) { + case (.latest, .latest): + return true + + case (.concurrent(let leftLimit), .concurrent(let rightLimit)): + return leftLimit == rightLimit + + default: + return false + } + } +} + +extension Signal where Value: SignalProducerConvertible, Error == Value.Error { + /// Flattens the inner producers sent upon `signal` (into a single signal of + /// values), according to the semantics of the given strategy. + /// + /// - note: If `signal` or an active inner producer fails, the returned + /// signal will forward that failure immediately. + /// + /// - warning: `interrupted` events on inner producers will be treated like + /// `completed` events on inner producers. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + public func flatten(_ strategy: FlattenStrategy) -> Signal { + switch strategy { + case .concurrent(let limit): + return self.concurrent(limit: limit) + + case .latest: + return self.switchToLatest() + + case .race: + return self.race() + } + } +} + +extension Signal where Value: SignalProducerConvertible, Error == NoError { + /// Flattens the inner producers sent upon `signal` (into a single signal of + /// values), according to the semantics of the given strategy. + /// + /// - note: If `signal` or an active inner producer fails, the returned + /// signal will forward that failure immediately. + /// + /// - warning: `interrupted` events on inner producers will be treated like + /// `completed` events on inner producers. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + public func flatten(_ strategy: FlattenStrategy) -> Signal { + return self + .promoteError(Value.Error.self) + .flatten(strategy) + } +} + +extension Signal where Value: SignalProducerConvertible, Error == NoError, Value.Error == NoError { + /// Flattens the inner producers sent upon `signal` (into a single signal of + /// values), according to the semantics of the given strategy. + /// + /// - warning: `interrupted` events on inner producers will be treated like + /// `completed` events on inner producers. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + public func flatten(_ strategy: FlattenStrategy) -> Signal { + switch strategy { + case .concurrent(let limit): + return self.concurrent(limit: limit) + + case .latest: + return self.switchToLatest() + + case .race: + return self.race() + } + } +} + +extension Signal where Value: SignalProducerConvertible, Value.Error == NoError { + /// Flattens the inner producers sent upon `signal` (into a single signal of + /// values), according to the semantics of the given strategy. + /// + /// - note: If `signal` fails, the returned signal will forward that failure + /// immediately. + /// + /// - warning: `interrupted` events on inner producers will be treated like + /// `completed` events on inner producers. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + public func flatten(_ strategy: FlattenStrategy) -> Signal { + return self.flatMap(strategy) { $0.producer.promoteError(Error.self) } + } +} + +extension SignalProducer where Value: SignalProducerConvertible, Error == Value.Error { + /// Flattens the inner producers sent upon `producer` (into a single + /// producer of values), according to the semantics of the given strategy. + /// + /// - note: If `producer` or an active inner producer fails, the returned + /// producer will forward that failure immediately. + /// + /// - warning: `interrupted` events on inner producers will be treated like + /// `completed` events on inner producers. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + public func flatten(_ strategy: FlattenStrategy) -> SignalProducer { + switch strategy { + case .concurrent(let limit): + return self.concurrent(limit: limit) + + case .latest: + return self.switchToLatest() + + case .race: + return self.race() + } + } +} + +extension SignalProducer where Value: SignalProducerConvertible, Error == NoError { + /// Flattens the inner producers sent upon `producer` (into a single + /// producer of values), according to the semantics of the given strategy. + /// + /// - note: If an active inner producer fails, the returned producer will + /// forward that failure immediately. + /// + /// - warning: `interrupted` events on inner producers will be treated like + /// `completed` events on inner producers. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + public func flatten(_ strategy: FlattenStrategy) -> SignalProducer { + return self + .promoteError(Value.Error.self) + .flatten(strategy) + } +} + +extension SignalProducer where Value: SignalProducerConvertible, Error == NoError, Value.Error == NoError { + /// Flattens the inner producers sent upon `producer` (into a single + /// producer of values), according to the semantics of the given strategy. + /// + /// - warning: `interrupted` events on inner producers will be treated like + /// `completed` events on inner producers. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + public func flatten(_ strategy: FlattenStrategy) -> SignalProducer { + switch strategy { + case .concurrent(let limit): + return self.concurrent(limit: limit) + + case .latest: + return self.switchToLatest() + + case .race: + return self.race() + } + } +} + +extension SignalProducer where Value: SignalProducerConvertible, Value.Error == NoError { + /// Flattens the inner producers sent upon `signal` (into a single signal of + /// values), according to the semantics of the given strategy. + /// + /// - note: If `signal` fails, the returned signal will forward that failure + /// immediately. + /// + /// - warning: `interrupted` events on inner producers will be treated like + /// `completed` events on inner producers. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + public func flatten(_ strategy: FlattenStrategy) -> SignalProducer { + return self.flatMap(strategy) { $0.producer.promoteError(Error.self) } + } +} + +extension Signal where Value: Sequence { + /// Flattens the `sequence` value sent by `signal`. + public func flatten() -> Signal { + return self.flatMap(.merge, SignalProducer.init) + } +} + +extension SignalProducer where Value: Sequence { + /// Flattens the `sequence` value sent by `signal`. + public func flatten() -> SignalProducer { + return self.flatMap(.merge, SignalProducer.init) + } +} + +extension Signal where Value: SignalProducerConvertible, Error == Value.Error { + fileprivate func concurrent(limit: UInt) -> Signal { + precondition(limit > 0, "The concurrent limit must be greater than zero.") + + return Signal { relayObserver in + let disposable = CompositeDisposable() + let relayDisposable = CompositeDisposable() + + disposable += relayDisposable + disposable += self.observeConcurrent(relayObserver, limit, relayDisposable) + + return disposable + } + } + + fileprivate func observeConcurrent(_ observer: Signal.Observer, _ limit: UInt, _ disposable: CompositeDisposable) -> Disposable? { + let state = Atomic(ConcurrentFlattenState(limit: limit)) + + func startNextIfNeeded() { + while let producer = state.modify({ $0.dequeue() }) { + let producerState = UnsafeAtomicState(.starting) + let deinitializer = ScopedDisposable(AnyDisposable(producerState.deinitialize)) + + producer.startWithSignal { signal, inner in + let handle = disposable.add(inner) + + signal.observe { event in + switch event { + case .completed, .interrupted: + handle?.dispose() + + let shouldComplete: Bool = state.modify { state in + state.activeCount -= 1 + return state.shouldComplete + } + + withExtendedLifetime(deinitializer) { + if shouldComplete { + observer.sendCompleted() + } else if producerState.is(.started) { + startNextIfNeeded() + } + } + + case .value, .failed: + observer.action(event) + } + } + } + + withExtendedLifetime(deinitializer) { + producerState.setStarted() + } + } + } + + return observe { event in + switch event { + case let .value(value): + state.modify { $0.queue.append(value.producer) } + startNextIfNeeded() + + case let .failed(error): + observer.send(error: error) + + case .completed: + let shouldComplete: Bool = state.modify { state in + state.isOuterCompleted = true + return state.shouldComplete + } + + if shouldComplete { + observer.sendCompleted() + } + + case .interrupted: + observer.sendInterrupted() + } + } + } +} + +extension SignalProducer where Value: SignalProducerConvertible, Error == Value.Error { + fileprivate func concurrent(limit: UInt) -> SignalProducer { + precondition(limit > 0, "The concurrent limit must be greater than zero.") + + return SignalProducer { relayObserver, lifetime in + self.startWithSignal { signal, signalDisposable in + let disposables = CompositeDisposable() + lifetime.observeEnded(signalDisposable.dispose) + lifetime.observeEnded(disposables.dispose) + + _ = signal.observeConcurrent(relayObserver, limit, disposables) + } + } + } +} + +extension SignalProducer { + /// `concat`s `next` onto `self`. + /// + /// - parameters: + /// - next: A follow-up producer to concat `self` with. + /// + /// - returns: A producer that will start `self` and then on completion of + /// `self` - will start `next`. + public func concat(_ next: SignalProducer) -> SignalProducer { + return SignalProducer, Error>([ self.producer, next ]).flatten(.concat) + } + + /// `concat`s `value` onto `self`. + /// + /// - parameters: + /// - value: A value to concat onto `self`. + /// + /// - returns: A producer that, when started, will emit own values and on + /// completion will emit a `value`. + public func concat(value: Value) -> SignalProducer { + return self.concat(SignalProducer(value: value)) + } + + /// `concat`s `self` onto initial `previous`. + /// + /// - parameters: + /// - previous: A producer to start before `self`. + /// + /// - returns: A signal producer that, when started, first emits values from + /// `previous` producer and then from `self`. + public func prefix(_ previous: SignalProducer) -> SignalProducer { + return previous.concat(self) + } + + /// `concat`s `self` onto initial `value`. + /// + /// - parameters: + /// - value: A first value to emit. + /// + /// - returns: A producer that, when started, first emits `value`, then all + /// values emited by `self`. + public func prefix(value: Value) -> SignalProducer { + return self.prefix(SignalProducer(value: value)) + } +} + +private final class ConcurrentFlattenState { + typealias Producer = ReactiveSwift.SignalProducer + + /// The limit of active producers. + let limit: UInt + + /// The number of active producers. + var activeCount: UInt = 0 + + /// The producers waiting to be started. + var queue: [Producer] = [] + + /// Whether the outer producer has completed. + var isOuterCompleted = false + + /// Whether the flattened signal should complete. + var shouldComplete: Bool { + return isOuterCompleted && activeCount == 0 && queue.isEmpty + } + + init(limit: UInt) { + self.limit = limit + } + + /// Dequeue the next producer if one should be started. + /// + /// - returns: The `Producer` to start or `nil` if no producer should be + /// started. + func dequeue() -> Producer? { + if activeCount < limit, !queue.isEmpty { + activeCount += 1 + return queue.removeFirst() + } else { + return nil + } + } +} + +private enum ProducerState: Int32 { + case starting + case started +} + +extension UnsafeAtomicState where State == ProducerState { + fileprivate func setStarted() { + precondition(tryTransition(from: .starting, to: .started), "The transition is not supposed to fail.") + } +} + +extension Signal { + /// Merges the given signals into a single `Signal` that will emit all + /// values from each of them, and complete when all of them have completed. + /// + /// - parameters: + /// - signals: A sequence of signals to merge. + public static func merge(_ signals: Seq) -> Signal where Seq.Iterator.Element == Signal + { + return SignalProducer, Error>(signals) + .flatten(.merge) + .startAndRetrieveSignal() + } + + /// Merges the given signals into a single `Signal` that will emit all + /// values from each of them, and complete when all of them have completed. + /// + /// - parameters: + /// - signals: A list of signals to merge. + public static func merge(_ signals: Signal...) -> Signal { + return Signal.merge(signals) + } +} + +extension SignalProducer { + /// Merges the given producers into a single `SignalProducer` that will emit + /// all values from each of them, and complete when all of them have + /// completed. + /// + /// - parameters: + /// - producers: A sequence of producers to merge. + public static func merge(_ producers: Seq) -> SignalProducer where Seq.Iterator.Element == SignalProducer + { + return SignalProducer(producers).flatten(.merge) + } + + /// Merges the given producers into a single `SignalProducer` that will emit + /// all values from each of them, and complete when all of them have + /// completed. + /// + /// - parameters: + /// - producers: A sequence of producers to merge. + public static func merge(_ producers: SignalProducer...) -> SignalProducer { + return SignalProducer.merge(producers) + } +} + +extension Signal where Value: SignalProducerConvertible, Error == Value.Error { + /// Returns a signal that forwards values from the latest signal sent on + /// `signal`, ignoring values sent on previous inner signal. + /// + /// - warning: An error sent on `signal` or the latest inner signal will be + /// sent on the returned signal. + /// + /// - note: The returned signal completes when `signal` and the latest inner + /// signal have both completed. + fileprivate func switchToLatest() -> Signal { + return Signal { observer in + let composite = CompositeDisposable() + let serial = SerialDisposable() + + composite += serial + composite += self.observeSwitchToLatest(observer, serial) + + return composite + } + } + + fileprivate func observeSwitchToLatest(_ observer: Signal.Observer, _ latestInnerDisposable: SerialDisposable) -> Disposable? { + let state = Atomic(LatestState()) + + return self.observe { event in + switch event { + case let .value(p): + p.producer.startWithSignal { innerSignal, innerDisposable in + state.modify { + // When we replace the disposable below, this prevents + // the generated Interrupted event from doing any work. + $0.replacingInnerSignal = true + } + + latestInnerDisposable.inner = innerDisposable + + state.modify { + $0.replacingInnerSignal = false + $0.innerSignalComplete = false + } + + innerSignal.observe { event in + switch event { + case .interrupted: + // If interruption occurred as a result of a new + // producer arriving, we don't want to notify our + // observer. + let shouldComplete: Bool = state.modify { state in + if !state.replacingInnerSignal { + state.innerSignalComplete = true + } + return !state.replacingInnerSignal && state.outerSignalComplete + } + + if shouldComplete { + observer.sendCompleted() + } + + case .completed: + let shouldComplete: Bool = state.modify { + $0.innerSignalComplete = true + return $0.outerSignalComplete + } + + if shouldComplete { + observer.sendCompleted() + } + + case .value, .failed: + observer.action(event) + } + } + } + + case let .failed(error): + observer.send(error: error) + + case .completed: + let shouldComplete: Bool = state.modify { + $0.outerSignalComplete = true + return $0.innerSignalComplete + } + + if shouldComplete { + observer.sendCompleted() + } + + case .interrupted: + observer.sendInterrupted() + } + } + } +} + +extension SignalProducer where Value: SignalProducerConvertible, Error == Value.Error { + /// - warning: An error sent on `signal` or the latest inner signal will be + /// sent on the returned signal. + /// + /// - note: The returned signal completes when `signal` and the latest inner + /// signal have both completed. + /// + /// - returns: A signal that forwards values from the latest signal sent on + /// `signal`, ignoring values sent on previous inner signal. + fileprivate func switchToLatest() -> SignalProducer { + return SignalProducer { observer, lifetime in + let latestInnerDisposable = SerialDisposable() + lifetime.observeEnded(latestInnerDisposable.dispose) + + self.startWithSignal { signal, signalDisposable in + lifetime.observeEnded(signalDisposable.dispose) + + if let disposable = signal.observeSwitchToLatest(observer, latestInnerDisposable) { + lifetime.observeEnded(disposable.dispose) + } + } + } + } +} + +private struct LatestState { + var outerSignalComplete: Bool = false + var innerSignalComplete: Bool = true + + var replacingInnerSignal: Bool = false +} + +extension Signal where Value: SignalProducerConvertible, Error == Value.Error { + /// Returns a signal that forwards values from the "first input signal to send an event" + /// (winning signal) that is sent on `self`, ignoring values sent from other inner signals. + /// + /// An error sent on `self` or the winning inner signal will be sent on the + /// returned signal. + /// + /// The returned signal completes when `self` and the winning inner signal have both completed. + fileprivate func race() -> Signal { + return Signal { observer in + let composite = CompositeDisposable() + let relayDisposable = CompositeDisposable() + + composite += relayDisposable + composite += self.observeRace(observer, relayDisposable) + + return composite + } + } + + fileprivate func observeRace(_ observer: Signal.Observer, _ relayDisposable: CompositeDisposable) -> Disposable? { + let state = Atomic(RaceState()) + + return self.observe { event in + switch event { + case let .value(innerProducer): + // Ignore consecutive `innerProducer`s if any `innerSignal` already sent an event. + guard !relayDisposable.isDisposed else { + return + } + + innerProducer.producer.startWithSignal { innerSignal, innerDisposable in + state.modify { + $0.innerSignalComplete = false + } + + let disposableHandle = relayDisposable.add(innerDisposable) + var isWinningSignal = false + + innerSignal.observe { event in + if !isWinningSignal { + isWinningSignal = state.modify { state in + guard !state.isActivated else { + return false + } + + state.isActivated = true + return true + } + + // Ignore non-winning signals. + guard isWinningSignal else { return } + + // The disposals would be run exactly once immediately after + // the winning signal flips `state.isActivated`. + disposableHandle?.dispose() + relayDisposable.dispose() + } + + switch event { + case .completed: + let shouldComplete: Bool = state.modify { state in + state.innerSignalComplete = true + return state.outerSignalComplete + } + + if shouldComplete { + observer.sendCompleted() + } + + case .value, .failed, .interrupted: + observer.action(event) + } + } + } + + case let .failed(error): + observer.send(error: error) + + case .completed: + let shouldComplete: Bool = state.modify { state in + state.outerSignalComplete = true + return state.innerSignalComplete + } + + if shouldComplete { + observer.sendCompleted() + } + + case .interrupted: + observer.sendInterrupted() + } + } + } +} + +extension SignalProducer where Value: SignalProducerConvertible, Error == Value.Error { + /// Returns a producer that forwards values from the "first input producer to send an event" + /// (winning producer) that is sent on `self`, ignoring values sent from other inner producers. + /// + /// An error sent on `self` or the winning inner producer will be sent on the + /// returned producer. + /// + /// The returned producer completes when `self` and the winning inner producer have both completed. + fileprivate func race() -> SignalProducer { + return SignalProducer { observer, lifetime in + let relayDisposable = CompositeDisposable() + lifetime.observeEnded(relayDisposable.dispose) + + self.startWithSignal { signal, signalDisposable in + lifetime.observeEnded(signalDisposable.dispose) + + if let disposable = signal.observeRace(observer, relayDisposable) { + lifetime.observeEnded(disposable.dispose) + } + } + } + } +} + +private struct RaceState { + var outerSignalComplete = false + var innerSignalComplete = true + var isActivated = false +} + +extension Signal { + /// Maps each event from `signal` to a new signal, then flattens the + /// resulting producers (into a signal of values), according to the + /// semantics of the given strategy. + /// + /// - warning: If `signal` or any of the created producers fail, the + /// returned signal will forward that failure immediately. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + /// - transform: A closure that takes a value emitted by `self` and + /// returns a signal producer with transformed value. + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal where Inner.Error == Error { + return map(transform).flatten(strategy) + } + + /// Maps each event from `signal` to a new signal, then flattens the + /// resulting producers (into a signal of values), according to the + /// semantics of the given strategy. + /// + /// - warning: If `signal` fails, the returned signal will forward that + /// failure immediately. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + /// - transform: A closure that takes a value emitted by `self` and + /// returns a signal producer with transformed value. + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal where Inner.Error == NoError { + return map(transform).flatten(strategy) + } +} + +extension Signal where Error == NoError { + /// Maps each event from `signal` to a new signal, then flattens the + /// resulting signals (into a signal of values), according to the + /// semantics of the given strategy. + /// + /// - warning: If any of the created signals emit an error, the returned + /// signal will forward that error immediately. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + /// - transform: A closure that takes a value emitted by `self` and + /// returns a signal producer with transformed value. + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal { + return map(transform).flatten(strategy) + } + + /// Maps each event from `signal` to a new signal, then flattens the + /// resulting signals (into a signal of values), according to the + /// semantics of the given strategy. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + /// - transform: A closure that takes a value emitted by `self` and + /// returns a signal producer with transformed value. + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal where Inner.Error == NoError { + return map(transform).flatten(strategy) + } +} + +extension SignalProducer { + /// Maps each event from `self` to a new producer, then flattens the + /// resulting producers (into a producer of values), according to the + /// semantics of the given strategy. + /// + /// - warning: If `self` or any of the created producers fail, the returned + /// producer will forward that failure immediately. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + /// - transform: A closure that takes a value emitted by `self` and + /// returns a signal producer with transformed value. + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer where Inner.Error == Error { + return map(transform).flatten(strategy) + } + + /// Maps each event from `self` to a new producer, then flattens the + /// resulting producers (into a producer of values), according to the + /// semantics of the given strategy. + /// + /// - warning: If `self` fails, the returned producer will forward that + /// failure immediately. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + /// - transform: A closure that takes a value emitted by `self` and + /// returns a signal producer with transformed value. + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer where Inner.Error == NoError { + return map(transform).flatten(strategy) + } +} + +extension SignalProducer where Error == NoError { + /// Maps each event from `self` to a new producer, then flattens the + /// resulting producers (into a producer of values), according to the + /// semantics of the given strategy. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + /// - transform: A closure that takes a value emitted by `self` and + /// returns a signal producer with transformed value. + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer where Inner.Error == Error { + return map(transform).flatten(strategy) + } + + /// Maps each event from `self` to a new producer, then flattens the + /// resulting producers (into a producer of values), according to the + /// semantics of the given strategy. + /// + /// - warning: If any of the created producers fail, the returned producer + /// will forward that failure immediately. + /// + /// - parameters: + /// - strategy: Strategy used when flattening signals. + /// - transform: A closure that takes a value emitted by `self` and + /// returns a signal producer with transformed value. + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer { + return map(transform).flatten(strategy) + } +} + + +extension Signal { + /// Catches any failure that may occur on the input signal, mapping to a new + /// producer that starts in its place. + /// + /// - parameters: + /// - transform: A closure that accepts emitted error and returns a signal + /// producer with a different type of error. + public func flatMapError(_ transform: @escaping (Error) -> SignalProducer) -> Signal { + return Signal { observer in + self.observeFlatMapError(transform, observer, SerialDisposable()) + } + } + + fileprivate func observeFlatMapError(_ handler: @escaping (Error) -> SignalProducer, _ observer: Signal.Observer, _ serialDisposable: SerialDisposable) -> Disposable? { + return self.observe { event in + switch event { + case let .value(value): + observer.send(value: value) + case let .failed(error): + handler(error).startWithSignal { signal, disposable in + serialDisposable.inner = disposable + signal.observe(observer) + } + case .completed: + observer.sendCompleted() + case .interrupted: + observer.sendInterrupted() + } + } + } +} + +extension SignalProducer { + /// Catches any failure that may occur on the input producer, mapping to a + /// new producer that starts in its place. + /// + /// - parameters: + /// - transform: A closure that accepts emitted error and returns a signal + /// producer with a different type of error. + public func flatMapError(_ transform: @escaping (Error) -> SignalProducer) -> SignalProducer { + return SignalProducer { observer, lifetime in + let serialDisposable = SerialDisposable() + lifetime.observeEnded(serialDisposable.dispose) + + self.startWithSignal { signal, signalDisposable in + serialDisposable.inner = signalDisposable + + _ = signal.observeFlatMapError(transform, observer, serialDisposable) + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/FoundationExtensions.swift b/Carthage/Checkouts/ReactiveSwift/Sources/FoundationExtensions.swift new file mode 100644 index 0000000..8f433dd --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/FoundationExtensions.swift @@ -0,0 +1,138 @@ +// +// FoundationExtensions.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-10-19. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +import Foundation +import Dispatch +import enum Result.NoError +import struct Result.AnyError + +#if os(Linux) + import let CDispatch.NSEC_PER_USEC + import let CDispatch.NSEC_PER_SEC +#endif + +extension NotificationCenter: ReactiveExtensionsProvider {} + +extension Reactive where Base: NotificationCenter { + /// Returns a Signal to observe posting of the specified notification. + /// + /// - parameters: + /// - name: name of the notification to observe + /// - object: an instance which sends the notifications + /// + /// - returns: A Signal of notifications posted that match the given criteria. + /// + /// - note: The signal does not terminate naturally. Observers must be + /// explicitly disposed to avoid leaks. + public func notifications(forName name: Notification.Name?, object: AnyObject? = nil) -> Signal { + return Signal { [base = self.base] observer in + let notificationObserver = base.addObserver(forName: name, object: object, queue: nil) { notification in + observer.send(value: notification) + } + + return AnyDisposable { + base.removeObserver(notificationObserver) + } + } + } +} + +private let defaultSessionError = NSError(domain: "org.reactivecocoa.ReactiveSwift.Reactivity.URLSession.dataWithRequest", + code: 1, + userInfo: nil) + +extension URLSession: ReactiveExtensionsProvider {} + +extension Reactive where Base: URLSession { + /// Returns a SignalProducer which performs the work associated with an + /// `NSURLSession` + /// + /// - parameters: + /// - request: A request that will be performed when the producer is + /// started + /// + /// - returns: A producer that will execute the given request once for each + /// invocation of `start()`. + /// + /// - note: This method will not send an error event in the case of a server + /// side error (i.e. when a response with status code other than + /// 200...299 is received). + public func data(with request: URLRequest) -> SignalProducer<(Data, URLResponse), AnyError> { + return SignalProducer { [base = self.base] observer, lifetime in + let task = base.dataTask(with: request) { data, response, error in + if let data = data, let response = response { + observer.send(value: (data, response)) + observer.sendCompleted() + } else { + observer.send(error: AnyError(error ?? defaultSessionError)) + } + } + + lifetime.observeEnded(task.cancel) + task.resume() + } + } +} + +extension Date { + internal func addingTimeInterval(_ interval: DispatchTimeInterval) -> Date { + return addingTimeInterval(interval.timeInterval) + } +} + +extension DispatchTimeInterval { + internal var timeInterval: TimeInterval { + switch self { + case let .seconds(s): + return TimeInterval(s) + case let .milliseconds(ms): + return TimeInterval(TimeInterval(ms) / 1000.0) + case let .microseconds(us): + return TimeInterval( UInt64(us) * NSEC_PER_USEC ) / TimeInterval(NSEC_PER_SEC) + case let .nanoseconds(ns): + return TimeInterval(ns) / TimeInterval(NSEC_PER_SEC) + } + } + + // This was added purely so that our test scheduler to "go backwards" in + // time. See `TestScheduler.rewind(by interval: DispatchTimeInterval)`. + internal static prefix func -(lhs: DispatchTimeInterval) -> DispatchTimeInterval { + switch lhs { + case let .seconds(s): + return .seconds(-s) + case let .milliseconds(ms): + return .milliseconds(-ms) + case let .microseconds(us): + return .microseconds(-us) + case let .nanoseconds(ns): + return .nanoseconds(-ns) + } + } + + /// Scales a time interval by the given scalar specified in `rhs`. + /// + /// - note: This method is only used internally to "scale down" a time + /// interval. Specifically it's used only to scale intervals to 10% + /// of their original value for the default `leeway` parameter in + /// `Scheduler.schedule(after:action:)` schedule and similar + /// other methods. + /// + /// If seconds is over 200,000, 10% is ~2,000, and hence we end up + /// with a value of ~2,000,000,000. Not quite overflowing a signed + /// integer on 32-bit platforms, but close. + /// + /// Even still, 200,000 seconds should be a rarely (if ever) + /// specified interval for our APIs. And even then, folks should be + /// smart and specify their own `leeway` parameter. + /// + /// - returns: Scaled interval in microseconds + internal static func *(lhs: DispatchTimeInterval, rhs: Double) -> DispatchTimeInterval { + let seconds = lhs.timeInterval * rhs + return .microseconds(Int(seconds * 1000 * 1000)) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Info.plist b/Carthage/Checkouts/ReactiveSwift/Sources/Info.plist new file mode 100644 index 0000000..112303e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 2.0.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2014 GitHub. All rights reserved. + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/InhabitableTypeGuards.swift b/Carthage/Checkouts/ReactiveSwift/Sources/InhabitableTypeGuards.swift new file mode 100644 index 0000000..5c5d44a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/InhabitableTypeGuards.swift @@ -0,0 +1,132 @@ +import Result + +// Observation +extension SignalProducer where Value == Never { + @discardableResult + @available(*, deprecated, message:"`Result.success` is never delivered - `Value` is inhabitable (Instantiation at runtime would trap)") + public func startWithResult(_ action: @escaping (Result) -> Void) -> Disposable { observingInhabitableTypeError() } + + @discardableResult + @available(*, deprecated, message:"Observer is never called - `Value` is inhabitable (Instantiation at runtime would trap)") + public func startWithValues(_ action: @escaping (Value) -> Void) -> Disposable { observingInhabitableTypeError() } +} + +extension SignalProducer where Value == Never, Error == NoError { + @discardableResult + @available(*, deprecated, message:"Observer is never called - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)") + public func startWithResult(_ action: @escaping (Result) -> Void) -> Disposable { observingInhabitableTypeError() } +} + +extension SignalProducer where Error == NoError { + @discardableResult + @available(*, deprecated, message:"`Error` is inhabitable so the observer is never called (Instantiation at runtime would trap)") + public func startWithFailed(_ action: @escaping (Error) -> Void) -> Disposable { observingInhabitableTypeError() } +} + +extension Signal where Value == Never { + @discardableResult + @available(*, deprecated, message:"`Result.success` is never delivered - `Value` is inhabitable (Instantiation at runtime would trap)") + public func observeResult(_ action: @escaping (Result) -> Void) -> Disposable? { observingInhabitableTypeError() } + + @discardableResult + @available(*, deprecated, message:"Observer is never called - `Value` is inhabitable (Instantiation at runtime would trap)") + public func observeValues(_ action: @escaping (Value) -> Void) -> Disposable? { observingInhabitableTypeError() } +} + +extension Signal where Value == Never, Error == NoError { + @discardableResult + @available(*, deprecated, message:"Observer is never called - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)") + public func observeResult(_ action: @escaping (Result) -> Void) -> Disposable? { observingInhabitableTypeError() } +} + +extension Signal where Error == NoError { + @discardableResult + @available(*, deprecated, message:"Observer is never invoked - `Error` is inhabitable (Instantiation at runtime would trap)") + public func observeFailed(_ action: @escaping (Error) -> Void) -> Disposable? { observingInhabitableTypeError() } +} + +// flatMap +extension SignalProducer where Value == Never { + @discardableResult + @available(*, deprecated, message:"Use `promoteValue` instead - `Value` is inhabitable (Instantiation at runtime would trap)") + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer where Inner.Error == Error { observingInhabitableTypeError() } + + @discardableResult + @available(*, deprecated, message:"Use `promoteValue` instead - `Value` is inhabitable (Instantiation at runtime would trap)") + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer where Inner.Error == NoError { observingInhabitableTypeError() } +} + +extension SignalProducer where Value == Never, Error == NoError { + @discardableResult + @available(*, deprecated, message:"Use `promoteValue` instead - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)") + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer { observingInhabitableTypeError() } + + @discardableResult + @available(*, deprecated, message:"Use `promoteValue` instead - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)") + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> SignalProducer where Inner.Error == Error { observingInhabitableTypeError() } +} + +extension SignalProducer where Error == NoError { + @discardableResult + @available(*, deprecated, message:"Use `promoteError` instead - `Error` is inhabitable (Instantiation at runtime would trap)") + public func flatMapError(_ transform: @escaping (Error) -> SignalProducer) -> SignalProducer { observingInhabitableTypeError() } +} + +extension Signal where Value == Never { + @discardableResult + @available(*, deprecated, message:"Use `promoteValue` instead - `Value` is inhabitable (Instantiation at runtime would trap)") + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal where Inner.Error == Error { observingInhabitableTypeError() } + + @discardableResult + @available(*, deprecated, message:"Use `promoteValue` instead - `Value` is inhabitable (Instantiation at runtime would trap)") + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal where Inner.Error == NoError { observingInhabitableTypeError() } + +} + +extension Signal where Value == Never, Error == NoError { + @discardableResult + @available(*, deprecated, message:"Use `promoteValue` instead - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)") + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal { observingInhabitableTypeError() } + + @discardableResult + @available(*, deprecated, message:"Use `promoteValue` instead - `Value` and `Error` are inhabitable (Instantiation at runtime would trap)") + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> Inner) -> Signal where Inner.Error == Error { observingInhabitableTypeError() } +} + +extension Signal where Error == NoError { + @discardableResult + @available(*, deprecated, message:"Use `promoteError` instead - `Error` is inhabitable (Instantiation at runtime would trap)") + public func flatMapError(_ transform: @escaping (Error) -> SignalProducer) -> Signal { observingInhabitableTypeError() } +} + +@inline(never) +private func observingInhabitableTypeError() -> Never { + fatalError("Detected an attempt to instantiate a `Signal` or `SignalProducer` that observes an inhabitable type, e.g. `Never` or `NoError`. This is considered a logical error, and appropriate operators should be used instead. Please refer to the warnings raised by the compiler.") +} + +/* +func test() { + SignalProducer.never.startWithResult { _ in } + SignalProducer.never.startWithResult { _ in } + SignalProducer.never.startWithFailed { _ in } + SignalProducer.never.startWithFailed { _ in } + Signal.never.observeResult { _ in } + Signal.never.observeResult { _ in } + Signal.never.observeFailed { _ in } + Signal.never.observeFailed { _ in } + + SignalProducer.never.flatMap(.latest) { _ in SignalProducer.empty } + SignalProducer.never.flatMap(.latest) { _ in SignalProducer.empty } + SignalProducer.never.flatMap(.latest) { _ in SignalProducer.empty } + SignalProducer.never.flatMap(.latest) { _ in SignalProducer.empty } + SignalProducer.never.flatMapError { _ in SignalProducer.empty } + SignalProducer.never.flatMapError { _ in SignalProducer.empty } + + Signal.never.flatMap(.latest) { _ in SignalProducer.empty } + Signal.never.flatMap(.latest) { _ in SignalProducer.empty } + Signal.never.flatMap(.latest) { _ in SignalProducer.empty } + Signal.never.flatMap(.latest) { _ in SignalProducer.empty } + Signal.never.flatMapError { _ in SignalProducer.empty } + Signal.never.flatMapError { _ in SignalProducer.empty } +} +*/ diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Lifetime.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Lifetime.swift new file mode 100644 index 0000000..9d06356 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Lifetime.swift @@ -0,0 +1,98 @@ +import Foundation +import enum Result.NoError + +/// Represents the lifetime of an object, and provides a hook to observe when +/// the object deinitializes. +public final class Lifetime { + private let disposables: CompositeDisposable + + /// A signal that sends a `completed` event when the lifetime ends. + /// + /// - note: Consider using `Lifetime.observeEnded` if only a closure observer + /// is to be attached. + public var ended: Signal { + return Signal { observer in + return disposables += observer.sendCompleted + } + } + + /// A flag indicating whether the lifetime has ended. + public var hasEnded: Bool { + return disposables.isDisposed + } + + /// Initialize a `Lifetime` object with the supplied composite disposable. + /// + /// - parameters: + /// - signal: The composite disposable. + internal init(_ disposables: CompositeDisposable) { + self.disposables = disposables + } + + /// Initialize a `Lifetime` from a lifetime token, which is expected to be + /// associated with an object. + /// + /// - important: The resulting lifetime object does not retain the lifetime + /// token. + /// + /// - parameters: + /// - token: A lifetime token for detecting the deinitialization of the + /// associated object. + public convenience init(_ token: Token) { + self.init(token.disposables) + } + + /// Observe the termination of `self`. + /// + /// - parameters: + /// - action: The action to be invoked when `self` ends. + /// + /// - returns: A disposable that detaches `action` from the lifetime, or `nil` + /// if `lifetime` has already ended. + @discardableResult + public func observeEnded(_ action: @escaping () -> Void) -> Disposable? { + return disposables += action + } +} + +extension Lifetime { + /// Factory method for creating a `Lifetime` and its associated `Token`. + /// + /// - returns: A `(lifetime, token)` tuple. + public static func make() -> (lifetime: Lifetime, token: Token) { + let token = Token() + return (Lifetime(token), token) + } + + /// A `Lifetime` that has already ended. + public static let empty: Lifetime = { + let disposables = CompositeDisposable() + disposables.dispose() + return Lifetime(disposables) + }() +} + +extension Lifetime { + /// A token object which completes its signal when it deinitializes. + /// + /// It is generally used in conjuncion with `Lifetime` as a private + /// deinitialization trigger. + /// + /// ``` + /// class MyController { + /// private let (lifetime, token) = Lifetime.make() + /// } + /// ``` + public final class Token { + /// A signal that sends a Completed event when the lifetime ends. + fileprivate let disposables: CompositeDisposable + + public init() { + disposables = CompositeDisposable() + } + + deinit { + disposables.dispose() + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Observer.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Observer.swift new file mode 100644 index 0000000..85aeccc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Observer.swift @@ -0,0 +1,97 @@ +// +// Observer.swift +// ReactiveSwift +// +// Created by Andy Matuschak on 10/2/15. +// Copyright © 2015 GitHub. All rights reserved. +// + +extension Signal { + /// An Observer is a simple wrapper around a function which can receive Events + /// (typically from a Signal). + public final class Observer { + public typealias Action = (Event) -> Void + + /// An action that will be performed upon arrival of the event. + public let action: Action + + /// An initializer that accepts a closure accepting an event for the + /// observer. + /// + /// - parameters: + /// - action: A closure to lift over received event. + public init(_ action: @escaping Action) { + self.action = action + } + + /// An initializer that accepts closures for different event types. + /// + /// - parameters: + /// - value: Optional closure executed when a `value` event is observed. + /// - failed: Optional closure that accepts an `Error` parameter when a + /// failed event is observed. + /// - completed: Optional closure executed when a `completed` event is + /// observed. + /// - interruped: Optional closure executed when an `interrupted` event is + /// observed. + public convenience init( + value: ((Value) -> Void)? = nil, + failed: ((Error) -> Void)? = nil, + completed: (() -> Void)? = nil, + interrupted: (() -> Void)? = nil + ) { + self.init { event in + switch event { + case let .value(v): + value?(v) + + case let .failed(error): + failed?(error) + + case .completed: + completed?() + + case .interrupted: + interrupted?() + } + } + } + + internal convenience init(mappingInterruptedToCompleted observer: Signal.Observer) { + self.init { event in + switch event { + case .value, .completed, .failed: + observer.action(event) + case .interrupted: + observer.sendCompleted() + } + } + } + + /// Puts a `value` event into `self`. + /// + /// - parameters: + /// - value: A value sent with the `value` event. + public func send(value: Value) { + action(.value(value)) + } + + /// Puts a failed event into `self`. + /// + /// - parameters: + /// - error: An error object sent with failed event. + public func send(error: Error) { + action(.failed(error)) + } + + /// Puts a `completed` event into `self`. + public func sendCompleted() { + action(.completed) + } + + /// Puts an `interrupted` event into `self`. + public func sendInterrupted() { + action(.interrupted) + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Optional.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Optional.swift new file mode 100644 index 0000000..1e8584c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Optional.swift @@ -0,0 +1,42 @@ +// +// Optional.swift +// ReactiveSwift +// +// Created by Neil Pankey on 6/24/15. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +/// An optional protocol for use in type constraints. +public protocol OptionalProtocol { + /// The type contained in the otpional. + associatedtype Wrapped + + init(reconstructing value: Wrapped?) + + /// Extracts an optional from the receiver. + var optional: Wrapped? { get } +} + +extension Optional: OptionalProtocol { + public var optional: Wrapped? { + return self + } + + public init(reconstructing value: Wrapped?) { + self = value + } +} + +extension Signal { + /// Turns each value into an Optional. + internal func optionalize() -> Signal { + return map(Optional.init) + } +} + +extension SignalProducer { + /// Turns each value into an Optional. + internal func optionalize() -> SignalProducer { + return lift { $0.optionalize() } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Property.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Property.swift new file mode 100644 index 0000000..4fb4044 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Property.swift @@ -0,0 +1,751 @@ +#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS) +import Darwin.POSIX.pthread +#else +import Glibc +#endif +import enum Result.NoError + +/// Represents a property that allows observation of its changes. +/// +/// Only classes can conform to this protocol, because having a signal +/// for changes over time implies the origin must have a unique identity. +public protocol PropertyProtocol: class, BindingSource { + associatedtype Value + + /// The current value of the property. + var value: Value { get } + + /// The values producer of the property. + /// + /// It produces a signal that sends the property's current value, + /// followed by all changes over time. It completes when the property + /// has deinitialized, or has no further change. + /// + /// - note: If `self` is a composed property, the producer would be + /// bound to the lifetime of its sources. + var producer: SignalProducer { get } + + /// A signal that will send the property's changes over time. It + /// completes when the property has deinitialized, or has no further + /// change. + /// + /// - note: If `self` is a composed property, the signal would be + /// bound to the lifetime of its sources. + var signal: Signal { get } +} + +/// Represents an observable property that can be mutated directly. +public protocol MutablePropertyProtocol: PropertyProtocol, BindingTargetProvider { + /// The current value of the property. + var value: Value { get set } + + /// The lifetime of the property. + var lifetime: Lifetime { get } +} + +/// Default implementation of `BindingTargetProvider` for mutable properties. +extension MutablePropertyProtocol { + public var bindingTarget: BindingTarget { + return BindingTarget(lifetime: lifetime) { [weak self] in self?.value = $0 } + } +} + +/// Represents a mutable property that can be safety composed by exposing its +/// synchronization mechanic through the defined closure-based interface. +public protocol ComposableMutablePropertyProtocol: MutablePropertyProtocol { + /// Atomically performs an arbitrary action using the current value of the + /// variable. + /// + /// - parameters: + /// - action: A closure that accepts current property value. + /// + /// - returns: the result of the action. + func withValue(_ action: (Value) throws -> Result) rethrows -> Result + + /// Atomically modifies the variable. + /// + /// - parameters: + /// - action: A closure that accepts old property value and returns a new + /// property value. + /// + /// - returns: The result of the action. + func modify(_ action: (inout Value) throws -> Result) rethrows -> Result +} + +// Property operators. +// +// A composed property is a transformed view of its sources, and does not +// own its lifetime. Its producer and signal are bound to the lifetime of +// its sources. + +extension PropertyProtocol { + /// Lifts a unary SignalProducer operator to operate upon PropertyProtocol instead. + fileprivate func lift(_ transform: @escaping (SignalProducer) -> SignalProducer) -> Property { + return Property(unsafeProducer: transform(producer)) + } + + /// Lifts a binary SignalProducer operator to operate upon PropertyProtocol instead. + fileprivate func lift(_ transform: @escaping (SignalProducer) -> (SignalProducer) -> SignalProducer) -> (P) -> Property { + return { other in + return Property(unsafeProducer: transform(self.producer)(other.producer)) + } + } + + /// Maps the current value and all subsequent values to a new property. + /// + /// - parameters: + /// - transform: A closure that will map the current `value` of this + /// `Property` to a new value. + /// + /// - returns: A property that holds a mapped value from `self`. + public func map(_ transform: @escaping (Value) -> U) -> Property { + return lift { $0.map(transform) } + } + +#if swift(>=3.2) + /// Maps the current value and all subsequent values to a new property + /// by applying a key path. + /// + /// - parameters: + /// - keyPath: A key path relative to the property's `Value` type. + /// + /// - returns: A property that holds a mapped value from `self`. + public func map(_ keyPath: KeyPath) -> Property { + return lift { $0.map(keyPath) } + } +#endif + + /// Combines the current value and the subsequent values of two `Property`s in + /// the manner described by `Signal.combineLatest(with:)`. + /// + /// - parameters: + /// - other: A property to combine `self`'s value with. + /// + /// - returns: A property that holds a tuple containing values of `self` and + /// the given property. + public func combineLatest(with other: P) -> Property<(Value, P.Value)> { + return Property.combineLatest(self, other) + } + + /// Zips the current value and the subsequent values of two `Property`s in + /// the manner described by `Signal.zipWith`. + /// + /// - parameters: + /// - other: A property to zip `self`'s value with. + /// + /// - returns: A property that holds a tuple containing values of `self` and + /// the given property. + public func zip(with other: P) -> Property<(Value, P.Value)> { + return Property.zip(self, other) + } + + /// Forward events from `self` with history: values of the returned property + /// are a tuple whose first member is the previous value and whose second + /// member is the current value. `initial` is supplied as the first member + /// when `self` sends its first value. + /// + /// - parameters: + /// - initial: A value that will be combined with the first value sent by + /// `self`. + /// + /// - returns: A property that holds tuples that contain previous and + /// current values of `self`. + public func combinePrevious(_ initial: Value) -> Property<(Value, Value)> { + return lift { $0.combinePrevious(initial) } + } + + /// Forward only values from `self` that are not considered equivalent to its + /// consecutive predecessor. + /// + /// - note: The first value is always forwarded. + /// + /// - parameters: + /// - isEquivalent: A closure to determine whether two values are equivalent. + /// + /// - returns: A property which conditionally forwards values from `self`. + public func skipRepeats(_ isEquivalent: @escaping (Value, Value) -> Bool) -> Property { + return lift { $0.skipRepeats(isEquivalent) } + } +} + +extension PropertyProtocol where Value: Equatable { + /// Forward only values from `self` that are not equal to its consecutive predecessor. + /// + /// - note: The first value is always forwarded. + /// + /// - returns: A property which conditionally forwards values from `self`. + public func skipRepeats() -> Property { + return lift { $0.skipRepeats() } + } +} + +extension PropertyProtocol where Value: PropertyProtocol { + /// Flattens the inner property held by `self` (into a single property of + /// values), according to the semantics of the given strategy. + /// + /// - parameters: + /// - strategy: The preferred flatten strategy. + /// + /// - returns: A property that sends the values of its inner properties. + public func flatten(_ strategy: FlattenStrategy) -> Property { + return lift { $0.flatMap(strategy) { $0.producer } } + } +} + +extension PropertyProtocol { + /// Maps each property from `self` to a new property, then flattens the + /// resulting properties (into a single property), according to the + /// semantics of the given strategy. + /// + /// - parameters: + /// - strategy: The preferred flatten strategy. + /// - transform: The transform to be applied on `self` before flattening. + /// + /// - returns: A property that sends the values of its inner properties. + public func flatMap(_ strategy: FlattenStrategy, _ transform: @escaping (Value) -> P) -> Property { + return lift { $0.flatMap(strategy) { transform($0).producer } } + } + + /// Forward only those values from `self` that have unique identities across + /// the set of all values that have been held. + /// + /// - note: This causes the identities to be retained to check for + /// uniqueness. + /// + /// - parameters: + /// - transform: A closure that accepts a value and returns identity + /// value. + /// + /// - returns: A property that sends unique values during its lifetime. + public func uniqueValues(_ transform: @escaping (Value) -> Identity) -> Property { + return lift { $0.uniqueValues(transform) } + } +} + +extension PropertyProtocol where Value: Hashable { + /// Forwards only those values from `self` that are unique across the set of + /// all values that have been seen. + /// + /// - note: This causes the identities to be retained to check for uniqueness. + /// Providing a function that returns a unique value for each sent + /// value can help you reduce the memory footprint. + /// + /// - returns: A property that sends unique values during its lifetime. + public func uniqueValues() -> Property { + return lift { $0.uniqueValues() } + } +} + +extension PropertyProtocol { + /// Combines the values of all the given properties, in the manner described + /// by `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B) -> Property<(A.Value, B.Value)> where Value == A.Value { + return a.lift { SignalProducer.combineLatest($0, b.producer) } + } + + /// Combines the values of all the given properties, in the manner described + /// by `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C) -> Property<(A.Value, B.Value, C.Value)> where Value == A.Value { + return a.lift { SignalProducer.combineLatest($0, b.producer, c.producer) } + } + + /// Combines the values of all the given properties, in the manner described + /// by `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D) -> Property<(A.Value, B.Value, C.Value, D.Value)> where Value == A.Value { + return a.lift { SignalProducer.combineLatest($0, b.producer, c.producer, d.producer) } + } + + /// Combines the values of all the given properties, in the manner described + /// by `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value)> where Value == A.Value { + return a.lift { SignalProducer.combineLatest($0, b.producer, c.producer, d.producer, e.producer) } + } + + /// Combines the values of all the given properties, in the manner described + /// by `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value)> where Value == A.Value { + return a.lift { SignalProducer.combineLatest($0, b.producer, c.producer, d.producer, e.producer, f.producer) } + } + + /// Combines the values of all the given properties, in the manner described + /// by `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value)> where Value == A.Value { + return a.lift { SignalProducer.combineLatest($0, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer) } + } + + /// Combines the values of all the given properties, in the manner described + /// by `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value)> where Value == A.Value { + return a.lift { SignalProducer.combineLatest($0, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer) } + } + + /// Combines the values of all the given properties, in the manner described + /// by `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value)> where Value == A.Value { + return a.lift { SignalProducer.combineLatest($0, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer, i.producer) } + } + + /// Combines the values of all the given properties, in the manner described + /// by `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I, _ j: J) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value, J.Value)> where Value == A.Value { + return a.lift { SignalProducer.combineLatest($0, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer, i.producer, j.producer) } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. Returns nil if the sequence is empty. + public static func combineLatest(_ properties: S) -> Property<[S.Iterator.Element.Value]>? where S.Iterator.Element: PropertyProtocol { + let producers = properties.map { $0.producer } + guard !producers.isEmpty else { + return nil + } + + return Property(unsafeProducer: SignalProducer.combineLatest(producers)) + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B) -> Property<(A.Value, B.Value)> where Value == A.Value { + return a.lift { SignalProducer.zip($0, b.producer) } + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C) -> Property<(A.Value, B.Value, C.Value)> where Value == A.Value { + return a.lift { SignalProducer.zip($0, b.producer, c.producer) } + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D) -> Property<(A.Value, B.Value, C.Value, D.Value)> where Value == A.Value { + return a.lift { SignalProducer.zip($0, b.producer, c.producer, d.producer) } + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value)> where Value == A.Value { + return a.lift { SignalProducer.zip($0, b.producer, c.producer, d.producer, e.producer) } + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value)> where Value == A.Value { + return a.lift { SignalProducer.zip($0, b.producer, c.producer, d.producer, e.producer, f.producer) } + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value)> where Value == A.Value { + return a.lift { SignalProducer.zip($0, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer) } + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value)> where Value == A.Value { + return a.lift { SignalProducer.zip($0, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer) } + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value)> where Value == A.Value { + return a.lift { SignalProducer.zip($0, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer, i.producer) } + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I, _ j: J) -> Property<(A.Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value, J.Value)> where Value == A.Value { + return a.lift { SignalProducer.zip($0, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer, i.producer, j.producer) } + } + + /// Zips the values of all the given properties, in the manner described by + /// `zip(with:)`. Returns nil if the sequence is empty. + public static func zip(_ properties: S) -> Property<[S.Iterator.Element.Value]>? where S.Iterator.Element: PropertyProtocol { + let producers = properties.map { $0.producer } + guard !producers.isEmpty else { + return nil + } + + return Property(unsafeProducer: SignalProducer.zip(producers)) + } +} + +extension PropertyProtocol where Value == Bool { + /// Create a property that computes a logical NOT in the latest values of `self`. + /// + /// - returns: A property that contains the logial NOT results. + public func negate() -> Property { + return self.lift { $0.negate() } + } + + /// Create a property that computes a logical AND between the latest values of `self` + /// and `property`. + /// + /// - parameters: + /// - property: Property to be combined with `self`. + /// + /// - returns: A property that contains the logial AND results. + public func and(_ property: Property) -> Property { + return self.lift(SignalProducer.and)(property) + } + + /// Create a property that computes a logical OR between the latest values of `self` + /// and `property`. + /// + /// - parameters: + /// - property: Property to be combined with `self`. + /// + /// - returns: A property that contains the logial OR results. + public func or(_ property: Property) -> Property { + return self.lift(SignalProducer.or)(property) + } +} + +/// A read-only property that can be observed for its changes over time. There +/// are three categories of read-only properties: +/// +/// # Constant property +/// Created by `Property(value:)`, the producer and signal of a constant +/// property would complete immediately when it is initialized. +/// +/// # Existential property +/// Created by `Property(capturing:)`, it wraps any arbitrary `PropertyProtocol` +/// types, and passes through the behavior. Note that it would retain the +/// wrapped property. +/// +/// Existential property would be deprecated when generalized existential +/// eventually lands in Swift. +/// +/// # Composed property +/// A composed property presents a composed view of its sources, which can be +/// one or more properties, a producer, or a signal. It can be created using +/// property composition operators, `Property(_:)` or `Property(initial:then:)`. +/// +/// It does not own its lifetime, and its producer and signal are bound to the +/// lifetime of its sources. It also does not have an influence on its sources, +/// so retaining a composed property would not prevent its sources from +/// deinitializing. +/// +/// Note that composed properties do not retain any of its sources. +public final class Property: PropertyProtocol { + private let _value: () -> Value + + /// The current value of the property. + public var value: Value { + return _value() + } + + /// A producer for Signals that will send the property's current + /// value, followed by all changes over time, then complete when the + /// property has deinitialized or has no further changes. + /// + /// - note: If `self` is a composed property, the producer would be + /// bound to the lifetime of its sources. + public let producer: SignalProducer + + /// A signal that will send the property's changes over time, then + /// complete when the property has deinitialized or has no further changes. + /// + /// - note: If `self` is a composed property, the signal would be + /// bound to the lifetime of its sources. + public let signal: Signal + + /// Initializes a constant property. + /// + /// - parameters: + /// - property: A value of the constant property. + public init(value: Value) { + _value = { value } + producer = SignalProducer(value: value) + signal = Signal.empty + } + + /// Initializes an existential property which wraps the given property. + /// + /// - note: The resulting property retains the given property. + /// + /// - parameters: + /// - property: A property to be wrapped. + public init(capturing property: P) where P.Value == Value { + _value = { property.value } + producer = property.producer + signal = property.signal + } + + /// Initializes a composed property which reflects the given property. + /// + /// - note: The resulting property does not retain the given property. + /// + /// - parameters: + /// - property: A property to be wrapped. + public convenience init(_ property: P) where P.Value == Value { + self.init(unsafeProducer: property.producer) + } + + /// Initializes a composed property that first takes on `initial`, then each + /// value sent on a signal created by `producer`. + /// + /// - parameters: + /// - initial: Starting value for the property. + /// - values: A producer that will start immediately and send values to + /// the property. + public convenience init(initial: Value, then values: SignalProducer) { + self.init(unsafeProducer: SignalProducer { observer, lifetime in + observer.send(value: initial) + let disposable = values.start(Signal.Observer(mappingInterruptedToCompleted: observer)) + lifetime.observeEnded(disposable.dispose) + }) + } + + /// Initialize a composed property that first takes on `initial`, then each + /// value sent on `signal`. + /// + /// - parameters: + /// - initialValue: Starting value for the property. + /// - values: A signal that will send values to the property. + public convenience init(initial: Value, then values: Signal) { + self.init(initial: initial, then: SignalProducer(values)) + } + + /// Initialize a composed property from a producer that promises to send + /// at least one value synchronously in its start handler before sending any + /// subsequent event. + /// + /// - important: The producer and the signal of the created property would + /// complete only when the `unsafeProducer` completes. + /// + /// - warning: If the producer fails its promise, a fatal error would be + /// raised. + /// + /// - warning: `unsafeProducer` should not emit any `interrupted` event unless it is + /// a result of being interrupted by the downstream. + /// + /// - parameters: + /// - unsafeProducer: The composed producer for creating the property. + fileprivate init( + unsafeProducer: SignalProducer, + transform: ((Signal.Observer) -> Signal.Observer)? = nil + ) { + // The ownership graph: + // + // ------------ weak ----------- strong ------------------ + // | Upstream | ~~~~~~~~> | Box | <======== | SignalProducer | <=== strong + // ------------ ----------- // ------------------ \\ + // \\ // \\ + // \\ ------------ weak ----------- <== ------------ + // ==> | Observer | ~~~~> | Relay | <=========================== | Property | + // strong ------------ ----------- strong ------------ + + let box = PropertyBox(nil) + var relay: Signal! + + unsafeProducer.startWithSignal { upstream, interruptHandle in + // A composed property tracks its active consumers through its relay signal, and + // interrupts `unsafeProducer` if the relay signal terminates. + let (signal, _observer) = Signal.pipe(disposable: interruptHandle) + let observer = transform?(_observer) ?? _observer + relay = signal + + // `observer` receives `interrupted` only as a result of the termination of + // `signal`, and would not be delivered anyway. So transforming + // `interrupted` to `completed` is unnecessary here. + upstream.observe { [weak box] event in + guard let box = box else { + // Just forward the event, since no one owns the box or IOW no demand + // for a cached latest value. + return observer.action(event) + } + + box.modify(didSet: { _ in observer.action(event) }) { value in + if let newValue = event.value { + value = newValue + } + } + } + } + + // Verify that an initial is sent. This is friendlier than deadlocking + // in the event that one isn't. + guard box.value != nil else { + fatalError("The producer promised to send at least one value. Received none.") + } + + _value = { box.value! } + signal = relay + + producer = SignalProducer { [box, signal = relay!] observer, lifetime in + box.withValue { value in + observer.send(value: value!) + if let d = signal.observe(Signal.Observer(mappingInterruptedToCompleted: observer)) { + lifetime.observeEnded(d.dispose) + } + } + } + } +} + +extension Property where Value: OptionalProtocol { + /// Initializes a composed property that first takes on `initial`, then each + /// value sent on a signal created by `producer`. + /// + /// - parameters: + /// - initial: Starting value for the property. + /// - values: A producer that will start immediately and send values to + /// the property. + public convenience init(initial: Value, then values: SignalProducer) { + self.init(initial: initial, then: values.map(Value.init(reconstructing:))) + } + + /// Initialize a composed property that first takes on `initial`, then each + /// value sent on `signal`. + /// + /// - parameters: + /// - initialValue: Starting value for the property. + /// - values: A signal that will send values to the property. + public convenience init(initial: Value, then values: Signal) { + self.init(initial: initial, then: SignalProducer(values)) + } +} + +/// A mutable property of type `Value` that allows observation of its changes. +/// +/// Instances of this class are thread-safe. +public final class MutableProperty: ComposableMutablePropertyProtocol { + private let token: Lifetime.Token + private let observer: Signal.Observer + private let box: PropertyBox + + /// The current value of the property. + /// + /// Setting this to a new value will notify all observers of `signal`, or + /// signals created using `producer`. + public var value: Value { + get { return box.value } + set { modify { $0 = newValue } } + } + + /// The lifetime of the property. + public let lifetime: Lifetime + + /// A signal that will send the property's changes over time, + /// then complete when the property has deinitialized. + public let signal: Signal + + /// A producer for Signals that will send the property's current value, + /// followed by all changes over time, then complete when the property has + /// deinitialized. + public var producer: SignalProducer { + return SignalProducer { [box, signal] observer, lifetime in + box.withValue { value in + observer.send(value: value) + if let d = signal.observe(Signal.Observer(mappingInterruptedToCompleted: observer)) { + lifetime.observeEnded(d.dispose) + } + } + } + } + + /// Initializes a mutable property that first takes on `initialValue` + /// + /// - parameters: + /// - initialValue: Starting value for the mutable property. + public init(_ initialValue: Value) { + (signal, observer) = Signal.pipe() + token = Lifetime.Token() + lifetime = Lifetime(token) + + /// Need a recursive lock around `value` to allow recursive access to + /// `value`. Note that recursive sets will still deadlock because the + /// underlying producer prevents sending recursive events. + box = PropertyBox(initialValue) + } + + /// Atomically replaces the contents of the variable. + /// + /// - parameters: + /// - newValue: New property value. + /// + /// - returns: The previous property value. + @discardableResult + public func swap(_ newValue: Value) -> Value { + return modify { value in + defer { value = newValue } + return value + } + } + + /// Atomically modifies the variable. + /// + /// - parameters: + /// - action: A closure that accepts old property value and returns a new + /// property value. + /// + /// - returns: The result of the action. + @discardableResult + public func modify(_ action: (inout Value) throws -> Result) rethrows -> Result { + return try box.modify(didSet: { self.observer.send(value: $0) }) { value in + return try action(&value) + } + } + + /// Atomically modifies the variable. + /// + /// - parameters: + /// - didSet: A closure that is invoked after `action` returns and the value is + /// committed to the storage, but before `modify` releases the lock. + /// - action: A closure that accepts old property value and returns a new + /// property value. + /// + /// - returns: The result of the action. + @discardableResult + internal func modify(didSet: () -> Void, _ action: (inout Value) throws -> Result) rethrows -> Result { + return try box.modify(didSet: { self.observer.send(value: $0); didSet() }) { value in + return try action(&value) + } + } + + /// Atomically performs an arbitrary action using the current value of the + /// variable. + /// + /// - parameters: + /// - action: A closure that accepts current property value. + /// + /// - returns: the result of the action. + @discardableResult + public func withValue(_ action: (Value) throws -> Result) rethrows -> Result { + return try box.withValue { try action($0) } + } + + deinit { + observer.sendCompleted() + } +} + +/// A reference counted box which holds a recursive lock and a value storage. +/// +/// The requirement of a `Value?` storage from composed properties prevents further +/// implementation sharing with `MutableProperty`. +private final class PropertyBox { + private let lock: Lock.PthreadLock + private var _value: Value + private var isModifying = false + + var value: Value { return modify { $0 } } + + init(_ value: Value) { + _value = value + lock = Lock.PthreadLock(recursive: true) + } + + func withValue(_ action: (Value) throws -> Result) rethrows -> Result { + lock.lock() + defer { lock.unlock() } + return try action(_value) + } + + func modify(didSet: (Value) -> Void = { _ in }, _ action: (inout Value) throws -> Result) rethrows -> Result { + lock.lock() + guard !isModifying else { fatalError("Nested modifications violate exclusivity of access.") } + isModifying = true + defer { isModifying = false; didSet(_value); lock.unlock() } + return try action(&_value) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Reactive.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Reactive.swift new file mode 100644 index 0000000..e48c02b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Reactive.swift @@ -0,0 +1,33 @@ +/// Describes a provider of reactive extensions. +/// +/// - note: `ReactiveExtensionsProvider` does not indicate whether a type is +/// reactive. It is intended for extensions to types that are not owned +/// by the module in order to avoid name collisions and return type +/// ambiguities. +public protocol ReactiveExtensionsProvider: class {} + +extension ReactiveExtensionsProvider { + /// A proxy which hosts reactive extensions for `self`. + public var reactive: Reactive { + return Reactive(self) + } + + /// A proxy which hosts static reactive extensions for the type of `self`. + public static var reactive: Reactive.Type { + return Reactive.self + } +} + +/// A proxy which hosts reactive extensions of `Base`. +public struct Reactive { + /// The `Base` instance the extensions would be invoked with. + public let base: Base + + /// Construct a proxy + /// + /// - parameters: + /// - base: The object to be proxied. + fileprivate init(_ base: Base) { + self.base = base + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/ReactiveSwift.h b/Carthage/Checkouts/ReactiveSwift/Sources/ReactiveSwift.h new file mode 100644 index 0000000..dde845c --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/ReactiveSwift.h @@ -0,0 +1,15 @@ +// +// ReactiveSwift.h +// ReactiveSwift +// +// Created by Matt Diephouse on 8/15/16. +// Copyright (c) 2016 the ReactiveSwift contributors. All rights reserved. +// + +#import + +//! Project version number for ReactiveSwift. +FOUNDATION_EXPORT double ReactiveSwiftVersionNumber; + +//! Project version string for ReactiveSwift. +FOUNDATION_EXPORT const unsigned char ReactiveSwiftVersionString[]; diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/ResultExtensions.swift b/Carthage/Checkouts/ReactiveSwift/Sources/ResultExtensions.swift new file mode 100644 index 0000000..c0f7143 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/ResultExtensions.swift @@ -0,0 +1,13 @@ +import Result + +/// Private alias of the free `materialize()` from `Result`. +/// +/// This exists because within a `Signal` or `SignalProducer` operator, +/// `materialize()` refers to the operator with that name. +/// Namespacing as `Result.materialize()` doesn't work either, +/// because it tries to resolve a static member on the _type_ +/// `Result`, rather than the free function in the _module_ +/// of the same name. +internal func materialize(_ f: () throws -> T) -> Result { + return materialize(try f()) +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Scheduler.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Scheduler.swift new file mode 100644 index 0000000..659a2a5 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Scheduler.swift @@ -0,0 +1,556 @@ +// +// Scheduler.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-06-02. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +import Dispatch +import Foundation + +#if os(Linux) + import let CDispatch.NSEC_PER_SEC +#endif + +/// Represents a serial queue of work items. +public protocol Scheduler: class { + /// Enqueues an action on the scheduler. + /// + /// When the work is executed depends on the scheduler in use. + /// + /// - parameters: + /// - action: The action to be scheduled. + /// + /// - returns: Optional `Disposable` that can be used to cancel the work + /// before it begins. + @discardableResult + func schedule(_ action: @escaping () -> Void) -> Disposable? +} + +/// A particular kind of scheduler that supports enqueuing actions at future +/// dates. +public protocol DateScheduler: Scheduler { + /// The current date, as determined by this scheduler. + /// + /// This can be implemented to deterministically return a known date (e.g., + /// for testing purposes). + var currentDate: Date { get } + + /// Schedules an action for execution at or after the given date. + /// + /// - parameters: + /// - date: The start date. + /// - action: A closure of the action to be performed. + /// + /// - returns: Optional `Disposable` that can be used to cancel the work + /// before it begins. + @discardableResult + func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? + + /// Schedules a recurring action at the given interval, beginning at the + /// given date. + /// + /// - parameters: + /// - date: The start date. + /// - interval: A repetition interval. + /// - leeway: Some delta for repetition. + /// - action: A closure of the action to be performed. + /// + /// - note: If you plan to specify an `interval` value greater than 200,000 + /// seconds, use `schedule(after:interval:leeway:action)` instead + /// and specify your own `leeway` value to avoid potential overflow. + /// + /// - returns: Optional `Disposable` that can be used to cancel the work + /// before it begins. + @discardableResult + func schedule(after date: Date, interval: DispatchTimeInterval, leeway: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? +} + +/// A scheduler that performs all work synchronously. +public final class ImmediateScheduler: Scheduler { + public init() {} + + /// Immediately calls passed in `action`. + /// + /// - parameters: + /// - action: A closure of the action to be performed. + /// + /// - returns: `nil`. + @discardableResult + public func schedule(_ action: @escaping () -> Void) -> Disposable? { + action() + return nil + } +} + +/// A scheduler that performs all work on the main queue, as soon as possible. +/// +/// If the caller is already running on the main queue when an action is +/// scheduled, it may be run synchronously. However, ordering between actions +/// will always be preserved. +public final class UIScheduler: Scheduler { + private static let dispatchSpecificKey = DispatchSpecificKey() + private static let dispatchSpecificValue = UInt8.max + private static var __once: () = { + DispatchQueue.main.setSpecific(key: UIScheduler.dispatchSpecificKey, + value: dispatchSpecificValue) + }() + + #if os(Linux) + private var queueLength: Atomic = Atomic(0) + #else + // `inout` references do not guarantee atomicity. Use `UnsafeMutablePointer` + // instead. + // + // https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20161205/004147.html + private let queueLength: UnsafeMutablePointer = { + let memory = UnsafeMutablePointer.allocate(capacity: 1) + memory.initialize(to: 0) + return memory + }() + + deinit { + queueLength.deinitialize() + queueLength.deallocate(capacity: 1) + } + #endif + + /// Initializes `UIScheduler` + public init() { + /// This call is to ensure the main queue has been setup appropriately + /// for `UIScheduler`. It is only called once during the application + /// lifetime, since Swift has a `dispatch_once` like mechanism to + /// lazily initialize global variables and static variables. + _ = UIScheduler.__once + } + + /// Queues an action to be performed on main queue. If the action is called + /// on the main thread and no work is queued, no scheduling takes place and + /// the action is called instantly. + /// + /// - parameters: + /// - action: A closure of the action to be performed on the main thread. + /// + /// - returns: `Disposable` that can be used to cancel the work before it + /// begins. + @discardableResult + public func schedule(_ action: @escaping () -> Void) -> Disposable? { + let disposable = AnyDisposable() + let actionAndDecrement = { + if !disposable.isDisposed { + action() + } + + #if os(Linux) + self.queueLength.modify { $0 -= 1 } + #else + OSAtomicDecrement32(self.queueLength) + #endif + } + + #if os(Linux) + let queued = self.queueLength.modify { value -> Int32 in + value += 1 + return value + } + #else + let queued = OSAtomicIncrement32(queueLength) + #endif + + // If we're already running on the main queue, and there isn't work + // already enqueued, we can skip scheduling and just execute directly. + if queued == 1 && DispatchQueue.getSpecific(key: UIScheduler.dispatchSpecificKey) == UIScheduler.dispatchSpecificValue { + actionAndDecrement() + } else { + DispatchQueue.main.async(execute: actionAndDecrement) + } + + return disposable + } +} + +/// A scheduler backed by a serial GCD queue. +public final class QueueScheduler: DateScheduler { + /// A singleton `QueueScheduler` that always targets the main thread's GCD + /// queue. + /// + /// - note: Unlike `UIScheduler`, this scheduler supports scheduling for a + /// future date, and will always schedule asynchronously (even if + /// already running on the main thread). + public static let main = QueueScheduler(internalQueue: DispatchQueue.main) + + public var currentDate: Date { + return Date() + } + + public let queue: DispatchQueue + + internal init(internalQueue: DispatchQueue) { + queue = internalQueue + } + + /// Initializes a scheduler that will target the given queue with its + /// work. + /// + /// - note: Even if the queue is concurrent, all work items enqueued with + /// the `QueueScheduler` will be serial with respect to each other. + /// + /// - warning: Obsoleted in OS X 10.11 + @available(OSX, deprecated:10.10, obsoleted:10.11, message:"Use init(qos:name:targeting:) instead") + @available(iOS, deprecated:8.0, obsoleted:9.0, message:"Use init(qos:name:targeting:) instead.") + public convenience init(queue: DispatchQueue, name: String = "org.reactivecocoa.ReactiveSwift.QueueScheduler") { + self.init(internalQueue: DispatchQueue(label: name, target: queue)) + } + + /// Initializes a scheduler that creates a new serial queue with the + /// given quality of service class. + /// + /// - parameters: + /// - qos: Dispatch queue's QoS value. + /// - name: A name for the queue in the form of reverse domain. + /// - targeting: (Optional) The queue on which this scheduler's work is + /// targeted + @available(OSX 10.10, *) + public convenience init( + qos: DispatchQoS = .default, + name: String = "org.reactivecocoa.ReactiveSwift.QueueScheduler", + targeting targetQueue: DispatchQueue? = nil + ) { + self.init(internalQueue: DispatchQueue( + label: name, + qos: qos, + target: targetQueue + )) + } + + /// Schedules action for dispatch on internal queue + /// + /// - parameters: + /// - action: A closure of the action to be scheduled. + /// + /// - returns: `Disposable` that can be used to cancel the work before it + /// begins. + @discardableResult + public func schedule(_ action: @escaping () -> Void) -> Disposable? { + let d = AnyDisposable() + + queue.async { + if !d.isDisposed { + action() + } + } + + return d + } + + private func wallTime(with date: Date) -> DispatchWallTime { + let (seconds, frac) = modf(date.timeIntervalSince1970) + + let nsec: Double = frac * Double(NSEC_PER_SEC) + let walltime = timespec(tv_sec: Int(seconds), tv_nsec: Int(nsec)) + + return DispatchWallTime(timespec: walltime) + } + + /// Schedules an action for execution at or after the given date. + /// + /// - parameters: + /// - date: The start date. + /// - action: A closure of the action to be performed. + /// + /// - returns: Optional `Disposable` that can be used to cancel the work + /// before it begins. + @discardableResult + public func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? { + let d = AnyDisposable() + + queue.asyncAfter(wallDeadline: wallTime(with: date)) { + if !d.isDisposed { + action() + } + } + + return d + } + + /// Schedules a recurring action at the given interval and beginning at the + /// given start date. A reasonable default timer interval leeway is + /// provided. + /// + /// - parameters: + /// - date: A date to schedule the first action for. + /// - interval: A repetition interval. + /// - action: Closure of the action to repeat. + /// + /// - note: If you plan to specify an `interval` value greater than 200,000 + /// seconds, use `schedule(after:interval:leeway:action)` instead + /// and specify your own `leeway` value to avoid potential overflow. + /// + /// - returns: Optional disposable that can be used to cancel the work + /// before it begins. + @discardableResult + public func schedule(after date: Date, interval: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? { + // Apple's "Power Efficiency Guide for Mac Apps" recommends a leeway of + // at least 10% of the timer interval. + return schedule(after: date, interval: interval, leeway: interval * 0.1, action: action) + } + + /// Schedules a recurring action at the given interval with provided leeway, + /// beginning at the given start time. + /// + /// - precondition: `interval` must be non-negative number. + /// - precondition: `leeway` must be non-negative number. + /// + /// - parameters: + /// - date: A date to schedule the first action for. + /// - interval: A repetition interval. + /// - leeway: Some delta for repetition interval. + /// - action: A closure of the action to repeat. + /// + /// - returns: Optional `Disposable` that can be used to cancel the work + /// before it begins. + @discardableResult + public func schedule(after date: Date, interval: DispatchTimeInterval, leeway: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? { + precondition(interval.timeInterval >= 0) + precondition(leeway.timeInterval >= 0) + + let timer = DispatchSource.makeTimerSource( + flags: DispatchSource.TimerFlags(rawValue: UInt(0)), + queue: queue + ) + timer.scheduleRepeating(wallDeadline: wallTime(with: date), + interval: interval, + leeway: leeway) + timer.setEventHandler(handler: action) + timer.resume() + + return AnyDisposable { + timer.cancel() + } + } +} + +/// A scheduler that implements virtualized time, for use in testing. +public final class TestScheduler: DateScheduler { + private final class ScheduledAction { + let date: Date + let action: () -> Void + + init(date: Date, action: @escaping () -> Void) { + self.date = date + self.action = action + } + + func less(_ rhs: ScheduledAction) -> Bool { + return date.compare(rhs.date) == .orderedAscending + } + } + + private let lock = NSRecursiveLock() + private var _currentDate: Date + + /// The virtual date that the scheduler is currently at. + public var currentDate: Date { + let d: Date + + lock.lock() + d = _currentDate + lock.unlock() + + return d + } + + private var scheduledActions: [ScheduledAction] = [] + + /// Initializes a TestScheduler with the given start date. + /// + /// - parameters: + /// - startDate: The start date of the scheduler. + public init(startDate: Date = Date(timeIntervalSinceReferenceDate: 0)) { + lock.name = "org.reactivecocoa.ReactiveSwift.TestScheduler" + _currentDate = startDate + } + + private func schedule(_ action: ScheduledAction) -> Disposable { + lock.lock() + scheduledActions.append(action) + scheduledActions.sort { $0.less($1) } + lock.unlock() + + return AnyDisposable { + self.lock.lock() + self.scheduledActions = self.scheduledActions.filter { $0 !== action } + self.lock.unlock() + } + } + + /// Enqueues an action on the scheduler. + /// + /// - note: The work is executed on `currentDate` as it is understood by the + /// scheduler. + /// + /// - parameters: + /// - action: An action that will be performed on scheduler's + /// `currentDate`. + /// + /// - returns: Optional `Disposable` that can be used to cancel the work + /// before it begins. + @discardableResult + public func schedule(_ action: @escaping () -> Void) -> Disposable? { + return schedule(ScheduledAction(date: currentDate, action: action)) + } + + /// Schedules an action for execution after some delay. + /// + /// - parameters: + /// - delay: A delay for execution. + /// - action: A closure of the action to perform. + /// + /// - returns: Optional disposable that can be used to cancel the work + /// before it begins. + @discardableResult + public func schedule(after delay: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? { + return schedule(after: currentDate.addingTimeInterval(delay), action: action) + } + + /// Schedules an action for execution at or after the given date. + /// + /// - parameters: + /// - date: A starting date. + /// - action: A closure of the action to perform. + /// + /// - returns: Optional disposable that can be used to cancel the work + /// before it begins. + @discardableResult + public func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? { + return schedule(ScheduledAction(date: date, action: action)) + } + + /// Schedules a recurring action at the given interval, beginning at the + /// given start date. + /// + /// - precondition: `interval` must be non-negative. + /// + /// - parameters: + /// - date: A date to schedule the first action for. + /// - interval: A repetition interval. + /// - disposable: A disposable. + /// - action: A closure of the action to repeat. + /// + /// - note: If you plan to specify an `interval` value greater than 200,000 + /// seconds, use `schedule(after:interval:leeway:action)` instead + /// and specify your own `leeway` value to avoid potential overflow. + /// + /// - returns: Optional `Disposable` that can be used to cancel the work + /// before it begins. + private func schedule(after date: Date, interval: DispatchTimeInterval, disposable: SerialDisposable, action: @escaping () -> Void) { + precondition(interval.timeInterval >= 0) + + disposable.inner = schedule(after: date) { [unowned self] in + action() + self.schedule(after: date.addingTimeInterval(interval), interval: interval, disposable: disposable, action: action) + } + } + + /// Schedules a recurring action after given delay repeated at the given, + /// interval, beginning at the given interval counted from `currentDate`. + /// + /// - parameters: + /// - delay: A delay for action's dispatch. + /// - interval: A repetition interval. + /// - leeway: Some delta for repetition interval. + /// - action: A closure of the action to repeat. + /// + /// - returns: Optional `Disposable` that can be used to cancel the work + /// before it begins. + @discardableResult + public func schedule(after delay: DispatchTimeInterval, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = .seconds(0), action: @escaping () -> Void) -> Disposable? { + return schedule(after: currentDate.addingTimeInterval(delay), interval: interval, leeway: leeway, action: action) + } + + /// Schedules a recurring action at the given interval with + /// provided leeway, beginning at the given start date. + /// + /// - parameters: + /// - date: A date to schedule the first action for. + /// - interval: A repetition interval. + /// - leeway: Some delta for repetition interval. + /// - action: A closure of the action to repeat. + /// + /// - returns: Optional `Disposable` that can be used to cancel the work + /// before it begins. + public func schedule(after date: Date, interval: DispatchTimeInterval, leeway: DispatchTimeInterval = .seconds(0), action: @escaping () -> Void) -> Disposable? { + let disposable = SerialDisposable() + schedule(after: date, interval: interval, disposable: disposable, action: action) + return disposable + } + + /// Advances the virtualized clock by an extremely tiny interval, dequeuing + /// and executing any actions along the way. + /// + /// This is intended to be used as a way to execute actions that have been + /// scheduled to run as soon as possible. + public func advance() { + advance(by: .nanoseconds(1)) + } + + /// Advances the virtualized clock by the given interval, dequeuing and + /// executing any actions along the way. + /// + /// - parameters: + /// - interval: Interval by which the current date will be advanced. + public func advance(by interval: DispatchTimeInterval) { + lock.lock() + advance(to: currentDate.addingTimeInterval(interval)) + lock.unlock() + } + + /// Advances the virtualized clock to the given future date, dequeuing and + /// executing any actions up until that point. + /// + /// - parameters: + /// - newDate: Future date to which the virtual clock will be advanced. + public func advance(to newDate: Date) { + lock.lock() + + assert(currentDate.compare(newDate) != .orderedDescending) + + while scheduledActions.count > 0 { + if newDate.compare(scheduledActions[0].date) == .orderedAscending { + break + } + + _currentDate = scheduledActions[0].date + + let scheduledAction = scheduledActions.remove(at: 0) + scheduledAction.action() + } + + _currentDate = newDate + + lock.unlock() + } + + /// Dequeues and executes all scheduled actions, leaving the scheduler's + /// date at `Date.distantFuture()`. + public func run() { + advance(to: Date.distantFuture) + } + + /// Rewinds the virtualized clock by the given interval. + /// This simulates that user changes device date. + /// + /// - parameters: + /// - interval: An interval by which the current date will be retreated. + public func rewind(by interval: DispatchTimeInterval) { + lock.lock() + + let newDate = currentDate.addingTimeInterval(-interval) + assert(currentDate.compare(newDate) != .orderedAscending) + _currentDate = newDate + + lock.unlock() + + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/Signal.swift b/Carthage/Checkouts/ReactiveSwift/Sources/Signal.swift new file mode 100644 index 0000000..331a7ca --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/Signal.swift @@ -0,0 +1,2669 @@ +import Foundation +import Result + +/// A push-driven stream that sends Events over time, parameterized by the type +/// of values being sent (`Value`) and the type of failure that can occur +/// (`Error`). If no failures should be possible, NoError can be specified for +/// `Error`. +/// +/// An observer of a Signal will see the exact same sequence of events as all +/// other observers. In other words, events will be sent to all observers at the +/// same time. +/// +/// Signals are generally used to represent event streams that are already “in +/// progress,” like notifications, user input, etc. To represent streams that +/// must first be _started_, see the SignalProducer type. +/// +/// A Signal is kept alive until either of the following happens: +/// 1. its input observer receives a terminating event; or +/// 2. it has no active observers, and is not being retained. +public final class Signal { + /// The `Signal` core which manages the event stream. + /// + /// A `Signal` is the externally retained shell of the `Signal` core. The separation + /// enables an explicit metric for the `Signal` self-disposal in case of having no + /// observer and no external retain. + /// + /// `Signal` ownership graph from the perspective of an operator. + /// Note that there is no circular strong reference in the graph. + /// ``` + /// ------------ -------------- -------- + /// | | | endObserve | | | + /// | | <~~ weak ~~~ | disposable | <== strong === | | + /// | | -------------- | | ... downstream(s) + /// | Upstream | ------------ | | + /// | Core | === strong ==> | Observer | === strong ==> | Core | + /// ------------ ===\\ ------------ -------- ===\\ + /// \\ ------------------ ^^ \\ + /// \\ | Signal (shell) | === strong ==// \\ + /// \\ ------------------ \\ + /// || strong || strong + /// vv vv + /// ------------------- ------------------- + /// | Other observers | | Other observers | + /// ------------------- ------------------- + /// ``` + private let core: Core + + private final class Core { + private enum OperationResult { + case shouldDispose + case shouldTryCommitTermination + case none + } + + /// The disposable associated with the signal. + private let disposable: SerialDisposable + + /// The state of the signal. + /// + /// `state` synchronizes using Read-Copy-Update. Reads on the event delivery + /// routine are thus wait-free. But modifications, e.g. inserting observers, + /// still have to be serialized, and are required not to mutate in place. + /// + /// This suits `Signal` as reads to `status` happens on the critical path of + /// event delivery, while observers bag manipulation or termination generally + /// has a constant occurrence. + /// + /// As `SignalState` is a packed object reference (a tagged pointer) that is + /// naturally aligned, reads to are guaranteed to be atomic on all supported + /// hardware architectures of Swift (ARM and x86). + /// + /// # Thread Safety Notes + /// + /// - Check if the signal is at a specific state. + /// * Read directly. + /// + /// - Deliver `value` events with the alive state. + /// * `sendLock` must be acquired. + /// + /// - Replace the alive state with another. (e.g. observers bag manipulation) + /// * `updateLock` must be acquired. + /// + /// - Transition from `alive` to `terminating` as a result of receiving + /// a termination event. + /// * `updateLock` must be acquired, and should fail gracefully if the + /// signal has terminated. + /// + /// - Check if the signal is terminating. If it is, invoke `tryTerminate` + /// which transitions the state from `terminating` to `terminated`, and + /// delivers the termination event. + /// * Both `sendLock` and `updateLock` must be acquired. The check can be + /// relaxed, but the state must be checked again after the locks are + /// acquired. Fail gracefully if the state has changed since the relaxed + /// read, i.e. a concurrent sender has already handled the termination + /// event. + /// + /// Exploiting the relaxation of reads, please note that false positives + /// are intentionally allowed in the `terminating` checks below. As a + /// result, normal event deliveries need not acquire `updateLock`. + /// Nevertheless, this should not cause the termination event being + /// sent multiple times, since `tryTerminate` would not respond to false + /// positives. + private var state: State + + /// Used to ensure that state updates are serialized. + private let updateLock: Lock + + /// Used to ensure that events are serialized during delivery to observers. + private let sendLock: Lock + + /// Used to indicate if the `Signal` has deinitialized. + private var hasDeinitialized: Bool + + fileprivate init(_ generator: (Observer) -> Disposable?) { + state = .alive(AliveState()) + + updateLock = Lock.make() + sendLock = Lock.make() + + hasDeinitialized = false + disposable = SerialDisposable() + + // The generator observer retains the `Signal` core. + disposable.inner = generator(Observer(self.send)) + } + + private func send(_ event: Event) { + if event.isTerminating { + // Recursive events are disallowed for `value` events, but are permitted + // for termination events. Specifically: + // + // - `interrupted` + // It can inadvertently be sent by downstream consumers as part of the + // `SignalProducer` mechanics. + // + // - `completed` + // If a downstream consumer weakly references an object, invocation of + // such consumer may cause a race condition with its weak retain against + // the last strong release of the object. If the `Lifetime` of the + // object is being referenced by an upstream `take(during:)`, a + // signal recursion might occur. + // + // So we would treat termination events specially. If it happens to + // occur while the `sendLock` is acquired, the observer call-out and + // the disposal would be delegated to the current sender, or + // occasionally one of the senders waiting on `sendLock`. + + self.updateLock.lock() + + if case let .alive(state) = self.state { + let newSnapshot = TerminatingState(observers: state.observers, event: event) + self.state = .terminating(newSnapshot) + self.updateLock.unlock() + + // Check whether the terminating state has been handled by a + // concurrent sender. If not, handle it. + if self.tryToCommitTermination() == .shouldDispose { + self.disposable.dispose() + } + } else { + self.updateLock.unlock() + } + } else { + var result = OperationResult.none + + // The `terminating` status check is performed twice for two different + // purposes: + // + // 1. Within the main protected section + // It guarantees that a recursive termination event sent by a + // downstream consumer, is immediately processed and need not compete + // with concurrent pending senders (if any). + // + // Termination events sent concurrently may also be caught here, but + // not necessarily all of them due to data races. + // + // 2. After the main protected section + // It ensures the termination event sent concurrently that are not + // caught by (1) due to data races would still be processed. + // + // The related PR on the race conditions: + // https://github.com/ReactiveCocoa/ReactiveSwift/pull/112 + + self.sendLock.lock() + + if case let .alive(state) = self.state { + for observer in state.observers { + observer.action(event) + } + + // Check if the status has been bumped to `terminating` due to a + // concurrent or a recursive termination event. + if case .terminating = self.state { + result = self.tryToCommitTermination(acquired: self.sendLock) + } + } + + self.sendLock.unlock() + + // Check if the status has been bumped to `terminating` due to a + // concurrent termination event that has not been caught in the main + // protected section. + if result == .none, case .terminating = self.state { + result = self.tryToCommitTermination() + } + + // Dispose only after notifying observers, so disposal + // logic is consistently the last thing to run. + if result == .shouldDispose { + self.disposable.dispose() + } + } + } + + /// Observe the Signal by sending any future events to the given observer. + /// + /// - parameters: + /// - observer: An observer to forward the events to. + /// + /// - returns: A `Disposable` which can be used to disconnect the observer, + /// or `nil` if the signal has already terminated. + fileprivate func observe(_ observer: Observer) -> Disposable? { + var token: Bag.Token? + + updateLock.lock() + + if case let .alive(state) = state { + token = state.observers.insert(observer) + } + + updateLock.unlock() + + if let token = token { + return AnyDisposable { [weak self] in + self?.removeObserver(with: token) + } + } else { + observer.sendInterrupted() + return nil + } + } + + /// Remove the observer associated with the given token. + /// + /// - parameters: + /// - token: The token of the observer to remove. + private func removeObserver(with token: Bag.Token) { + updateLock.lock() + + if case let .alive(state) = state { + var observers = state.observers + let observer = observers.remove(using: token) + state.observers = observers + + var result = OperationResult.none + + // Ensure `observer` is deallocated after `updateLock` is + // released to avoid deadlocks. + withExtendedLifetime(observer) { + // Start the disposal of the `Signal` core if the `Signal` has + // deinitialized and there is no active observer. + result = tryToDisposeSilentlyIfQualified() + + updateLock.unlock() + } + + if result == .shouldTryCommitTermination { + result = tryToCommitTermination() + } + + if result == .shouldDispose { + // Disposing of `disposable` is assumed to remove the generator + // observer from its attached `Signal`, so that the generator observer + // as the last +1 retain of the `Signal` core may deinitialize. + disposable.dispose() + } + } else { + updateLock.unlock() + } + } + + /// Try to commit the termination, or in other words transition the signal from a + /// terminating state to a terminated state. + /// + /// It fails gracefully if the signal is alive or has terminated. Calling this + /// method as a result of a false positive `terminating` check is permitted. + /// + /// - precondition: `updateLock` must not be acquired by the caller. + /// + /// - parameters: + /// - sendLock: `sendLock` if the caller has acquired it. If not specified, + /// `tryTerminate` would attempt to acquire the `sendLock`. + /// + /// - returns: `.shouldDispose` if the attempt succeeds. `.none` otherwise. + private func tryToCommitTermination(acquired sendLock: Lock? = nil) -> OperationResult { + assert(sendLock == nil || sendLock === self.sendLock, + "`tryTerminate` receives a lock that is not the `sendLock` of the signal.") + func commit() -> OperationResult { + // Acquire `updateLock`. If the termination has still not yet been + // handled, take it over and bump the status to `terminated`. + self.updateLock.lock() + + if case let .terminating(state) = self.state { + self.state = .terminated + self.updateLock.unlock() + + if let event = state.event { + for observer in state.observers { + observer.action(event) + } + } + + return .shouldDispose + } + + self.updateLock.unlock() + return .none + } + + // If the caller declares prior acquisition of `sendLock`, go straight to + // the termination committing routine. + guard sendLock == nil else { + return commit() + } + + guard self.sendLock.try() else { + // The current sender would commit the termination anyway. + return .none + } + + defer { self.sendLock.unlock() } + return commit() + } + + /// Try to dispose of the signal silently if the `Signal` has deinitialized and + /// has no observer. + /// + /// It fails gracefully if the signal is terminating or terminated, has one or + /// more observers, or has not deinitialized. + /// + /// - precondition: `updateLock` must have been acquired by the caller. + /// + /// - returns: `.shouldDispose` if the signal has terminated immediately. + /// `.shouldTryCommitTermination` if the signal has transitioned to + /// `terminating` state, and the caller should try to commit the + /// termination with `tryToCommitTermination`. `.none` otherwise. + private func tryToDisposeSilentlyIfQualified() -> OperationResult { + assert(!updateLock.try(), "Calling `unconditionallyTerminate` without acquiring `updateLock`.") + + if hasDeinitialized, case let .alive(state) = state, state.observers.isEmpty { + // Transition to `terminated` directly only if there is no event delivery + // on going. + if sendLock.try() { + defer { sendLock.unlock() } + self.state = .terminated + return .shouldDispose + } + + self.state = .terminating(TerminatingState(observers: Bag(), event: nil)) + return .shouldTryCommitTermination + } + + return .none + } + + /// Acknowledge the deinitialization of the `Signal`. + fileprivate func signalDidDeinitialize() { + updateLock.lock() + + // Mark the `Signal` has now deinitialized. + hasDeinitialized = true + + // Attempt to start the disposal of the signal if it has no active observer. + var result = tryToDisposeSilentlyIfQualified() + + updateLock.unlock() + + if result == .shouldTryCommitTermination { + result = tryToCommitTermination() + } + + if result == .shouldDispose { + disposable.dispose() + } + } + + deinit { + disposable.dispose() + } + } + + /// Initialize a Signal that will immediately invoke the given generator, + /// then forward events sent to the given observer. + /// + /// - note: The disposable returned from the closure will be automatically + /// disposed if a terminating event is sent to the observer. The + /// Signal itself will remain alive until the observer is released. + /// + /// - parameters: + /// - generator: A closure that accepts an implicitly created observer + /// that will act as an event emitter for the signal. + public init(_ generator: (Observer) -> Disposable?) { + core = Core(generator) + } + + /// Observe the Signal by sending any future events to the given observer. + /// + /// - note: If the Signal has already terminated, the observer will + /// immediately receive an `interrupted` event. + /// + /// - parameters: + /// - observer: An observer to forward the events to. + /// + /// - returns: A `Disposable` which can be used to disconnect the observer, + /// or `nil` if the signal has already terminated. + @discardableResult + public func observe(_ observer: Observer) -> Disposable? { + return core.observe(observer) + } + + deinit { + core.signalDidDeinitialize() + } + + /// The state of a `Signal`. + /// + /// `SignalState` is guaranteed to be laid out as a tagged pointer by the Swift + /// compiler in the support targets of the Swift 3.0.1 ABI. + /// + /// The Swift compiler has also an optimization for enums with payloads that are + /// all reference counted, and at most one no-payload case. + private enum State { + /// The `Signal` is alive. + case alive(AliveState) + + /// The `Signal` has received a termination event, and is about to be + /// terminated. + case terminating(TerminatingState) + + /// The `Signal` has terminated. + case terminated + } + + // As the amount of state would definitely span over a cache line, + // `AliveState` and `TerminatingState` is set to be a reference type so + // that we can atomically update the reference instead. + + /// The state of a `Signal` that is alive. It contains a bag of observers and + /// an optional self-retaining reference. + private final class AliveState { + /// The observers of the `Signal`. + /// + /// - note: Since `Bag` is a copy-on-write collection, writes can be done safety + /// as long as `updateLock` is acquired. + fileprivate var observers: Bag + + /// Create an alive state. + init() { + self.observers = Bag() + } + } + + /// The state of a terminating `Signal`. It contains a bag of observers and the + /// termination event. + private final class TerminatingState { + /// The observers of the `Signal`. + fileprivate let observers: Bag + + /// The termination event. + fileprivate let event: Event? + + /// Create a terminating state. + /// + /// - parameters: + /// - observers: The latest bag of observers. + /// - event: The termination event. + init(observers: Bag, event: Event?) { + self.observers = observers + self.event = event + } + } +} + +extension Signal { + /// A Signal that never sends any events to its observers. + public static var never: Signal { + return self.init { _ in nil } + } + + /// A Signal that completes immediately without emitting any value. + public static var empty: Signal { + return self.init { observer in + observer.sendCompleted() + return nil + } + } + + /// Create a `Signal` that will be controlled by sending events to an + /// input observer. + /// + /// - note: The `Signal` will remain alive until a terminating event is sent + /// to the input observer, or until it has no observers and there + /// are no strong references to it. + /// + /// - parameters: + /// - disposable: An optional disposable to associate with the signal, and + /// to be disposed of when the signal terminates. + /// + /// - returns: A tuple of `output: Signal`, the output end of the pipe, + /// and `input: Observer`, the input end of the pipe. + public static func pipe(disposable: Disposable? = nil) -> (output: Signal, input: Observer) { + var observer: Observer! + let signal = self.init { innerObserver in + observer = innerObserver + return disposable + } + + return (signal, observer) + } +} + +public protocol SignalProtocol: class { + /// The type of values being sent by `self`. + associatedtype Value + + /// The type of error that can occur on `self`. + associatedtype Error: Swift.Error + + /// The materialized `self`. + var signal: Signal { get } +} + +extension Signal: SignalProtocol { + public var signal: Signal { + return self + } +} + +extension Signal: SignalProducerConvertible { + public var producer: SignalProducer { + return SignalProducer(self) + } +} + +extension Signal { + /// Observe `self` for all events being emitted. + /// + /// - note: If `self` has terminated, the closure would be invoked with an + /// `interrupted` event immediately. + /// + /// - parameters: + /// - action: A closure to be invoked with every event from `self`. + /// + /// - returns: A disposable to detach `action` from `self`. `nil` if `self` has + /// terminated. + @discardableResult + public func observe(_ action: @escaping Signal.Observer.Action) -> Disposable? { + return observe(Observer(action)) + } + + /// Observe `self` for all values being emitted, and if any, the failure. + /// + /// - parameters: + /// - action: A closure to be invoked with values from `self`, or the propagated + /// error should any `failed` event is emitted. + /// + /// - returns: A disposable to detach `action` from `self`. `nil` if `self` has + /// terminated. + @discardableResult + public func observeResult(_ action: @escaping (Result) -> Void) -> Disposable? { + return observe( + Observer( + value: { action(.success($0)) }, + failed: { action(.failure($0)) } + ) + ) + } + + /// Observe `self` for its completion. + /// + /// - parameters: + /// - action: A closure to be invoked when a `completed` event is emitted. + /// + /// - returns: A disposable to detach `action` from `self`. `nil` if `self` has + /// terminated. + @discardableResult + public func observeCompleted(_ action: @escaping () -> Void) -> Disposable? { + return observe(Observer(completed: action)) + } + + /// Observe `self` for its failure. + /// + /// - parameters: + /// - action: A closure to be invoked with the propagated error, should any + /// `failed` event is emitted. + /// + /// - returns: A disposable to detach `action` from `self`. `nil` if `self` has + /// terminated. + @discardableResult + public func observeFailed(_ action: @escaping (Error) -> Void) -> Disposable? { + return observe(Observer(failed: action)) + } + + /// Observe `self` for its interruption. + /// + /// - note: If `self` has terminated, the closure would be invoked immediately. + /// + /// - parameters: + /// - action: A closure to be invoked when an `interrupted` event is emitted. + /// + /// - returns: A disposable to detach `action` from `self`. `nil` if `self` has + /// terminated. + @discardableResult + public func observeInterrupted(_ action: @escaping () -> Void) -> Disposable? { + return observe(Observer(interrupted: action)) + } +} + +extension Signal where Error == NoError { + /// Observe `self` for all values being emitted. + /// + /// - parameters: + /// - action: A closure to be invoked with values from `self`. + /// + /// - returns: A disposable to detach `action` from `self`. `nil` if `self` has + /// terminated. + @discardableResult + public func observeValues(_ action: @escaping (Value) -> Void) -> Disposable? { + return observe(Observer(value: action)) + } +} + +extension Signal { + /// Map each value in the signal to a new value. + /// + /// - parameters: + /// - transform: A closure that accepts a value from the `value` event and + /// returns a new value. + /// + /// - returns: A signal that will send new values. + public func map(_ transform: @escaping (Value) -> U) -> Signal { + return Signal { observer in + return self.observe { event in + observer.action(event.map(transform)) + } + } + } + +#if swift(>=3.2) + /// Map each value in the signal to a new value by applying a key path. + /// + /// - parameters: + /// - keyPath: A key path relative to the signal's `Value` type. + /// + /// - returns: A signal that will send new values. + public func map(_ keyPath: KeyPath) -> Signal { + return map { $0[keyPath: keyPath] } + } +#endif + + /// Map errors in the signal to a new error. + /// + /// - parameters: + /// - transform: A closure that accepts current error object and returns + /// a new type of error object. + /// + /// - returns: A signal that will send new type of errors. + public func mapError(_ transform: @escaping (Error) -> F) -> Signal { + return Signal { observer in + return self.observe { event in + observer.action(event.mapError(transform)) + } + } + } + + /// Maps each value in the signal to a new value, lazily evaluating the + /// supplied transformation on the specified scheduler. + /// + /// - important: Unlike `map`, there is not a 1-1 mapping between incoming + /// values, and values sent on the returned signal. If + /// `scheduler` has not yet scheduled `transform` for + /// execution, then each new value will replace the last one as + /// the parameter to `transform` once it is finally executed. + /// + /// - parameters: + /// - transform: The closure used to obtain the returned value from this + /// signal's underlying value. + /// + /// - returns: A signal that sends values obtained using `transform` as this + /// signal sends values. + public func lazyMap(on scheduler: Scheduler, transform: @escaping (Value) -> U) -> Signal { + return flatMap(.latest) { value in + return SignalProducer({ transform(value) }) + .start(on: scheduler) + } + } + + /// Preserve only values which pass the given closure. + /// + /// - parameters: + /// - isIncluded: A closure to determine whether a value from `self` should be + /// included in the returned `Signal`. + /// + /// - returns: A signal that forwards the values passing the given closure. + public func filter(_ isIncluded: @escaping (Value) -> Bool) -> Signal { + return Signal { observer in + return self.observe { (event: Event) -> Void in + guard let value = event.value else { + observer.action(event) + return + } + + if isIncluded(value) { + observer.send(value: value) + } + } + } + } + + /// Applies `transform` to values from `signal` and forwards values with non `nil` results unwrapped. + /// - parameters: + /// - transform: A closure that accepts a value from the `value` event and + /// returns a new optional value. + /// + /// - returns: A signal that will send new values, that are non `nil` after the transformation. + public func filterMap(_ transform: @escaping (Value) -> U?) -> Signal { + return Signal { observer in + return self.observe { (event: Event) -> Void in + switch event { + case let .value(value): + if let mapped = transform(value) { + observer.send(value: mapped) + } + case let .failed(error): + observer.send(error: error) + case .completed: + observer.sendCompleted() + case .interrupted: + observer.sendInterrupted() + } + } + } + } +} + +extension Signal where Value: OptionalProtocol { + /// Unwrap non-`nil` values and forward them on the returned signal, `nil` + /// values are dropped. + /// + /// - returns: A signal that sends only non-nil values. + public func skipNil() -> Signal { + return filterMap { $0.optional } + } +} + +extension Signal { + /// Take up to `n` values from the signal and then complete. + /// + /// - precondition: `count` must be non-negative number. + /// + /// - parameters: + /// - count: A number of values to take from the signal. + /// + /// - returns: A signal that will yield the first `count` values from `self` + public func take(first count: Int) -> Signal { + precondition(count >= 0) + + return Signal { observer in + if count == 0 { + observer.sendCompleted() + return nil + } + + var taken = 0 + + return self.observe { event in + guard let value = event.value else { + observer.action(event) + return + } + + if taken < count { + taken += 1 + observer.send(value: value) + } + + if taken == count { + observer.sendCompleted() + } + } + } + } +} + +/// A reference type which wraps an array to auxiliate the collection of values +/// for `collect` operator. +private final class CollectState { + var values: [Value] = [] + + /// Collects a new value. + func append(_ value: Value) { + values.append(value) + } + + /// Check if there are any items remaining. + /// + /// - note: This method also checks if there weren't collected any values + /// and, in that case, it means an empty array should be sent as the + /// result of collect. + var isEmpty: Bool { + /// We use capacity being zero to determine if we haven't collected any + /// value since we're keeping the capacity of the array to avoid + /// unnecessary and expensive allocations). This also guarantees + /// retro-compatibility around the original `collect()` operator. + return values.isEmpty && values.capacity > 0 + } + + /// Removes all values previously collected if any. + func flush() { + // Minor optimization to avoid consecutive allocations. Can + // be useful for sequences of regular or similar size and to + // track if any value was ever collected. + values.removeAll(keepingCapacity: true) + } +} + +extension Signal { + /// Collect all values sent by the signal then forward them as a single + /// array and complete. + /// + /// - note: When `self` completes without collecting any value, it will send + /// an empty array of values. + /// + /// - returns: A signal that will yield an array of values when `self` + /// completes. + public func collect() -> Signal<[Value], Error> { + return collect { _,_ in false } + } + + /// Collect at most `count` values from `self`, forward them as a single + /// array and complete. + /// + /// - note: When the count is reached the array is sent and the signal + /// starts over yielding a new array of values. + /// + /// - note: When `self` completes any remaining values will be sent, the + /// last array may not have `count` values. Alternatively, if were + /// not collected any values will sent an empty array of values. + /// + /// - precondition: `count` should be greater than zero. + /// + public func collect(count: Int) -> Signal<[Value], Error> { + precondition(count > 0) + return collect { values in values.count == count } + } + + /// Collect values from `self`, and emit them if the predicate passes. + /// + /// When `self` completes any remaining values will be sent, regardless of the + /// collected values matching `shouldEmit` or not. + /// + /// If `self` completes without having emitted any value, an empty array would be + /// emitted, followed by the completion of the returned `Signal`. + /// + /// ```` + /// let (signal, observer) = Signal.pipe() + /// + /// signal + /// .collect { values in values.reduce(0, combine: +) == 8 } + /// .observeValues { print($0) } + /// + /// observer.send(value: 1) + /// observer.send(value: 3) + /// observer.send(value: 4) + /// observer.send(value: 7) + /// observer.send(value: 1) + /// observer.send(value: 5) + /// observer.send(value: 6) + /// observer.sendCompleted() + /// + /// // Output: + /// // [1, 3, 4] + /// // [7, 1] + /// // [5, 6] + /// ```` + /// + /// - parameters: + /// - shouldEmit: A closure to determine, when every time a new value is received, + /// whether the collected values should be emitted. The new value + /// is included in the collected values. + /// + /// - returns: A signal of arrays of values, as instructed by the `shouldEmit` + /// closure. + public func collect(_ shouldEmit: @escaping (_ collectedValues: [Value]) -> Bool) -> Signal<[Value], Error> { + return Signal<[Value], Error> { observer in + let state = CollectState() + + return self.observe { event in + switch event { + case let .value(value): + state.append(value) + if shouldEmit(state.values) { + observer.send(value: state.values) + state.flush() + } + case .completed: + if !state.isEmpty { + observer.send(value: state.values) + } + observer.sendCompleted() + case let .failed(error): + observer.send(error: error) + case .interrupted: + observer.sendInterrupted() + } + } + } + } + + /// Collect values from `self`, and emit them if the predicate passes. + /// + /// When `self` completes any remaining values will be sent, regardless of the + /// collected values matching `shouldEmit` or not. + /// + /// If `self` completes without having emitted any value, an empty array would be + /// emitted, followed by the completion of the returned `Signal`. + /// + /// ```` + /// let (signal, observer) = Signal.pipe() + /// + /// signal + /// .collect { values, value in value == 7 } + /// .observeValues { print($0) } + /// + /// observer.send(value: 1) + /// observer.send(value: 1) + /// observer.send(value: 7) + /// observer.send(value: 7) + /// observer.send(value: 5) + /// observer.send(value: 6) + /// observer.sendCompleted() + /// + /// // Output: + /// // [1, 1] + /// // [7] + /// // [7, 5, 6] + /// ```` + /// + /// - parameters: + /// - shouldEmit: A closure to determine, when every time a new value is received, + /// whether the collected values should be emitted. The new value + /// is **not** included in the collected values, and is included when + /// the next value is received. + /// + /// - returns: A signal of arrays of values, as instructed by the `shouldEmit` + /// closure. + public func collect(_ shouldEmit: @escaping (_ collected: [Value], _ latest: Value) -> Bool) -> Signal<[Value], Error> { + return Signal<[Value], Error> { observer in + let state = CollectState() + + return self.observe { event in + switch event { + case let .value(value): + if shouldEmit(state.values, value) { + observer.send(value: state.values) + state.flush() + } + state.append(value) + case .completed: + if !state.isEmpty { + observer.send(value: state.values) + } + observer.sendCompleted() + case let .failed(error): + observer.send(error: error) + case .interrupted: + observer.sendInterrupted() + } + } + } + } + + /// Forward all events onto the given scheduler, instead of whichever + /// scheduler they originally arrived upon. + /// + /// - parameters: + /// - scheduler: A scheduler to deliver events on. + /// + /// - returns: A signal that will yield `self` values on provided scheduler. + public func observe(on scheduler: Scheduler) -> Signal { + return Signal { observer in + return self.observe { event in + scheduler.schedule { + observer.action(event) + } + } + } + } +} + +extension Signal { + /// Combine the latest value of the receiver with the latest value from the + /// given signal. + /// + /// - note: The returned signal will not send a value until both inputs have + /// sent at least one value each. + /// + /// - note: If either signal is interrupted, the returned signal will also + /// be interrupted. + /// + /// - note: The returned signal will not complete until both inputs + /// complete. + /// + /// - parameters: + /// - otherSignal: A signal to combine `self`'s value with. + /// + /// - returns: A signal that will yield a tuple containing values of `self` + /// and given signal. + public func combineLatest(with other: Signal) -> Signal<(Value, U), Error> { + return Signal.combineLatest(self, other) + } + + /// Delay `value` and `completed` events by the given interval, forwarding + /// them on the given scheduler. + /// + /// - note: failed and `interrupted` events are always scheduled + /// immediately. + /// + /// - precondition: `interval` must be non-negative number. + /// + /// - parameters: + /// - interval: Interval to delay `value` and `completed` events by. + /// - scheduler: A scheduler to deliver delayed events on. + /// + /// - returns: A signal that will delay `value` and `completed` events and + /// will yield them on given scheduler. + public func delay(_ interval: TimeInterval, on scheduler: DateScheduler) -> Signal { + precondition(interval >= 0) + + return Signal { observer in + return self.observe { event in + switch event { + case .failed, .interrupted: + scheduler.schedule { + observer.action(event) + } + + case .value, .completed: + let date = scheduler.currentDate.addingTimeInterval(interval) + scheduler.schedule(after: date) { + observer.action(event) + } + } + } + } + } + + /// Skip first `count` number of values then act as usual. + /// + /// - precondition: `count` must be non-negative number. + /// + /// - parameters: + /// - count: A number of values to skip. + /// + /// - returns: A signal that will skip the first `count` values, then + /// forward everything afterward. + public func skip(first count: Int) -> Signal { + precondition(count >= 0) + + if count == 0 { + return self + } + + return Signal { observer in + var skipped = 0 + + return self.observe { event in + if case .value = event, skipped < count { + skipped += 1 + } else { + observer.action(event) + } + } + } + } + + /// Treat all Events from `self` as plain values, allowing them to be + /// manipulated just like any other value. + /// + /// In other words, this brings Events “into the monad”. + /// + /// - note: When a Completed or Failed event is received, the resulting + /// signal will send the Event itself and then complete. When an + /// Interrupted event is received, the resulting signal will send + /// the Event itself and then interrupt. + /// + /// - returns: A signal that sends events as its values. + public func materialize() -> Signal { + return Signal { observer in + return self.observe { event in + observer.send(value: event) + + switch event { + case .interrupted: + observer.sendInterrupted() + + case .completed, .failed: + observer.sendCompleted() + + case .value: + break + } + } + } + } +} + +extension Signal where Value: EventProtocol, Error == NoError { + /// Translate a signal of `Event` _values_ into a signal of those events + /// themselves. + /// + /// - returns: A signal that sends values carried by `self` events. + public func dematerialize() -> Signal { + return Signal { observer in + return self.observe { event in + switch event { + case let .value(innerEvent): + observer.action(innerEvent.event) + + case .failed: + fatalError("NoError is impossible to construct") + + case .completed: + observer.sendCompleted() + + case .interrupted: + observer.sendInterrupted() + } + } + } + } +} + +extension Signal { + /// Inject side effects to be performed upon the specified signal events. + /// + /// - parameters: + /// - event: A closure that accepts an event and is invoked on every + /// received event. + /// - failed: A closure that accepts error object and is invoked for + /// failed event. + /// - completed: A closure that is invoked for `completed` event. + /// - interrupted: A closure that is invoked for `interrupted` event. + /// - terminated: A closure that is invoked for any terminating event. + /// - disposed: A closure added as disposable when signal completes. + /// - value: A closure that accepts a value from `value` event. + /// + /// - returns: A signal with attached side-effects for given event cases. + public func on( + event: ((Event) -> Void)? = nil, + failed: ((Error) -> Void)? = nil, + completed: (() -> Void)? = nil, + interrupted: (() -> Void)? = nil, + terminated: (() -> Void)? = nil, + disposed: (() -> Void)? = nil, + value: ((Value) -> Void)? = nil + ) -> Signal { + return Signal { observer in + let disposable = CompositeDisposable() + + _ = disposed.map(disposable.add) + + disposable += self.observe { receivedEvent in + event?(receivedEvent) + + switch receivedEvent { + case let .value(v): + value?(v) + + case let .failed(error): + failed?(error) + + case .completed: + completed?() + + case .interrupted: + interrupted?() + } + + if receivedEvent.isTerminating { + terminated?() + } + + observer.action(receivedEvent) + } + + return disposable + } + } +} + +private struct SampleState { + var latestValue: Value? = nil + var isSignalCompleted: Bool = false + var isSamplerCompleted: Bool = false +} + +extension Signal { + /// Forward the latest value from `self` with the value from `sampler` as a + /// tuple, only when`sampler` sends a `value` event. + /// + /// - note: If `sampler` fires before a value has been observed on `self`, + /// nothing happens. + /// + /// - parameters: + /// - sampler: A signal that will trigger the delivery of `value` event + /// from `self`. + /// + /// - returns: A signal that will send values from `self` and `sampler`, + /// sampled (possibly multiple times) by `sampler`, then complete + /// once both input signals have completed, or interrupt if + /// either input signal is interrupted. + public func sample(with sampler: Signal) -> Signal<(Value, T), Error> { + return Signal<(Value, T), Error> { observer in + let state = Atomic(SampleState()) + let disposable = CompositeDisposable() + + disposable += self.observe { event in + switch event { + case let .value(value): + state.modify { + $0.latestValue = value + } + + case let .failed(error): + observer.send(error: error) + + case .completed: + let shouldComplete: Bool = state.modify { + $0.isSignalCompleted = true + return $0.isSamplerCompleted + } + + if shouldComplete { + observer.sendCompleted() + } + + case .interrupted: + observer.sendInterrupted() + } + } + + disposable += sampler.observe { event in + switch event { + case .value(let samplerValue): + if let value = state.value.latestValue { + observer.send(value: (value, samplerValue)) + } + + case .completed: + let shouldComplete: Bool = state.modify { + $0.isSamplerCompleted = true + return $0.isSignalCompleted + } + + if shouldComplete { + observer.sendCompleted() + } + + case .interrupted: + observer.sendInterrupted() + + case .failed: + break + } + } + + return disposable + } + } + + /// Forward the latest value from `self` whenever `sampler` sends a `value` + /// event. + /// + /// - note: If `sampler` fires before a value has been observed on `self`, + /// nothing happens. + /// + /// - parameters: + /// - sampler: A signal that will trigger the delivery of `value` event + /// from `self`. + /// + /// - returns: A signal that will send values from `self`, sampled (possibly + /// multiple times) by `sampler`, then complete once both input + /// signals have completed, or interrupt if either input signal + /// is interrupted. + public func sample(on sampler: Signal<(), NoError>) -> Signal { + return sample(with: sampler) + .map { $0.0 } + } + + /// Forward the latest value from `samplee` with the value from `self` as a + /// tuple, only when `self` sends a `value` event. + /// This is like a flipped version of `sample(with:)`, but `samplee`'s + /// terminal events are completely ignored. + /// + /// - note: If `self` fires before a value has been observed on `samplee`, + /// nothing happens. + /// + /// - parameters: + /// - samplee: A signal whose latest value is sampled by `self`. + /// + /// - returns: A signal that will send values from `self` and `samplee`, + /// sampled (possibly multiple times) by `self`, then terminate + /// once `self` has terminated. **`samplee`'s terminated events + /// are ignored**. + public func withLatest(from samplee: Signal) -> Signal<(Value, U), Error> { + return Signal<(Value, U), Error> { observer in + let state = Atomic(nil) + let disposable = CompositeDisposable() + + disposable += samplee.observeValues { value in + state.value = value + } + + disposable += self.observe { event in + switch event { + case let .value(value): + if let value2 = state.value { + observer.send(value: (value, value2)) + } + case .completed: + observer.sendCompleted() + case let .failed(error): + observer.send(error: error) + case .interrupted: + observer.sendInterrupted() + } + } + + return disposable + } + } + + /// Forward the latest value from `samplee` with the value from `self` as a + /// tuple, only when `self` sends a `value` event. + /// This is like a flipped version of `sample(with:)`, but `samplee`'s + /// terminal events are completely ignored. + /// + /// - note: If `self` fires before a value has been observed on `samplee`, + /// nothing happens. + /// + /// - parameters: + /// - samplee: A producer whose latest value is sampled by `self`. + /// + /// - returns: A signal that will send values from `self` and `samplee`, + /// sampled (possibly multiple times) by `self`, then terminate + /// once `self` has terminated. **`samplee`'s terminated events + /// are ignored**. + public func withLatest(from samplee: SignalProducer) -> Signal<(Value, U), Error> { + return Signal<(Value, U), Error> { observer in + let d = CompositeDisposable() + samplee.startWithSignal { signal, disposable in + d += disposable + d += self.withLatest(from: signal).observe(observer) + } + return d + } + } +} + +extension Signal { + /// Forwards events from `self` until `lifetime` ends, at which point the + /// returned signal will complete. + /// + /// - parameters: + /// - lifetime: A lifetime whose `ended` signal will cause the returned + /// signal to complete. + /// + /// - returns: A signal that will deliver events until `lifetime` ends. + public func take(during lifetime: Lifetime) -> Signal { + return Signal { observer in + let disposable = CompositeDisposable() + disposable += self.observe(observer) + disposable += lifetime.observeEnded(observer.sendCompleted) + return disposable + } + } + + /// Forward events from `self` until `trigger` sends a `value` or + /// `completed` event, at which point the returned signal will complete. + /// + /// - parameters: + /// - trigger: A signal whose `value` or `completed` events will stop the + /// delivery of `value` events from `self`. + /// + /// - returns: A signal that will deliver events until `trigger` sends + /// `value` or `completed` events. + public func take(until trigger: Signal<(), NoError>) -> Signal { + return Signal { observer in + let disposable = CompositeDisposable() + disposable += self.observe(observer) + + disposable += trigger.observe { event in + switch event { + case .value, .completed: + observer.sendCompleted() + + case .failed, .interrupted: + break + } + } + + return disposable + } + } + + /// Do not forward any values from `self` until `trigger` sends a `value` or + /// `completed` event, at which point the returned signal behaves exactly + /// like `signal`. + /// + /// - parameters: + /// - trigger: A signal whose `value` or `completed` events will start the + /// deliver of events on `self`. + /// + /// - returns: A signal that will deliver events once the `trigger` sends + /// `value` or `completed` events. + public func skip(until trigger: Signal<(), NoError>) -> Signal { + return Signal { observer in + let disposable = SerialDisposable() + + disposable.inner = trigger.observe { event in + switch event { + case .value, .completed: + disposable.inner = self.observe(observer) + + case .failed, .interrupted: + break + } + } + + return disposable + } + } + + /// Forward events from `self` with history: values of the returned signal + /// are a tuples whose first member is the previous value and whose second member + /// is the current value. `initial` is supplied as the first member when `self` + /// sends its first value. + /// + /// - parameters: + /// - initial: A value that will be combined with the first value sent by + /// `self`. + /// + /// - returns: A signal that sends tuples that contain previous and current + /// sent values of `self`. + public func combinePrevious(_ initial: Value) -> Signal<(Value, Value), Error> { + return scan((initial, initial)) { previousCombinedValues, newValue in + return (previousCombinedValues.1, newValue) + } + } + + + /// Combine all values from `self`, and forward only the final accumuated result. + /// + /// See `scan(_:_:)` if the resulting producer needs to forward also the partial + /// results. + /// + /// - parameters: + /// - initialResult: The value to use as the initial accumulating value. + /// - nextPartialResult: A closure that combines the accumulating value and the + /// latest value from `self`. The result would be used in the + /// next call of `nextPartialResult`, or emit to the returned + /// `Signal` when `self` completes. + /// + /// - returns: A signal that sends the final result as `self` completes. + public func reduce(_ initialResult: U, _ nextPartialResult: @escaping (U, Value) -> U) -> Signal { + return self.reduce(into: initialResult) { accumulator, value in + accumulator = nextPartialResult(accumulator, value) + } + } + + /// Combine all values from `self`, and forward only the final accumuated result. + /// + /// See `scan(into:_:)` if the resulting producer needs to forward also the partial + /// results. + /// + /// - parameters: + /// - initialResult: The value to use as the initial accumulating value. + /// - nextPartialResult: A closure that combines the accumulating value and the + /// latest value from `self`. The result would be used in the + /// next call of `nextPartialResult`, or emit to the returned + /// `Signal` when `self` completes. + /// + /// - returns: A signal that sends the final result as `self` completes. + public func reduce(into initialResult: U, _ nextPartialResult: @escaping (inout U, Value) -> Void) -> Signal { + // We need to handle the special case in which `signal` sends no values. + // We'll do that by sending `initial` on the output signal (before + // taking the last value). + let (scannedSignalWithInitialValue, outputSignalObserver) = Signal.pipe() + let outputSignal = scannedSignalWithInitialValue.take(last: 1) + + // Now that we've got takeLast() listening to the piped signal, send + + // that initial value. + outputSignalObserver.send(value: initialResult) + + // Pipe the scanned input signal into the output signal. + self.scan(into: initialResult, nextPartialResult) + .observe(outputSignalObserver) + + return outputSignal + } + + /// Combine all values from `self`, and forward the partial results and the final + /// result. + /// + /// See `reduce(_:_:)` if the resulting producer needs to forward only the final + /// result. + /// + /// - parameters: + /// - initialResult: The value to use as the initial accumulating value. + /// - nextPartialResult: A closure that combines the accumulating value and the + /// latest value from `self`. The result would be forwarded, + /// and would be used in the next call of `nextPartialResult`. + /// + /// - returns: A signal that sends the partial results of the accumuation, and the + /// final result as `self` completes. + public func scan(_ initialResult: U, _ nextPartialResult: @escaping (U, Value) -> U) -> Signal { + return self.scan(into: initialResult) { accumulator, value in + accumulator = nextPartialResult(accumulator, value) + } + } + + /// Combine all values from `self`, and forward the partial results and the final + /// result. + /// + /// See `reduce(into:_:)` if the resulting producer needs to forward only the final + /// result. + /// + /// - parameters: + /// - initialResult: The value to use as the initial accumulating value. + /// - nextPartialResult: A closure that combines the accumulating value and the + /// latest value from `self`. The result would be forwarded, + /// and would be used in the next call of `nextPartialResult`. + /// + /// - returns: A signal that sends the partial results of the accumuation, and the + /// final result as `self` completes. + public func scan(into initialResult: U, _ nextPartialResult: @escaping (inout U, Value) -> Void) -> Signal { + return Signal { observer in + var accumulator = initialResult + + return self.observe { event in + observer.action(event.map { value in + nextPartialResult(&accumulator, value) + return accumulator + }) + } + } + } +} + +extension Signal where Value: Equatable { + /// Forward only values from `self` that are not equal to its immediately preceding + /// value. + /// + /// - note: The first value is always forwarded. + /// + /// - returns: A signal which conditionally forwards values from `self`. + public func skipRepeats() -> Signal { + return skipRepeats(==) + } +} + +extension Signal { + /// Forward only values from `self` that are not considered equivalent to its + /// immediately preceding value. + /// + /// - note: The first value is always forwarded. + /// + /// - parameters: + /// - isEquivalent: A closure to determine whether two values are equivalent. + /// + /// - returns: A signal which conditionally forwards values from `self`. + public func skipRepeats(_ isEquivalent: @escaping (Value, Value) -> Bool) -> Signal { + return self + .scan((nil, false)) { (accumulated: (Value?, Bool), next: Value) -> (value: Value?, repeated: Bool) in + switch accumulated.0 { + case nil: + return (next, false) + case let prev? where isEquivalent(prev, next): + return (prev, true) + case _?: + return (Optional(next), false) + } + } + .filter { !$0.repeated } + .filterMap { $0.value } + } + + /// Do not forward any value from `self` until `shouldContinue` returns `false`, at + /// which point the returned signal starts to forward values from `self`, including + /// the one leading to the toggling. + /// + /// - parameters: + /// - shouldContinue: A closure to determine whether the skipping should continue. + /// + /// - returns: A signal which conditionally forwards values from `self`. + public func skip(while shouldContinue: @escaping (Value) -> Bool) -> Signal { + return Signal { observer in + var isSkipping = true + + return self.observe { event in + switch event { + case let .value(value): + isSkipping = isSkipping && shouldContinue(value) + if !isSkipping { + fallthrough + } + + case .failed, .completed, .interrupted: + observer.action(event) + } + } + } + } + + /// Forward events from `self` until `replacement` begins sending events. + /// + /// - parameters: + /// - replacement: A signal to wait to wait for values from and start + /// sending them as a replacement to `self`'s values. + /// + /// - returns: A signal which passes through `value`, failed, and + /// `interrupted` events from `self` until `replacement` sends + /// an event, at which point the returned signal will send that + /// event and switch to passing through events from `replacement` + /// instead, regardless of whether `self` has sent events + /// already. + public func take(untilReplacement signal: Signal) -> Signal { + return Signal { observer in + let disposable = CompositeDisposable() + + let signalDisposable = self.observe { event in + switch event { + case .completed: + break + + case .value, .failed, .interrupted: + observer.action(event) + } + } + + disposable += signalDisposable + disposable += signal.observe { event in + signalDisposable?.dispose() + observer.action(event) + } + + return disposable + } + } + + /// Wait until `self` completes and then forward the final `count` values + /// on the returned signal. + /// + /// - parameters: + /// - count: Number of last events to send after `self` completes. + /// + /// - returns: A signal that receives up to `count` values from `self` + /// after `self` completes. + public func take(last count: Int) -> Signal { + return Signal { observer in + var buffer: [Value] = [] + buffer.reserveCapacity(count) + + return self.observe { event in + switch event { + case let .value(value): + // To avoid exceeding the reserved capacity of the buffer, + // we remove then add. Remove elements until we have room to + // add one more. + while (buffer.count + 1) > count { + buffer.remove(at: 0) + } + + buffer.append(value) + case let .failed(error): + observer.send(error: error) + case .completed: + buffer.forEach(observer.send(value:)) + + observer.sendCompleted() + case .interrupted: + observer.sendInterrupted() + } + } + } + } + + /// Forward any values from `self` until `shouldContinue` returns `false`, at which + /// point the returned signal would complete. + /// + /// - parameters: + /// - shouldContinue: A closure to determine whether the forwarding of values should + /// continue. + /// + /// - returns: A signal which conditionally forwards values from `self`. + public func take(while shouldContinue: @escaping (Value) -> Bool) -> Signal { + return Signal { observer in + return self.observe { event in + if let value = event.value, !shouldContinue(value) { + observer.sendCompleted() + } else { + observer.action(event) + } + } + } + } +} + +extension Signal { + /// Zip elements of two signals into pairs. The elements of any Nth pair + /// are the Nth elements of the two input signals. + /// + /// - parameters: + /// - otherSignal: A signal to zip values with. + /// + /// - returns: A signal that sends tuples of `self` and `otherSignal`. + public func zip(with other: Signal) -> Signal<(Value, U), Error> { + return Signal.zip(self, other) + } + + /// Forward the latest value on `scheduler` after at least `interval` + /// seconds have passed since *the returned signal* last sent a value. + /// + /// If `self` always sends values more frequently than `interval` seconds, + /// then the returned signal will send a value every `interval` seconds. + /// + /// To measure from when `self` last sent a value, see `debounce`. + /// + /// - seealso: `debounce` + /// + /// - note: If multiple values are received before the interval has elapsed, + /// the latest value is the one that will be passed on. + /// + /// - note: If `self` terminates while a value is being throttled, that + /// value will be discarded and the returned signal will terminate + /// immediately. + /// + /// - note: If the device time changed backwards before previous date while + /// a value is being throttled, and if there is a new value sent, + /// the new value will be passed anyway. + /// + /// - precondition: `interval` must be non-negative number. + /// + /// - parameters: + /// - interval: Number of seconds to wait between sent values. + /// - scheduler: A scheduler to deliver events on. + /// + /// - returns: A signal that sends values at least `interval` seconds + /// appart on a given scheduler. + public func throttle(_ interval: TimeInterval, on scheduler: DateScheduler) -> Signal { + precondition(interval >= 0) + + return Signal { observer in + let state: Atomic> = Atomic(ThrottleState()) + let schedulerDisposable = SerialDisposable() + + let disposable = CompositeDisposable() + disposable += schedulerDisposable + + disposable += self.observe { event in + guard let value = event.value else { + schedulerDisposable.inner = scheduler.schedule { + observer.action(event) + } + return + } + + var scheduleDate: Date! + state.modify { + $0.pendingValue = value + + let proposedScheduleDate: Date + if let previousDate = $0.previousDate, previousDate.compare(scheduler.currentDate) != .orderedDescending { + proposedScheduleDate = previousDate.addingTimeInterval(interval) + } else { + proposedScheduleDate = scheduler.currentDate + } + + switch proposedScheduleDate.compare(scheduler.currentDate) { + case .orderedAscending: + scheduleDate = scheduler.currentDate + + case .orderedSame: fallthrough + case .orderedDescending: + scheduleDate = proposedScheduleDate + } + } + + schedulerDisposable.inner = scheduler.schedule(after: scheduleDate) { + let pendingValue: Value? = state.modify { state in + defer { + if state.pendingValue != nil { + state.pendingValue = nil + state.previousDate = scheduleDate + } + } + return state.pendingValue + } + + if let pendingValue = pendingValue { + observer.send(value: pendingValue) + } + } + } + + return disposable + } + } + + /// Conditionally throttles values sent on the receiver whenever + /// `shouldThrottle` is true, forwarding values on the given scheduler. + /// + /// - note: While `shouldThrottle` remains false, values are forwarded on the + /// given scheduler. If multiple values are received while + /// `shouldThrottle` is true, the latest value is the one that will + /// be passed on. + /// + /// - note: If the input signal terminates while a value is being throttled, + /// that value will be discarded and the returned signal will + /// terminate immediately. + /// + /// - note: If `shouldThrottle` completes before the receiver, and its last + /// value is `true`, the returned signal will remain in the throttled + /// state, emitting no further values until it terminates. + /// + /// - parameters: + /// - shouldThrottle: A boolean property that controls whether values + /// should be throttled. + /// - scheduler: A scheduler to deliver events on. + /// + /// - returns: A signal that sends values only while `shouldThrottle` is false. + public func throttle(while shouldThrottle: P, on scheduler: Scheduler) -> Signal + where P.Value == Bool + { + return Signal { observer in + let initial: ThrottleWhileState = .resumed + let state = Atomic(initial) + let schedulerDisposable = SerialDisposable() + + let disposable = CompositeDisposable() + disposable += schedulerDisposable + + disposable += shouldThrottle.producer + .skipRepeats() + .startWithValues { shouldThrottle in + let valueToSend = state.modify { state -> Value? in + guard !state.isTerminated else { return nil } + + if shouldThrottle { + state = .throttled(nil) + } else { + defer { state = .resumed } + + if case let .throttled(value?) = state { + return value + } + } + + return nil + } + + if let value = valueToSend { + schedulerDisposable.inner = scheduler.schedule { + observer.send(value: value) + } + } + } + + disposable += self.observe { event in + let eventToSend = state.modify { state -> Event? in + switch event { + case let .value(value): + switch state { + case .throttled: + state = .throttled(value) + return nil + case .resumed: + return event + case .terminated: + return nil + } + + case .completed, .interrupted, .failed: + state = .terminated + return event + } + } + + if let event = eventToSend { + schedulerDisposable.inner = scheduler.schedule { + observer.action(event) + } + } + } + + return disposable + } + } + + /// Forward the latest value on `scheduler` after at least `interval` + /// seconds have passed since `self` last sent a value. + /// + /// If `self` always sends values more frequently than `interval` seconds, + /// then the returned signal will never send any values. + /// + /// To measure from when the *returned signal* last sent a value, see + /// `throttle`. + /// + /// - seealso: `throttle` + /// + /// - note: If multiple values are received before the interval has elapsed, + /// the latest value is the one that will be passed on. + /// + /// - note: If the input signal terminates while a value is being debounced, + /// that value will be discarded and the returned signal will + /// terminate immediately. + /// + /// - precondition: `interval` must be non-negative number. + /// + /// - parameters: + /// - interval: A number of seconds to wait before sending a value. + /// - scheduler: A scheduler to send values on. + /// + /// - returns: A signal that sends values that are sent from `self` at least + /// `interval` seconds apart. + public func debounce(_ interval: TimeInterval, on scheduler: DateScheduler) -> Signal { + precondition(interval >= 0) + + let d = SerialDisposable() + + return Signal { observer in + return self.observe { event in + switch event { + case let .value(value): + let date = scheduler.currentDate.addingTimeInterval(interval) + d.inner = scheduler.schedule(after: date) { + observer.send(value: value) + } + + case .completed, .failed, .interrupted: + d.inner = scheduler.schedule { + observer.action(event) + } + } + } + } + } +} + +extension Signal { + /// Forward only those values from `self` that have unique identities across + /// the set of all values that have been seen. + /// + /// - note: This causes the identities to be retained to check for + /// uniqueness. + /// + /// - parameters: + /// - transform: A closure that accepts a value and returns identity + /// value. + /// + /// - returns: A signal that sends unique values during its lifetime. + public func uniqueValues(_ transform: @escaping (Value) -> Identity) -> Signal { + return Signal { observer in + var seenValues: Set = [] + + return self + .observe { event in + switch event { + case let .value(value): + let identity = transform(value) + let (inserted, _) = seenValues.insert(identity) + if inserted { + fallthrough + } + + case .failed, .completed, .interrupted: + observer.action(event) + } + } + } + } +} + +extension Signal where Value: Hashable { + /// Forward only those values from `self` that are unique across the set of + /// all values that have been seen. + /// + /// - note: This causes the values to be retained to check for uniqueness. + /// Providing a function that returns a unique value for each sent + /// value can help you reduce the memory footprint. + /// + /// - returns: A signal that sends unique values during its lifetime. + public func uniqueValues() -> Signal { + return uniqueValues { $0 } + } +} + +private struct ThrottleState { + var previousDate: Date? = nil + var pendingValue: Value? = nil +} + +private enum ThrottleWhileState { + case resumed + case throttled(Value?) + case terminated + + var isTerminated: Bool { + switch self { + case .terminated: + return true + case .resumed, .throttled: + return false + } + } +} + +private protocol SignalAggregateStrategy { + /// Update the latest value of the signal at `position` to be `value`. + /// + /// - parameters: + /// - value: The latest value emitted by the signal at `position`. + /// - position: The position of the signal. + /// + /// - returns: `true` if the aggregating signal should terminate as a result of the + /// update. `false` otherwise. + mutating func update(_ value: Any, at position: Int) -> Bool + + /// Record the completion of the signal at `position`. + /// + /// - parameters: + /// - position: The position of the signal. + /// + /// - returns: `true` if the aggregating signal should terminate as a result of the + /// completion. `false` otherwise. + mutating func complete(at position: Int) -> Bool + + init(count: Int, action: @escaping (ContiguousArray) -> Void) +} + +extension Signal { + private struct CombineLatestStrategy: SignalAggregateStrategy { + private enum Placeholder { + case none + } + + private var values: ContiguousArray + private var completionCount: Int + private let action: (ContiguousArray) -> Void + + private var _haveAllSentInitial: Bool + private var haveAllSentInitial: Bool { + mutating get { + if _haveAllSentInitial { + return true + } + + _haveAllSentInitial = values.reduce(true) { $0 && !($1 is Placeholder) } + return _haveAllSentInitial + } + } + + mutating func update(_ value: Any, at position: Int) -> Bool { + values[position] = value + + if haveAllSentInitial { + action(values) + } + + return false + } + + mutating func complete(at position: Int) -> Bool { + completionCount += 1 + return completionCount == values.count + } + + init(count: Int, action: @escaping (ContiguousArray) -> Void) { + values = ContiguousArray(repeating: Placeholder.none, count: count) + completionCount = 0 + _haveAllSentInitial = false + self.action = action + } + } + + private struct ZipStrategy: SignalAggregateStrategy { + private var values: ContiguousArray<[Any]> + private var isCompleted: ContiguousArray + private let action: (ContiguousArray) -> Void + + private var hasCompletedAndEmptiedSignal: Bool { + return Swift.zip(values, isCompleted).contains(where: { $0.0.isEmpty && $0.1 }) + } + + private var canEmit: Bool { + return values.reduce(true) { $0 && !$1.isEmpty } + } + + private var areAllCompleted: Bool { + return isCompleted.reduce(true) { $0 && $1 } + } + + mutating func update(_ value: Any, at position: Int) -> Bool { + values[position].append(value) + + if canEmit { + var buffer = ContiguousArray() + buffer.reserveCapacity(values.count) + + for index in values.startIndex ..< values.endIndex { + buffer.append(values[index].removeFirst()) + } + + action(buffer) + + if hasCompletedAndEmptiedSignal { + return true + } + } + + return false + } + + mutating func complete(at position: Int) -> Bool { + isCompleted[position] = true + + // `zip` completes when all signals has completed, or any of the signals + // has completed without any buffered value. + return hasCompletedAndEmptiedSignal || areAllCompleted + } + + init(count: Int, action: @escaping (ContiguousArray) -> Void) { + values = ContiguousArray(repeating: [], count: count) + isCompleted = ContiguousArray(repeating: false, count: count) + self.action = action + } + } + + private final class AggregateBuilder { + fileprivate var startHandlers: [(_ index: Int, _ strategy: Atomic, _ action: @escaping (Signal.Event) -> Void) -> Disposable?] + + init() { + self.startHandlers = [] + } + + @discardableResult + func add(_ signal: Signal) -> Self { + startHandlers.append { index, strategy, action in + return signal.observe { event in + switch event { + case let .value(value): + let shouldComplete = strategy.modify { + return $0.update(value, at: index) + } + + if shouldComplete { + action(.completed) + } + + case .completed: + let shouldComplete = strategy.modify { + return $0.complete(at: index) + } + + if shouldComplete { + action(.completed) + } + + case .interrupted: + action(.interrupted) + + case let .failed(error): + action(.failed(error)) + } + } + } + + return self + } + } + + private convenience init(_ builder: AggregateBuilder, _ transform: @escaping (ContiguousArray) -> Value) { + self.init { observer in + let disposables = CompositeDisposable() + let strategy = Atomic(Strategy(count: builder.startHandlers.count) { observer.send(value: transform($0)) }) + + for (index, action) in builder.startHandlers.enumerated() where !disposables.isDisposed { + disposables += action(index, strategy) { observer.action($0.map { _ in fatalError() }) } + } + + return AnyDisposable { + strategy.modify { _ in + disposables.dispose() + } + } + } + } + + private convenience init(_ strategy: Strategy.Type, _ signals: S) where Value == [U], S.Iterator.Element == Signal { + self.init(signals.reduce(AggregateBuilder()) { $0.add($1) }) { $0.map { $0 as! U } } + } + + private convenience init(_ strategy: Strategy.Type, _ a: Signal, _ b: Signal) where Value == (A, B) { + self.init(AggregateBuilder().add(a).add(b)) { + return ($0[0] as! A, $0[1] as! B) + } + } + + private convenience init(_ strategy: Strategy.Type, _ a: Signal, _ b: Signal, _ c: Signal) where Value == (A, B, C) { + self.init(AggregateBuilder().add(a).add(b).add(c)) { + return ($0[0] as! A, $0[1] as! B, $0[2] as! C) + } + } + + private convenience init(_ strategy: Strategy.Type, _ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal) where Value == (A, B, C, D) { + self.init(AggregateBuilder().add(a).add(b).add(c).add(d)) { + return ($0[0] as! A, $0[1] as! B, $0[2] as! C, $0[3] as! D) + } + } + + private convenience init(_ strategy: Strategy.Type, _ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal) where Value == (A, B, C, D, E) { + self.init(AggregateBuilder().add(a).add(b).add(c).add(d).add(e)) { + return ($0[0] as! A, $0[1] as! B, $0[2] as! C, $0[3] as! D, $0[4] as! E) + } + } + + private convenience init(_ strategy: Strategy.Type, _ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal) where Value == (A, B, C, D, E, F) { + self.init(AggregateBuilder().add(a).add(b).add(c).add(d).add(e).add(f)) { + return ($0[0] as! A, $0[1] as! B, $0[2] as! C, $0[3] as! D, $0[4] as! E, $0[5] as! F) + } + } + + private convenience init(_ strategy: Strategy.Type, _ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal) where Value == (A, B, C, D, E, F, G) { + self.init(AggregateBuilder().add(a).add(b).add(c).add(d).add(e).add(f).add(g)) { + return ($0[0] as! A, $0[1] as! B, $0[2] as! C, $0[3] as! D, $0[4] as! E, $0[5] as! F, $0[6] as! G) + } + } + + private convenience init(_ strategy: Strategy.Type, _ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal) where Value == (A, B, C, D, E, F, G, H) { + self.init(AggregateBuilder().add(a).add(b).add(c).add(d).add(e).add(f).add(g).add(h)) { + return ($0[0] as! A, $0[1] as! B, $0[2] as! C, $0[3] as! D, $0[4] as! E, $0[5] as! F, $0[6] as! G, $0[7] as! H) + } + } + + private convenience init(_ strategy: Strategy.Type, _ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal) where Value == (A, B, C, D, E, F, G, H, I) { + self.init(AggregateBuilder().add(a).add(b).add(c).add(d).add(e).add(f).add(g).add(h).add(i)) { + return ($0[0] as! A, $0[1] as! B, $0[2] as! C, $0[3] as! D, $0[4] as! E, $0[5] as! F, $0[6] as! G, $0[7] as! H, $0[8] as! I) + } + } + + private convenience init(_ strategy: Strategy.Type, _ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal, _ j: Signal) where Value == (A, B, C, D, E, F, G, H, I, J) { + self.init(AggregateBuilder().add(a).add(b).add(c).add(d).add(e).add(f).add(g).add(h).add(i).add(j)) { + return ($0[0] as! A, $0[1] as! B, $0[2] as! C, $0[3] as! D, $0[4] as! E, $0[5] as! F, $0[6] as! G, $0[7] as! H, $0[8] as! I, $0[9] as! J) + } + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: Signal, _ b: Signal) -> Signal<(Value, B), Error> { + return .init(CombineLatestStrategy.self, a, b) + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal) -> Signal<(Value, B, C), Error> { + return .init(CombineLatestStrategy.self, a, b, c) + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal) -> Signal<(Value, B, C, D), Error> { + return .init(CombineLatestStrategy.self, a, b, c, d) + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal) -> Signal<(Value, B, C, D, E), Error> { + return .init(CombineLatestStrategy.self, a, b, c, d, e) + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal) -> Signal<(Value, B, C, D, E, F), Error> { + return .init(CombineLatestStrategy.self, a, b, c, d, e, f) + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal) -> Signal<(Value, B, C, D, E, F, G), Error> { + return .init(CombineLatestStrategy.self, a, b, c, d, e, f, g) + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal) -> Signal<(Value, B, C, D, E, F, G, H), Error> { + return .init(CombineLatestStrategy.self, a, b, c, d, e, f, g, h) + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal) -> Signal<(Value, B, C, D, E, F, G, H, I), Error> { + return .init(CombineLatestStrategy.self, a, b, c, d, e, f, g, h, i) + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal, _ j: Signal) -> Signal<(Value, B, C, D, E, F, G, H, I, J), Error> { + return .init(CombineLatestStrategy.self, a, b, c, d, e, f, g, h, i, j) + } + + /// Combines the values of all the given signals, in the manner described by + /// `combineLatest(with:)`. No events will be sent if the sequence is empty. + public static func combineLatest(_ signals: S) -> Signal<[Value], Error> where S.Iterator.Element == Signal { + return .init(CombineLatestStrategy.self, signals) + } + + /// Zip the values of all the given signals, in the manner described by `zip(with:)`. + public static func zip(_ a: Signal, _ b: Signal) -> Signal<(Value, B), Error> { + return .init(ZipStrategy.self, a, b) + } + + /// Zip the values of all the given signals, in the manner described by `zip(with:)`. + public static func zip(_ a: Signal, _ b: Signal, _ c: Signal) -> Signal<(Value, B, C), Error> { + return .init(ZipStrategy.self, a, b, c) + } + + /// Zip the values of all the given signals, in the manner described by `zip(with:)`. + public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal) -> Signal<(Value, B, C, D), Error> { + return .init(ZipStrategy.self, a, b, c, d) + } + + /// Zip the values of all the given signals, in the manner described by `zip(with:)`. + public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal) -> Signal<(Value, B, C, D, E), Error> { + return .init(ZipStrategy.self, a, b, c, d, e) + } + + /// Zip the values of all the given signals, in the manner described by `zip(with:)`. + public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal) -> Signal<(Value, B, C, D, E, F), Error> { + return .init(ZipStrategy.self, a, b, c, d, e, f) + } + + /// Zip the values of all the given signals, in the manner described by `zip(with:)`. + public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal) -> Signal<(Value, B, C, D, E, F, G), Error> { + return .init(ZipStrategy.self, a, b, c, d, e, f, g) + } + + /// Zip the values of all the given signals, in the manner described by `zip(with:)`. + public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal) -> Signal<(Value, B, C, D, E, F, G, H), Error> { + return .init(ZipStrategy.self, a, b, c, d, e, f, g, h) + } + + /// Zip the values of all the given signals, in the manner described by `zip(with:)`. + public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal) -> Signal<(Value, B, C, D, E, F, G, H, I), Error> { + return .init(ZipStrategy.self, a, b, c, d, e, f, g, h, i) + } + + /// Zip the values of all the given signals, in the manner described by `zip(with:)`. + public static func zip(_ a: Signal, _ b: Signal, _ c: Signal, _ d: Signal, _ e: Signal, _ f: Signal, _ g: Signal, _ h: Signal, _ i: Signal, _ j: Signal) -> Signal<(Value, B, C, D, E, F, G, H, I, J), Error> { + return .init(ZipStrategy.self, a, b, c, d, e, f, g, h, i, j) + } + + /// Zips the values of all the given signals, in the manner described by + /// `zip(with:)`. No events will be sent if the sequence is empty. + public static func zip(_ signals: S) -> Signal<[Value], Error> where S.Iterator.Element == Signal { + return .init(ZipStrategy.self, signals) + } +} + +extension Signal { + /// Forward events from `self` until `interval`. Then if signal isn't + /// completed yet, fails with `error` on `scheduler`. + /// + /// - note: If the interval is 0, the timeout will be scheduled immediately. + /// The signal must complete synchronously (or on a faster + /// scheduler) to avoid the timeout. + /// + /// - precondition: `interval` must be non-negative number. + /// + /// - parameters: + /// - error: Error to send with failed event if `self` is not completed + /// when `interval` passes. + /// - interval: Number of seconds to wait for `self` to complete. + /// - scheudler: A scheduler to deliver error on. + /// + /// - returns: A signal that sends events for at most `interval` seconds, + /// then, if not `completed` - sends `error` with failed event + /// on `scheduler`. + public func timeout(after interval: TimeInterval, raising error: Error, on scheduler: DateScheduler) -> Signal { + precondition(interval >= 0) + + return Signal { observer in + let disposable = CompositeDisposable() + let date = scheduler.currentDate.addingTimeInterval(interval) + + disposable += scheduler.schedule(after: date) { + observer.send(error: error) + } + + disposable += self.observe(observer) + return disposable + } + } +} + +extension Signal where Error == NoError { + /// Promote a signal that does not generate failures into one that can. + /// + /// - note: This does not actually cause failures to be generated for the + /// given signal, but makes it easier to combine with other signals + /// that may fail; for example, with operators like + /// `combineLatestWith`, `zipWith`, `flatten`, etc. + /// + /// - parameters: + /// - _ An `ErrorType`. + /// + /// - returns: A signal that has an instantiatable `ErrorType`. + public func promoteError(_: F.Type = F.self) -> Signal { + return Signal { observer in + return self.observe { event in + switch event { + case let .value(value): + observer.send(value: value) + case .failed: + fatalError("NoError is impossible to construct") + case .completed: + observer.sendCompleted() + case .interrupted: + observer.sendInterrupted() + } + } + } + } + + /// Promote a signal that does not generate failures into one that can. + /// + /// - note: This does not actually cause failures to be generated for the + /// given signal, but makes it easier to combine with other signals + /// that may fail; for example, with operators like + /// `combineLatestWith`, `zipWith`, `flatten`, etc. + /// + /// - parameters: + /// - _ An `ErrorType`. + /// + /// - returns: A signal that has an instantiatable `ErrorType`. + public func promoteError(_: Error.Type = Error.self) -> Signal { + return self + } + + /// Forward events from `self` until `interval`. Then if signal isn't + /// completed yet, fails with `error` on `scheduler`. + /// + /// - note: If the interval is 0, the timeout will be scheduled immediately. + /// The signal must complete synchronously (or on a faster + /// scheduler) to avoid the timeout. + /// + /// - parameters: + /// - interval: Number of seconds to wait for `self` to complete. + /// - error: Error to send with `failed` event if `self` is not completed + /// when `interval` passes. + /// - scheudler: A scheduler to deliver error on. + /// + /// - returns: A signal that sends events for at most `interval` seconds, + /// then, if not `completed` - sends `error` with `failed` event + /// on `scheduler`. + public func timeout( + after interval: TimeInterval, + raising error: NewError, + on scheduler: DateScheduler + ) -> Signal { + return self + .promoteError(NewError.self) + .timeout(after: interval, raising: error, on: scheduler) + } +} + +extension Signal where Value == Never { + /// Promote a signal that does not generate values, as indicated by `Never`, to be + /// a signal of the given type of value. + /// + /// - note: The promotion does not result in any value being generated. + /// + /// - parameters: + /// - _ The type of value to promote to. + /// + /// - returns: A signal that forwards all terminal events from `self`. + public func promoteValue(_: U.Type = U.self) -> Signal { + return Signal { observer in + return self.observe { event in + switch event { + case .value: + fatalError("Never is impossible to construct") + case let .failed(error): + observer.send(error: error) + case .completed: + observer.sendCompleted() + case .interrupted: + observer.sendInterrupted() + } + } + } + } + + /// Promote a signal that does not generate values, as indicated by `Never`, to be + /// a signal of the given type of value. + /// + /// - note: The promotion does not result in any value being generated. + /// + /// - parameters: + /// - _ The type of value to promote to. + /// + /// - returns: A signal that forwards all terminal events from `self`. + public func promoteValue(_: Value.Type = Value.self) -> Signal { + return self + } +} + +extension Signal where Value == Bool { + /// Create a signal that computes a logical NOT in the latest values of `self`. + /// + /// - returns: A signal that emits the logical NOT results. + public func negate() -> Signal { + return self.map(!) + } + + /// Create a signal that computes a logical AND between the latest values of `self` + /// and `signal`. + /// + /// - parameters: + /// - signal: Signal to be combined with `self`. + /// + /// - returns: A signal that emits the logical AND results. + public func and(_ signal: Signal) -> Signal { + return self.combineLatest(with: signal).map { $0.0 && $0.1 } + } + + /// Create a signal that computes a logical OR between the latest values of `self` + /// and `signal`. + /// + /// - parameters: + /// - signal: Signal to be combined with `self`. + /// + /// - returns: A signal that emits the logical OR results. + public func or(_ signal: Signal) -> Signal { + return self.combineLatest(with: signal).map { $0.0 || $0.1 } + } +} + +extension Signal { + /// Apply an action to every value from `self`, and forward the value if the action + /// succeeds. If the action fails with an error, the returned `Signal` would propagate + /// the failure and terminate. + /// + /// - parameters: + /// - action: An action which yields a `Result`. + /// + /// - returns: A signal which forwards the values from `self` until the given action + /// fails. + public func attempt(_ action: @escaping (Value) -> Result<(), Error>) -> Signal { + return attemptMap { value -> Result in + return action(value).map { _ -> Value in + return value + } + } + } + + /// Apply a transform to every value from `self`, and forward the transformed value + /// if the action succeeds. If the action fails with an error, the returned `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - action: A transform which yields a `Result` of the transformed value or the + /// error. + /// + /// - returns: A signal which forwards the transformed values. + public func attemptMap(_ transform: @escaping (Value) -> Result) -> Signal { + return Signal { observer in + self.observe { event in + switch event { + case let .value(value): + transform(value).analysis( + ifSuccess: observer.send(value:), + ifFailure: observer.send(error:) + ) + case let .failed(error): + observer.send(error: error) + case .completed: + observer.sendCompleted() + case .interrupted: + observer.sendInterrupted() + } + } + } + } +} + +extension Signal where Error == NoError { + /// Apply a throwable action to every value from `self`, and forward the values + /// if the action succeeds. If the action throws an error, the returned `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - action: A throwable closure to perform an arbitrary action on the value. + /// + /// - returns: A signal which forwards the successful values of the given action. + public func attempt(_ action: @escaping (Value) throws -> Void) -> Signal { + return self + .promoteError(AnyError.self) + .attempt(action) + } + + /// Apply a throwable transform to every value from `self`, and forward the results + /// if the action succeeds. If the transform throws an error, the returned `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - transform: A throwable transform. + /// + /// - returns: A signal which forwards the successfully transformed values. + public func attemptMap(_ transform: @escaping (Value) throws -> U) -> Signal { + return self + .promoteError(AnyError.self) + .attemptMap(transform) + } +} + +extension Signal where Error == AnyError { + /// Apply a throwable action to every value from `self`, and forward the values + /// if the action succeeds. If the action throws an error, the returned `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - action: A throwable closure to perform an arbitrary action on the value. + /// + /// - returns: A signal which forwards the successful values of the given action. + public func attempt(_ action: @escaping (Value) throws -> Void) -> Signal { + return attemptMap { value in + try action(value) + return value + } + } + + /// Apply a throwable transform to every value from `self`, and forward the results + /// if the action succeeds. If the transform throws an error, the returned `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - transform: A throwable transform. + /// + /// - returns: A signal which forwards the successfully transformed values. + public func attemptMap(_ transform: @escaping (Value) throws -> U) -> Signal { + return attemptMap { value in + ReactiveSwift.materialize { + try transform(value) + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/SignalProducer.swift b/Carthage/Checkouts/ReactiveSwift/Sources/SignalProducer.swift new file mode 100644 index 0000000..6676f49 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/SignalProducer.swift @@ -0,0 +1,2293 @@ +import Dispatch +import Foundation +import Result + +/// A SignalProducer creates Signals that can produce values of type `Value` +/// and/or fail with errors of type `Error`. If no failure should be possible, +/// `NoError` can be specified for `Error`. +/// +/// SignalProducers can be used to represent operations or tasks, like network +/// requests, where each invocation of `start()` will create a new underlying +/// operation. This ensures that consumers will receive the results, versus a +/// plain Signal, where the results might be sent before any observers are +/// attached. +/// +/// Because of the behavior of `start()`, different Signals created from the +/// producer may see a different version of Events. The Events may arrive in a +/// different order between Signals, or the stream might be completely +/// different! +public struct SignalProducer { + public typealias ProducedSignal = Signal + + /// Wraps a closure which, when invoked, produces a new instance of `Signal`, a + /// customized `observerDidSetup` post-creation side effect for the `Signal` and a + /// disposable to interrupt the produced `Signal`. + /// + /// Unlike the safe `startWithSignal(_:)` API, `builder` shifts the responsibility of + /// invoking the post-creation side effect to the caller, while it takes from the + /// caller the responsibility of the `Signal` creation. + /// + /// The design allows producer lifting to be as efficient as native `Signal` + /// operators, by eliminating the unnecessary relay `Signal` imposed by the old + /// `startWithSignal(_:)`, regardless of the fact that lifted operators can rely on + /// the upstreams for producer interruption. + /// + /// `observerDidSetup` must be invoked before any other post-creation side effect. + fileprivate struct Instance { + let producedSignal: Signal + let observerDidSetup: () -> Void + let interruptHandle: Disposable + } + + fileprivate let builder: () -> Instance + + /// Convert an entity into its equivalent representation as `SignalProducer`. + /// + /// - parameters: + /// - base: The entity to convert from. + public init(_ base: T) where T.Value == Value, T.Error == Error { + self = base.producer + } + + /// Initializes a `SignalProducer` that will emit the same events as the + /// given signal. + /// + /// If the Disposable returned from `start()` is disposed or a terminating + /// event is sent to the observer, the given signal will be disposed. + /// + /// - parameters: + /// - signal: A signal to observe after starting the producer. + public init(_ signal: Signal) { + self.init { observer, lifetime in + if let disposable = signal.observe(observer) { + lifetime.observeEnded(disposable.dispose) + } + } + } + + /// Initializes a SignalProducer that will invoke the given closure once for + /// each invocation of `start()`. + /// + /// The events that the closure puts into the given observer will become + /// the events sent by the started `Signal` to its observers. + /// + /// - note: If the `Disposable` returned from `start()` is disposed or a + /// terminating event is sent to the observer, the given + /// `CompositeDisposable` will be disposed, at which point work + /// should be interrupted and any temporary resources cleaned up. + /// + /// - parameters: + /// - startHandler: A closure that accepts observer and a disposable. + public init(_ startHandler: @escaping (Signal.Observer, Lifetime) -> Void) { + self.init { () -> Instance in + let disposable = CompositeDisposable() + let (signal, observer) = Signal.pipe(disposable: disposable) + let observerDidSetup = { startHandler(observer, Lifetime(disposable)) } + let interruptHandle = AnyDisposable(observer.sendInterrupted) + + return Instance(producedSignal: signal, observerDidSetup: observerDidSetup, interruptHandle: interruptHandle) + } + } + + /// Create a SignalProducer that will invoke the given factory once for each + /// invocation of `start()`. + /// + /// - parameters: + /// - builder: A builder that is used by `startWithSignal` to create new `Signal`s. + fileprivate init(_ builder: @escaping () -> Instance) { + self.builder = builder + } + + /// Creates a producer for a `Signal` that will immediately send one value + /// then complete. + /// + /// - parameters: + /// - value: A value that should be sent by the `Signal` in a `value` + /// event. + public init(value: Value) { + self.init { observer, lifetime in + observer.send(value: value) + observer.sendCompleted() + } + } + + /// Creates a producer for a `Signal` that immediately sends one value, then + /// completes. + /// + /// This initializer differs from `init(value:)` in that its sole `value` + /// event is constructed lazily by invoking the supplied `action` when + /// the `SignalProducer` is started. + /// + /// - parameters: + /// - action: A action that yields a value to be sent by the `Signal` as + /// a `value` event. + public init(_ action: @escaping () -> Value) { + self.init { observer, lifetime in + observer.send(value: action()) + observer.sendCompleted() + } + } + + /// Create a `SignalProducer` that will attempt the given operation once for + /// each invocation of `start()`. + /// + /// Upon success, the started signal will send the resulting value then + /// complete. Upon failure, the started signal will fail with the error that + /// occurred. + /// + /// - parameters: + /// - action: A closure that returns instance of `Result`. + public init(_ action: @escaping () -> Result) { + self.init { observer, disposable in + action().analysis(ifSuccess: { value in + observer.send(value: value) + observer.sendCompleted() + }, ifFailure: { error in + observer.send(error: error) + }) + } + } + + /// Creates a producer for a `Signal` that will immediately fail with the + /// given error. + /// + /// - parameters: + /// - error: An error that should be sent by the `Signal` in a `failed` + /// event. + public init(error: Error) { + self.init { observer, lifetime in + observer.send(error: error) + } + } + + /// Creates a producer for a Signal that will immediately send one value + /// then complete, or immediately fail, depending on the given Result. + /// + /// - parameters: + /// - result: A `Result` instance that will send either `value` event if + /// `result` is `success`ful or `failed` event if `result` is a + /// `failure`. + public init(result: Result) { + switch result { + case let .success(value): + self.init(value: value) + + case let .failure(error): + self.init(error: error) + } + } + + /// Creates a producer for a Signal that will immediately send the values + /// from the given sequence, then complete. + /// + /// - parameters: + /// - values: A sequence of values that a `Signal` will send as separate + /// `value` events and then complete. + public init(_ values: S) where S.Iterator.Element == Value { + self.init { observer, lifetime in + for value in values { + observer.send(value: value) + + if lifetime.hasEnded { + break + } + } + + observer.sendCompleted() + } + } + + /// Creates a producer for a Signal that will immediately send the values + /// from the given sequence, then complete. + /// + /// - parameters: + /// - first: First value for the `Signal` to send. + /// - second: Second value for the `Signal` to send. + /// - tail: Rest of the values to be sent by the `Signal`. + public init(values first: Value, _ second: Value, _ tail: Value...) { + self.init([ first, second ] + tail) + } + + /// A producer for a Signal that will immediately complete without sending + /// any values. + public static var empty: SignalProducer { + return self.init { observer, lifetime in + observer.sendCompleted() + } + } + + /// A producer for a Signal that never sends any events to its observers. + public static var never: SignalProducer { + return self.init { observer, lifetime in + lifetime.observeEnded { _ = observer } + } + } + + /// Create a `Signal` from `self`, pass it into the given closure, and start the + /// associated work on the produced `Signal` as the closure returns. + /// + /// - parameters: + /// - setup: A closure to be invoked before the work associated with the produced + /// `Signal` commences. Both the produced `Signal` and an interrupt handle + /// of the signal would be passed to the closure. + public func startWithSignal(_ setup: (_ signal: Signal, _ interruptHandle: Disposable) -> Void) { + let instance = builder() + setup(instance.producedSignal, instance.interruptHandle) + guard !instance.interruptHandle.isDisposed else { return } + instance.observerDidSetup() + } +} + +extension SignalProducer where Error == AnyError { + /// Create a `SignalProducer` that will attempt the given failable operation once for + /// each invocation of `start()`. + /// + /// Upon success, the started producer will send the resulting value then + /// complete. Upon failure, the started signal will fail with the error that + /// occurred. + /// + /// - parameters: + /// - operation: A failable closure. + public init(_ action: @escaping () throws -> Value) { + self.init { + return ReactiveSwift.materialize { + return try action() + } + } + } +} + +/// Represents reactive primitives that can be represented by `SignalProducer`. +public protocol SignalProducerConvertible { + /// The type of values being sent by `self`. + associatedtype Value + + /// The type of error that can occur on `self`. + associatedtype Error: Swift.Error + + /// The `SignalProducer` representation of `self`. + var producer: SignalProducer { get } +} + +/// A protocol for constraining associated types to `SignalProducer`. +public protocol SignalProducerProtocol { + /// The type of values being sent by `self`. + associatedtype Value + + /// The type of error that can occur on `self`. + associatedtype Error: Swift.Error + + /// The materialized `self`. + var producer: SignalProducer { get } +} + +extension SignalProducer: SignalProducerConvertible, SignalProducerProtocol { + public var producer: SignalProducer { + return self + } +} + +extension SignalProducer { + /// Create a `Signal` from `self`, and observe it with the given observer. + /// + /// - parameters: + /// - observer: An observer to attach to the produced `Signal`. + /// + /// - returns: A disposable to interrupt the produced `Signal`. + @discardableResult + public func start(_ observer: Signal.Observer = .init()) -> Disposable { + var disposable: Disposable! + + startWithSignal { signal, innerDisposable in + signal.observe(observer) + disposable = innerDisposable + } + + return disposable + } + + /// Create a `Signal` from `self`, and observe the `Signal` for all events + /// being emitted. + /// + /// - parameters: + /// - action: A closure to be invoked with every event from `self`. + /// + /// - returns: A disposable to interrupt the produced `Signal`. + @discardableResult + public func start(_ action: @escaping Signal.Observer.Action) -> Disposable { + return start(Signal.Observer(action)) + } + + /// Create a `Signal` from `self`, and observe the `Signal` for all values being + /// emitted, and if any, its failure. + /// + /// - parameters: + /// - action: A closure to be invoked with values from `self`, or the propagated + /// error should any `failed` event is emitted. + /// + /// - returns: A disposable to interrupt the produced `Signal`. + @discardableResult + public func startWithResult(_ action: @escaping (Result) -> Void) -> Disposable { + return start( + Signal.Observer( + value: { action(.success($0)) }, + failed: { action(.failure($0)) } + ) + ) + } + + /// Create a `Signal` from `self`, and observe its completion. + /// + /// - parameters: + /// - action: A closure to be invoked when a `completed` event is emitted. + /// + /// - returns: A disposable to interrupt the produced `Signal`. + @discardableResult + public func startWithCompleted(_ action: @escaping () -> Void) -> Disposable { + return start(Signal.Observer(completed: action)) + } + + /// Create a `Signal` from `self`, and observe its failure. + /// + /// - parameters: + /// - action: A closure to be invoked with the propagated error, should any + /// `failed` event is emitted. + /// + /// - returns: A disposable to interrupt the produced `Signal`. + @discardableResult + public func startWithFailed(_ action: @escaping (Error) -> Void) -> Disposable { + return start(Signal.Observer(failed: action)) + } + + /// Create a `Signal` from `self`, and observe its interruption. + /// + /// - parameters: + /// - action: A closure to be invoked when an `interrupted` event is emitted. + /// + /// - returns: A disposable to interrupt the produced `Signal`. + @discardableResult + public func startWithInterrupted(_ action: @escaping () -> Void) -> Disposable { + return start(Signal.Observer(interrupted: action)) + } + + /// Creates a `Signal` from the producer. + /// + /// This is equivalent to `SignalProducer.startWithSignal`, but it has + /// the downside that any values emitted synchronously upon starting will + /// be missed by the observer, because it won't be able to subscribe in time. + /// That's why we don't want this method to be exposed as `public`, + /// but it's useful internally. + internal func startAndRetrieveSignal() -> Signal { + var result: Signal! + self.startWithSignal { signal, _ in + result = signal + } + + return result + } + + /// Create a `Signal` from `self` in the manner described by `startWithSignal`, and + /// put the interrupt handle into the given `CompositeDisposable`. + /// + /// - parameters: + /// - lifetime: The `Lifetime` the interrupt handle to be added to. + /// - setup: A closure that accepts the produced `Signal`. + fileprivate func startWithSignal(during lifetime: Lifetime, setup: (Signal) -> Void) { + startWithSignal { signal, interruptHandle in + lifetime.observeEnded(interruptHandle.dispose) + setup(signal) + } + } +} + +extension SignalProducer where Error == NoError { + /// Create a `Signal` from `self`, and observe the `Signal` for all values being + /// emitted. + /// + /// - parameters: + /// - action: A closure to be invoked with values from the produced `Signal`. + /// + /// - returns: A disposable to interrupt the produced `Signal`. + @discardableResult + public func startWithValues(_ action: @escaping (Value) -> Void) -> Disposable { + return start(Signal.Observer(value: action)) + } +} + +extension SignalProducer { + /// Lift an unary Signal operator to operate upon SignalProducers instead. + /// + /// In other words, this will create a new `SignalProducer` which will apply + /// the given `Signal` operator to _every_ created `Signal`, just as if the + /// operator had been applied to each `Signal` yielded from `start()`. + /// + /// - parameters: + /// - transform: An unary operator to lift. + /// + /// - returns: A signal producer that applies signal's operator to every + /// created signal. + public func lift(_ transform: @escaping (Signal) -> Signal) -> SignalProducer { + return SignalProducer { () -> SignalProducer.Instance in + // Transform the `Signal`, and pass through the `didCreate` side effect and + // the interruptHandle. + let instance = self.producer.builder() + return SignalProducer.Instance(producedSignal: transform(instance.producedSignal), + observerDidSetup: instance.observerDidSetup, + interruptHandle: instance.interruptHandle) + } + } + + /// Lift a binary Signal operator to operate upon SignalProducers. + /// + /// The left producer would first be started. When both producers are synchronous this + /// order can be important depending on the operator to generate correct results. + /// + /// - returns: A factory that creates a SignalProducer with the given operator + /// applied. `self` would be the LHS, and the factory input would + /// be the RHS. + fileprivate func liftLeft(_ transform: @escaping (Signal) -> (Signal) -> Signal) -> (SignalProducer) -> SignalProducer { + return lift(leftFirst: true, transform) + } + + /// Lift a binary Signal operator to operate upon SignalProducers. + /// + /// The right producer would first be started. When both producers are synchronous + /// this order can be important depending on the operator to generate correct results. + /// + /// - returns: A factory that creates a SignalProducer with the given operator + /// applied. `self` would be the LHS, and the factory input would + /// be the RHS. + fileprivate func liftRight(_ transform: @escaping (Signal) -> (Signal) -> Signal) -> (SignalProducer) -> SignalProducer { + return lift(leftFirst: false, transform) + } + + private func lift(leftFirst: Bool, _ transform: @escaping (Signal) -> (Signal) -> Signal) -> (SignalProducer) -> SignalProducer { + return { otherProducer in + return SignalProducer { () -> SignalProducer.Instance in + let left = self.producer.builder() + let right = otherProducer.builder() + + return .init(producedSignal: transform(left.producedSignal)(right.producedSignal), + observerDidSetup: { + if leftFirst { + left.observerDidSetup() + right.observerDidSetup() + } else { + right.observerDidSetup() + left.observerDidSetup() + }}, + interruptHandle: CompositeDisposable([left.interruptHandle, right.interruptHandle])) + } + } + } + + /// Lift a binary Signal operator to operate upon SignalProducers instead. + /// + /// In other words, this will create a new `SignalProducer` which will apply + /// the given `Signal` operator to _every_ `Signal` created from the two + /// producers, just as if the operator had been applied to each `Signal` + /// yielded from `start()`. + /// + /// - note: starting the returned producer will start the receiver of the + /// operator, which may not be adviseable for some operators. + /// + /// - parameters: + /// - transform: A binary operator to lift. + /// + /// - returns: A binary operator that operates on two signal producers. + public func lift(_ transform: @escaping (Signal) -> (Signal) -> Signal) -> (SignalProducer) -> SignalProducer { + return liftRight(transform) + } +} + +/// Start the producers in the argument order. +/// +/// - parameters: +/// - disposable: The `CompositeDisposable` to collect the interrupt handles of all +/// produced `Signal`s. +/// - setup: The closure to accept all produced `Signal`s at once. +private func flattenStart(_ lifetime: Lifetime, _ a: SignalProducer, _ b: SignalProducer, _ setup: (Signal, Signal) -> Void) { + b.startWithSignal(during: lifetime) { b in + a.startWithSignal(during: lifetime) { setup($0, b) } + } +} + +/// Start the producers in the argument order. +/// +/// - parameters: +/// - disposable: The `CompositeDisposable` to collect the interrupt handles of all +/// produced `Signal`s. +/// - setup: The closure to accept all produced `Signal`s at once. +private func flattenStart(_ lifetime: Lifetime, _ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ setup: (Signal, Signal, Signal) -> Void) { + c.startWithSignal(during: lifetime) { c in + flattenStart(lifetime, a, b) { setup($0, $1, c) } + } +} + +/// Start the producers in the argument order. +/// +/// - parameters: +/// - disposable: The `CompositeDisposable` to collect the interrupt handles of all +/// produced `Signal`s. +/// - setup: The closure to accept all produced `Signal`s at once. +private func flattenStart(_ lifetime: Lifetime, _ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ setup: (Signal, Signal, Signal, Signal) -> Void) { + d.startWithSignal(during: lifetime) { d in + flattenStart(lifetime, a, b, c) { setup($0, $1, $2, d) } + } +} + +/// Start the producers in the argument order. +/// +/// - parameters: +/// - disposable: The `CompositeDisposable` to collect the interrupt handles of all +/// produced `Signal`s. +/// - setup: The closure to accept all produced `Signal`s at once. +private func flattenStart(_ lifetime: Lifetime, _ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ setup: (Signal, Signal, Signal, Signal, Signal) -> Void) { + e.startWithSignal(during: lifetime) { e in + flattenStart(lifetime, a, b, c, d) { setup($0, $1, $2, $3, e) } + } +} + +/// Start the producers in the argument order. +/// +/// - parameters: +/// - disposable: The `CompositeDisposable` to collect the interrupt handles of all +/// produced `Signal`s. +/// - setup: The closure to accept all produced `Signal`s at once. +private func flattenStart(_ lifetime: Lifetime, _ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ setup: (Signal, Signal, Signal, Signal, Signal, Signal) -> Void) { + f.startWithSignal(during: lifetime) { f in + flattenStart(lifetime, a, b, c, d, e) { setup($0, $1, $2, $3, $4, f) } + } +} + +/// Start the producers in the argument order. +/// +/// - parameters: +/// - disposable: The `CompositeDisposable` to collect the interrupt handles of all +/// produced `Signal`s. +/// - setup: The closure to accept all produced `Signal`s at once. +private func flattenStart(_ lifetime: Lifetime, _ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ setup: (Signal, Signal, Signal, Signal, Signal, Signal, Signal) -> Void) { + g.startWithSignal(during: lifetime) { g in + flattenStart(lifetime, a, b, c, d, e, f) { setup($0, $1, $2, $3, $4, $5, g) } + } +} + +/// Start the producers in the argument order. +/// +/// - parameters: +/// - disposable: The `CompositeDisposable` to collect the interrupt handles of all +/// produced `Signal`s. +/// - setup: The closure to accept all produced `Signal`s at once. +private func flattenStart(_ lifetime: Lifetime, _ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ setup: (Signal, Signal, Signal, Signal, Signal, Signal, Signal, Signal) -> Void) { + h.startWithSignal(during: lifetime) { h in + flattenStart(lifetime, a, b, c, d, e, f, g) { setup($0, $1, $2, $3, $4, $5, $6, h) } + } +} + +/// Start the producers in the argument order. +/// +/// - parameters: +/// - disposable: The `CompositeDisposable` to collect the interrupt handles of all +/// produced `Signal`s. +/// - setup: The closure to accept all produced `Signal`s at once. +private func flattenStart(_ lifetime: Lifetime, _ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer, _ setup: (Signal, Signal, Signal, Signal, Signal, Signal, Signal, Signal, Signal) -> Void) { + i.startWithSignal(during: lifetime) { i in + flattenStart(lifetime, a, b, c, d, e, f, g, h) { setup($0, $1, $2, $3, $4, $5, $6, $7, i) } + } +} + +/// Start the producers in the argument order. +/// +/// - parameters: +/// - disposable: The `CompositeDisposable` to collect the interrupt handles of all +/// produced `Signal`s. +/// - setup: The closure to accept all produced `Signal`s at once. +private func flattenStart(_ lifetime: Lifetime, _ a: SignalProducer, _ b: SignalProducer, _ c: SignalProducer, _ d: SignalProducer, _ e: SignalProducer, _ f: SignalProducer, _ g: SignalProducer, _ h: SignalProducer, _ i: SignalProducer, _ j: SignalProducer, _ setup: (Signal, Signal, Signal, Signal, Signal, Signal, Signal, Signal, Signal, Signal) -> Void) { + j.startWithSignal(during: lifetime) { j in + flattenStart(lifetime, a, b, c, d, e, f, g, h, i) { setup($0, $1, $2, $3, $4, $5, $6, $7, $8, j) } + } +} + +extension SignalProducer { + /// Map each value in the producer to a new value. + /// + /// - parameters: + /// - transform: A closure that accepts a value and returns a different + /// value. + /// + /// - returns: A signal producer that, when started, will send a mapped + /// value of `self.` + public func map(_ transform: @escaping (Value) -> U) -> SignalProducer { + return lift { $0.map(transform) } + } + +#if swift(>=3.2) + /// Map each value in the producer to a new value by applying a key path. + /// + /// - parameters: + /// - keyPath: A key path relative to the producer's `Value` type. + /// + /// - returns: A producer that will send new values. + public func map(_ keyPath: KeyPath) -> SignalProducer { + return lift { $0.map(keyPath) } + } +#endif + + /// Map errors in the producer to a new error. + /// + /// - parameters: + /// - transform: A closure that accepts an error object and returns a + /// different error. + /// + /// - returns: A producer that emits errors of new type. + public func mapError(_ transform: @escaping (Error) -> F) -> SignalProducer { + return lift { $0.mapError(transform) } + } + + /// Maps each value in the producer to a new value, lazily evaluating the + /// supplied transformation on the specified scheduler. + /// + /// - important: Unlike `map`, there is not a 1-1 mapping between incoming + /// values, and values sent on the returned producer. If + /// `scheduler` has not yet scheduled `transform` for + /// execution, then each new value will replace the last one as + /// the parameter to `transform` once it is finally executed. + /// + /// - parameters: + /// - transform: The closure used to obtain the returned value from this + /// producer's underlying value. + /// + /// - returns: A producer that, when started, sends values obtained using + /// `transform` as this producer sends values. + public func lazyMap(on scheduler: Scheduler, transform: @escaping (Value) -> U) -> SignalProducer { + return lift { $0.lazyMap(on: scheduler, transform: transform) } + } + + /// Preserve only values which pass the given closure. + /// + /// - parameters: + /// - isIncluded: A closure to determine whether a value from `self` should be + /// included in the produced `Signal`. + /// + /// - returns: A producer that, when started, forwards the values passing the given + /// closure. + public func filter(_ isIncluded: @escaping (Value) -> Bool) -> SignalProducer { + return lift { $0.filter(isIncluded) } + } + + /// Applies `transform` to values from the producer and forwards values with non `nil` results unwrapped. + /// - parameters: + /// - transform: A closure that accepts a value from the `value` event and + /// returns a new optional value. + /// + /// - returns: A producer that will send new values, that are non `nil` after the transformation. + public func filterMap(_ transform: @escaping (Value) -> U?) -> SignalProducer { + return lift { $0.filterMap(transform) } + } + + /// Yield the first `count` values from the input producer. + /// + /// - precondition: `count` must be non-negative number. + /// + /// - parameters: + /// - count: A number of values to take from the signal. + /// + /// - returns: A producer that, when started, will yield the first `count` + /// values from `self`. + public func take(first count: Int) -> SignalProducer { + return lift { $0.take(first: count) } + } + + /// Yield an array of values when `self` completes. + /// + /// - note: When `self` completes without collecting any value, it will send + /// an empty array of values. + /// + /// - returns: A producer that, when started, will yield an array of values + /// when `self` completes. + public func collect() -> SignalProducer<[Value], Error> { + return lift { $0.collect() } + } + + /// Yield an array of values until it reaches a certain count. + /// + /// - precondition: `count` must be greater than zero. + /// + /// - note: When the count is reached the array is sent and the signal + /// starts over yielding a new array of values. + /// + /// - note: When `self` completes any remaining values will be sent, the + /// last array may not have `count` values. Alternatively, if were + /// not collected any values will sent an empty array of values. + /// + /// - returns: A producer that, when started, collects at most `count` + /// values from `self`, forwards them as a single array and + /// completes. + public func collect(count: Int) -> SignalProducer<[Value], Error> { + precondition(count > 0) + return lift { $0.collect(count: count) } + } + + /// Collect values from `self`, and emit them if the predicate passes. + /// + /// When `self` completes any remaining values will be sent, regardless of the + /// collected values matching `shouldEmit` or not. + /// + /// If `self` completes without having emitted any value, an empty array would be + /// emitted, followed by the completion of the produced `Signal`. + /// + /// ```` + /// let (producer, observer) = SignalProducer.buffer(1) + /// + /// producer + /// .collect { values in values.reduce(0, combine: +) == 8 } + /// .startWithValues { print($0) } + /// + /// observer.send(value: 1) + /// observer.send(value: 3) + /// observer.send(value: 4) + /// observer.send(value: 7) + /// observer.send(value: 1) + /// observer.send(value: 5) + /// observer.send(value: 6) + /// observer.sendCompleted() + /// + /// // Output: + /// // [1, 3, 4] + /// // [7, 1] + /// // [5, 6] + /// ```` + /// + /// - parameters: + /// - shouldEmit: A closure to determine, when every time a new value is received, + /// whether the collected values should be emitted. + /// + /// - returns: A signal of arrays of values, as instructed by the `shouldEmit` + /// closure. + public func collect(_ shouldEmit: @escaping (_ values: [Value]) -> Bool) -> SignalProducer<[Value], Error> { + return lift { $0.collect(shouldEmit) } + } + + /// Collect values from `self`, and emit them if the predicate passes. + /// + /// When `self` completes any remaining values will be sent, regardless of the + /// collected values matching `shouldEmit` or not. + /// + /// If `self` completes without having emitted any value, an empty array would be + /// emitted, followed by the completion of the produced `Signal`. + /// + /// ```` + /// let (producer, observer) = SignalProducer.buffer(1) + /// + /// producer + /// .collect { values, value in value == 7 } + /// .startWithValues { print($0) } + /// + /// observer.send(value: 1) + /// observer.send(value: 1) + /// observer.send(value: 7) + /// observer.send(value: 7) + /// observer.send(value: 5) + /// observer.send(value: 6) + /// observer.sendCompleted() + /// + /// // Output: + /// // [1, 1] + /// // [7] + /// // [7, 5, 6] + /// ```` + /// + /// - parameters: + /// - shouldEmit: A closure to determine, when every time a new value is received, + /// whether the collected values should be emitted. The new value + /// is **not** included in the collected values, and is included when + /// the next value is received. + /// + /// - returns: A producer of arrays of values, as instructed by the `shouldEmit` + /// closure. + public func collect(_ shouldEmit: @escaping (_ collected: [Value], _ latest: Value) -> Bool) -> SignalProducer<[Value], Error> { + return lift { $0.collect(shouldEmit) } + } + + /// Forward all events onto the given scheduler, instead of whichever + /// scheduler they originally arrived upon. + /// + /// - parameters: + /// - scheduler: A scheduler to deliver events on. + /// + /// - returns: A producer that, when started, will yield `self` values on + /// provided scheduler. + public func observe(on scheduler: Scheduler) -> SignalProducer { + return lift { $0.observe(on: scheduler) } + } + + /// Combine the latest value of the receiver with the latest value from the + /// given producer. + /// + /// - note: The returned producer will not send a value until both inputs + /// have sent at least one value each. + /// + /// - note: If either producer is interrupted, the returned producer will + /// also be interrupted. + /// + /// - note: The returned producer will not complete until both inputs + /// complete. + /// + /// - parameters: + /// - other: A producer to combine `self`'s value with. + /// + /// - returns: A producer that, when started, will yield a tuple containing + /// values of `self` and given producer. + public func combineLatest(with other: Other) -> SignalProducer<(Value, Other.Value), Error> where Other.Error == Error { + return SignalProducer.combineLatest(self, other) + } + + /// Delay `value` and `completed` events by the given interval, forwarding + /// them on the given scheduler. + /// + /// - note: `failed` and `interrupted` events are always scheduled + /// immediately. + /// + /// - parameters: + /// - interval: Interval to delay `value` and `completed` events by. + /// - scheduler: A scheduler to deliver delayed events on. + /// + /// - returns: A producer that, when started, will delay `value` and + /// `completed` events and will yield them on given scheduler. + public func delay(_ interval: TimeInterval, on scheduler: DateScheduler) -> SignalProducer { + return lift { $0.delay(interval, on: scheduler) } + } + + /// Skip the first `count` values, then forward everything afterward. + /// + /// - parameters: + /// - count: A number of values to skip. + /// + /// - returns: A producer that, when started, will skip the first `count` + /// values, then forward everything afterward. + public func skip(first count: Int) -> SignalProducer { + return lift { $0.skip(first: count) } + } + + /// Treats all Events from the input producer as plain values, allowing them + /// to be manipulated just like any other value. + /// + /// In other words, this brings Events “into the monad.” + /// + /// - note: When a Completed or Failed event is received, the resulting + /// producer will send the Event itself and then complete. When an + /// `interrupted` event is received, the resulting producer will + /// send the `Event` itself and then interrupt. + /// + /// - returns: A producer that sends events as its values. + public func materialize() -> SignalProducer { + return lift { $0.materialize() } + } + + /// Forward the latest value from `self` with the value from `sampler` as a + /// tuple, only when `sampler` sends a `value` event. + /// + /// - note: If `sampler` fires before a value has been observed on `self`, + /// nothing happens. + /// + /// - parameters: + /// - sampler: A producer that will trigger the delivery of `value` event + /// from `self`. + /// + /// - returns: A producer that will send values from `self` and `sampler`, + /// sampled (possibly multiple times) by `sampler`, then complete + /// once both input producers have completed, or interrupt if + /// either input producer is interrupted. + public func sample(with sampler: Sampler) -> SignalProducer<(Value, Sampler.Value), Error> where Sampler.Error == NoError { + return liftLeft(Signal.sample(with:))(sampler.producer) + } + + /// Forward the latest value from `self` whenever `sampler` sends a `value` + /// event. + /// + /// - note: If `sampler` fires before a value has been observed on `self`, + /// nothing happens. + /// + /// - parameters: + /// - sampler: A producer that will trigger the delivery of `value` event + /// from `self`. + /// + /// - returns: A producer that, when started, will send values from `self`, + /// sampled (possibly multiple times) by `sampler`, then complete + /// once both input producers have completed, or interrupt if + /// either input producer is interrupted. + public func sample(on sampler: Sampler) -> SignalProducer where Sampler.Value == (), Sampler.Error == NoError { + return liftLeft(Signal.sample(on:))(sampler.producer) + } + + /// Forward the latest value from `samplee` with the value from `self` as a + /// tuple, only when `self` sends a `value` event. + /// This is like a flipped version of `sample(with:)`, but `samplee`'s + /// terminal events are completely ignored. + /// + /// - note: If `self` fires before a value has been observed on `samplee`, + /// nothing happens. + /// + /// - parameters: + /// - samplee: A producer whose latest value is sampled by `self`. + /// + /// - returns: A signal that will send values from `self` and `samplee`, + /// sampled (possibly multiple times) by `self`, then terminate + /// once `self` has terminated. **`samplee`'s terminated events + /// are ignored**. + public func withLatest(from samplee: Samplee) -> SignalProducer<(Value, Samplee.Value), Error> where Samplee.Error == NoError { + return liftRight(Signal.withLatest)(samplee.producer) + } + + /// Forwards events from `self` until `lifetime` ends, at which point the + /// returned producer will complete. + /// + /// - parameters: + /// - lifetime: A lifetime whose `ended` signal will cause the returned + /// producer to complete. + /// + /// - returns: A producer that will deliver events until `lifetime` ends. + public func take(during lifetime: Lifetime) -> SignalProducer { + return lift { $0.take(during: lifetime) } + } + + /// Forward events from `self` until `trigger` sends a `value` or `completed` + /// event, at which point the returned producer will complete. + /// + /// - parameters: + /// - trigger: A producer whose `value` or `completed` events will stop the + /// delivery of `value` events from `self`. + /// + /// - returns: A producer that will deliver events until `trigger` sends + /// `value` or `completed` events. + public func take(until trigger: Trigger) -> SignalProducer where Trigger.Value == (), Trigger.Error == NoError { + return liftRight(Signal.take(until:))(trigger.producer) + } + + /// Do not forward any values from `self` until `trigger` sends a `value` + /// or `completed`, at which point the returned producer behaves exactly + /// like `producer`. + /// + /// - parameters: + /// - trigger: A producer whose `value` or `completed` events will start + /// the deliver of events on `self`. + /// + /// - returns: A producer that will deliver events once the `trigger` sends + /// `value` or `completed` events. + public func skip(until trigger: Trigger) -> SignalProducer where Trigger.Value == (), Trigger.Error == NoError { + return liftRight(Signal.skip(until:))(trigger.producer) + } + + /// Forward events from `self` with history: values of the returned producer + /// are a tuple whose first member is the previous value and whose second + /// member is the current value. `initial` is supplied as the first member + /// when `self` sends its first value. + /// + /// - parameters: + /// - initial: A value that will be combined with the first value sent by + /// `self`. + /// + /// - returns: A producer that sends tuples that contain previous and + /// current sent values of `self`. + public func combinePrevious(_ initial: Value) -> SignalProducer<(Value, Value), Error> { + return lift { $0.combinePrevious(initial) } + } + + /// Combine all values from `self`, and forward the final result. + /// + /// See `scan(_:_:)` if the resulting producer needs to forward also the partial + /// results. + /// + /// - parameters: + /// - initialResult: The value to use as the initial accumulating value. + /// - nextPartialResult: A closure that combines the accumulating value and the + /// latest value from `self`. The result would be used in the + /// next call of `nextPartialResult`, or emit to the returned + /// `Signal` when `self` completes. + /// + /// - returns: A producer that sends the final result as `self` completes. + public func reduce(_ initialResult: U, _ nextPartialResult: @escaping (U, Value) -> U) -> SignalProducer { + return lift { $0.reduce(initialResult, nextPartialResult) } + } + + /// Combine all values from `self`, and forward the final result. + /// + /// See `scan(into:_:)` if the resulting producer needs to forward also the partial + /// results. + /// + /// - parameters: + /// - initialResult: The value to use as the initial accumulating value. + /// - nextPartialResult: A closure that combines the accumulating value and the + /// latest value from `self`. The result would be used in the + /// next call of `nextPartialResult`, or emit to the returned + /// `Signal` when `self` completes. + /// + /// - returns: A producer that sends the final value as `self` completes. + public func reduce(into initialResult: U, _ nextPartialResult: @escaping (inout U, Value) -> Void) -> SignalProducer { + return lift { $0.reduce(into: initialResult, nextPartialResult) } + } + + /// Combine all values from `self`, and forward the partial results and the final + /// result. + /// + /// See `reduce(_:_:)` if the resulting producer needs to forward only the final + /// result. + /// + /// - parameters: + /// - initialResult: The value to use as the initial accumulating value. + /// - nextPartialResult: A closure that combines the accumulating value and the + /// latest value from `self`. The result would be forwarded, + /// and would be used in the next call of `nextPartialResult`. + /// + /// - returns: A producer that sends the partial results of the accumuation, and the + /// final result as `self` completes. + public func scan(_ initialResult: U, _ nextPartialResult: @escaping (U, Value) -> U) -> SignalProducer { + return lift { $0.scan(initialResult, nextPartialResult) } + } + + /// Combine all values from `self`, and forward the partial results and the final + /// result. + /// + /// See `reduce(into:_:)` if the resulting producer needs to forward only the final + /// result. + /// + /// - parameters: + /// - initialResult: The value to use as the initial accumulating value. + /// - nextPartialResult: A closure that combines the accumulating value and the + /// latest value from `self`. The result would be forwarded, + /// and would be used in the next call of `nextPartialResult`. + /// + /// - returns: A producer that sends the partial results of the accumuation, and the + /// final result as `self` completes. + public func scan(into initialResult: U, _ nextPartialResult: @escaping (inout U, Value) -> Void) -> SignalProducer { + return lift { $0.scan(into: initialResult, nextPartialResult) } + } + + /// Forward only values from `self` that are not considered equivalent to its + /// immediately preceding value. + /// + /// - note: The first value is always forwarded. + /// + /// - parameters: + /// - isEquivalent: A closure to determine whether two values are equivalent. + /// + /// - returns: A producer which conditionally forwards values from `self` + public func skipRepeats(_ isEquivalent: @escaping (Value, Value) -> Bool) -> SignalProducer { + return lift { $0.skipRepeats(isEquivalent) } + } + + /// Do not forward any value from `self` until `shouldContinue` returns `false`, at + /// which point the returned signal starts to forward values from `self`, including + /// the one leading to the toggling. + /// + /// - parameters: + /// - shouldContinue: A closure to determine whether the skipping should continue. + /// + /// - returns: A producer which conditionally forwards values from `self`. + public func skip(while shouldContinue: @escaping (Value) -> Bool) -> SignalProducer { + return lift { $0.skip(while: shouldContinue) } + } + + /// Forwards events from `self` until `replacement` begins sending events. + /// + /// - parameters: + /// - replacement: A producer to wait to wait for values from and start + /// sending them as a replacement to `self`'s values. + /// + /// - returns: A producer which passes through `value`, `failed`, and + /// `interrupted` events from `self` until `replacement` sends an + /// event, at which point the returned producer will send that + /// event and switch to passing through events from `replacement` + /// instead, regardless of whether `self` has sent events + /// already. + public func take(untilReplacement replacement: Replacement) -> SignalProducer where Replacement.Value == Value, Replacement.Error == Error { + return liftRight(Signal.take(untilReplacement:))(replacement.producer) + } + + /// Wait until `self` completes and then forward the final `count` values + /// on the returned producer. + /// + /// - parameters: + /// - count: Number of last events to send after `self` completes. + /// + /// - returns: A producer that receives up to `count` values from `self` + /// after `self` completes. + public func take(last count: Int) -> SignalProducer { + return lift { $0.take(last: count) } + } + + /// Forward any values from `self` until `shouldContinue` returns `false`, at which + /// point the produced `Signal` would complete. + /// + /// - parameters: + /// - shouldContinue: A closure to determine whether the forwarding of values should + /// continue. + /// + /// - returns: A producer which conditionally forwards values from `self`. + public func take(while shouldContinue: @escaping (Value) -> Bool) -> SignalProducer { + return lift { $0.take(while: shouldContinue) } + } + + /// Zip elements of two producers into pairs. The elements of any Nth pair + /// are the Nth elements of the two input producers. + /// + /// - parameters: + /// - other: A producer to zip values with. + /// + /// - returns: A producer that sends tuples of `self` and `otherProducer`. + public func zip(with other: Other) -> SignalProducer<(Value, Other.Value), Error> where Other.Error == Error { + return SignalProducer.zip(self, other) + } + + /// Apply an action to every value from `self`, and forward the value if the action + /// succeeds. If the action fails with an error, the produced `Signal` would propagate + /// the failure and terminate. + /// + /// - parameters: + /// - action: An action which yields a `Result`. + /// + /// - returns: A producer which forwards the values from `self` until the given action + /// fails. + public func attempt(_ action: @escaping (Value) -> Result<(), Error>) -> SignalProducer { + return lift { $0.attempt(action) } + } + + /// Apply a transform to every value from `self`, and forward the transformed value + /// if the action succeeds. If the action fails with an error, the produced `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - action: A transform which yields a `Result` of the transformed value or the + /// error. + /// + /// - returns: A producer which forwards the transformed values. + public func attemptMap(_ action: @escaping (Value) -> Result) -> SignalProducer { + return lift { $0.attemptMap(action) } + } + + /// Forward the latest value on `scheduler` after at least `interval` + /// seconds have passed since *the returned signal* last sent a value. + /// + /// If `self` always sends values more frequently than `interval` seconds, + /// then the returned signal will send a value every `interval` seconds. + /// + /// To measure from when `self` last sent a value, see `debounce`. + /// + /// - seealso: `debounce` + /// + /// - note: If multiple values are received before the interval has elapsed, + /// the latest value is the one that will be passed on. + /// + /// - note: If `self` terminates while a value is being throttled, that + /// value will be discarded and the returned producer will terminate + /// immediately. + /// + /// - note: If the device time changed backwards before previous date while + /// a value is being throttled, and if there is a new value sent, + /// the new value will be passed anyway. + /// + /// - parameters: + /// - interval: Number of seconds to wait between sent values. + /// - scheduler: A scheduler to deliver events on. + /// + /// - returns: A producer that sends values at least `interval` seconds + /// appart on a given scheduler. + public func throttle(_ interval: TimeInterval, on scheduler: DateScheduler) -> SignalProducer { + return lift { $0.throttle(interval, on: scheduler) } + } + + /// Conditionally throttles values sent on the receiver whenever + /// `shouldThrottle` is true, forwarding values on the given scheduler. + /// + /// - note: While `shouldThrottle` remains false, values are forwarded on the + /// given scheduler. If multiple values are received while + /// `shouldThrottle` is true, the latest value is the one that will + /// be passed on. + /// + /// - note: If the input signal terminates while a value is being throttled, + /// that value will be discarded and the returned signal will + /// terminate immediately. + /// + /// - note: If `shouldThrottle` completes before the receiver, and its last + /// value is `true`, the returned signal will remain in the throttled + /// state, emitting no further values until it terminates. + /// + /// - parameters: + /// - shouldThrottle: A boolean property that controls whether values + /// should be throttled. + /// - scheduler: A scheduler to deliver events on. + /// + /// - returns: A producer that sends values only while `shouldThrottle` is false. + public func throttle(while shouldThrottle: P, on scheduler: Scheduler) -> SignalProducer + where P.Value == Bool + { + // Using `Property.init(_:)` avoids capturing a strong reference + // to `shouldThrottle`, so that we don't extend its lifetime. + let shouldThrottle = Property(shouldThrottle) + + return lift { $0.throttle(while: shouldThrottle, on: scheduler) } + } + + /// Forward the latest value on `scheduler` after at least `interval` + /// seconds have passed since `self` last sent a value. + /// + /// If `self` always sends values more frequently than `interval` seconds, + /// then the returned signal will never send any values. + /// + /// To measure from when the *returned signal* last sent a value, see + /// `throttle`. + /// + /// - seealso: `throttle` + /// + /// - note: If multiple values are received before the interval has elapsed, + /// the latest value is the one that will be passed on. + /// + /// - note: If `self` terminates while a value is being debounced, + /// that value will be discarded and the returned producer will + /// terminate immediately. + /// + /// - parameters: + /// - interval: A number of seconds to wait before sending a value. + /// - scheduler: A scheduler to send values on. + /// + /// - returns: A producer that sends values that are sent from `self` at + /// least `interval` seconds apart. + public func debounce(_ interval: TimeInterval, on scheduler: DateScheduler) -> SignalProducer { + return lift { $0.debounce(interval, on: scheduler) } + } + + /// Forward events from `self` until `interval`. Then if producer isn't + /// completed yet, fails with `error` on `scheduler`. + /// + /// - note: If the interval is 0, the timeout will be scheduled immediately. + /// The producer must complete synchronously (or on a faster + /// scheduler) to avoid the timeout. + /// + /// - parameters: + /// - interval: Number of seconds to wait for `self` to complete. + /// - error: Error to send with `failed` event if `self` is not completed + /// when `interval` passes. + /// - scheduler: A scheduler to deliver error on. + /// + /// - returns: A producer that sends events for at most `interval` seconds, + /// then, if not `completed` - sends `error` with `failed` event + /// on `scheduler`. + public func timeout(after interval: TimeInterval, raising error: Error, on scheduler: DateScheduler) -> SignalProducer { + return lift { $0.timeout(after: interval, raising: error, on: scheduler) } + } +} + +extension SignalProducer where Value: OptionalProtocol { + /// Unwraps non-`nil` values and forwards them on the returned signal, `nil` + /// values are dropped. + /// + /// - returns: A producer that sends only non-nil values. + public func skipNil() -> SignalProducer { + return lift { $0.skipNil() } + } +} + +extension SignalProducer where Value: EventProtocol, Error == NoError { + /// The inverse of materialize(), this will translate a producer of `Event` + /// _values_ into a producer of those events themselves. + /// + /// - returns: A producer that sends values carried by `self` events. + public func dematerialize() -> SignalProducer { + return lift { $0.dematerialize() } + } +} + +extension SignalProducer where Error == NoError { + /// Promote a producer that does not generate failures into one that can. + /// + /// - note: This does not actually cause failers to be generated for the + /// given producer, but makes it easier to combine with other + /// producers that may fail; for example, with operators like + /// `combineLatestWith`, `zipWith`, `flatten`, etc. + /// + /// - parameters: + /// - _ An `ErrorType`. + /// + /// - returns: A producer that has an instantiatable `ErrorType`. + public func promoteError(_: F.Type = F.self) -> SignalProducer { + return lift { $0.promoteError(F.self) } + } + + /// Promote a producer that does not generate failures into one that can. + /// + /// - note: This does not actually cause failers to be generated for the + /// given producer, but makes it easier to combine with other + /// producers that may fail; for example, with operators like + /// `combineLatestWith`, `zipWith`, `flatten`, etc. + /// + /// - parameters: + /// - _ An `ErrorType`. + /// + /// - returns: A producer that has an instantiatable `ErrorType`. + public func promoteError(_: Error.Type = Error.self) -> SignalProducer { + return self + } + + /// Forward events from `self` until `interval`. Then if producer isn't + /// completed yet, fails with `error` on `scheduler`. + /// + /// - note: If the interval is 0, the timeout will be scheduled immediately. + /// The producer must complete synchronously (or on a faster + /// scheduler) to avoid the timeout. + /// + /// - parameters: + /// - interval: Number of seconds to wait for `self` to complete. + /// - error: Error to send with `failed` event if `self` is not completed + /// when `interval` passes. + /// - scheudler: A scheduler to deliver error on. + /// + /// - returns: A producer that sends events for at most `interval` seconds, + /// then, if not `completed` - sends `error` with `failed` event + /// on `scheduler`. + public func timeout( + after interval: TimeInterval, + raising error: NewError, + on scheduler: DateScheduler + ) -> SignalProducer { + return lift { $0.timeout(after: interval, raising: error, on: scheduler) } + } + + /// Apply a throwable action to every value from `self`, and forward the values + /// if the action succeeds. If the action throws an error, the produced `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - action: A throwable closure to perform an arbitrary action on the value. + /// + /// - returns: A producer which forwards the successful values of the given action. + public func attempt(_ action: @escaping (Value) throws -> Void) -> SignalProducer { + return lift { $0.attempt(action) } + } + + /// Apply a throwable action to every value from `self`, and forward the results + /// if the action succeeds. If the action throws an error, the produced `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - action: A throwable closure to perform an arbitrary action on the value, and + /// yield a result. + /// + /// - returns: A producer which forwards the successful results of the given action. + public func attemptMap(_ action: @escaping (Value) throws -> U) -> SignalProducer { + return lift { $0.attemptMap(action) } + } +} + +extension SignalProducer where Error == AnyError { + /// Apply a throwable action to every value from `self`, and forward the values + /// if the action succeeds. If the action throws an error, the produced `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - action: A throwable closure to perform an arbitrary action on the value. + /// + /// - returns: A producer which forwards the successful values of the given action. + public func attempt(_ action: @escaping (Value) throws -> Void) -> SignalProducer { + return lift { $0.attempt(action) } + } + + /// Apply a throwable transform to every value from `self`, and forward the results + /// if the action succeeds. If the transform throws an error, the produced `Signal` + /// would propagate the failure and terminate. + /// + /// - parameters: + /// - transform: A throwable transform. + /// + /// - returns: A producer which forwards the successfully transformed values. + public func attemptMap(_ transform: @escaping (Value) throws -> U) -> SignalProducer { + return lift { $0.attemptMap(transform) } + } +} + +extension SignalProducer where Value == Never { + /// Promote a signal that does not generate values, as indicated by `Never`, to be + /// a signal of the given type of value. + /// + /// - note: The promotion does not result in any value being generated. + /// + /// - parameters: + /// - _ The type of value to promote to. + /// + /// - returns: A signal that forwards all terminal events from `self`. + public func promoteValue(_: U.Type = U.self) -> SignalProducer { + return lift { $0.promoteValue(U.self) } + } + + /// Promote a signal that does not generate values, as indicated by `Never`, to be + /// a signal of the given type of value. + /// + /// - note: The promotion does not result in any value being generated. + /// + /// - parameters: + /// - _ The type of value to promote to. + /// + /// - returns: A signal that forwards all terminal events from `self`. + public func promoteValue(_: Value.Type = Value.self) -> SignalProducer { + return self + } +} + +extension SignalProducer where Value: Equatable { + /// Forward only values from `self` that are not equal to its immediately preceding + /// value. + /// + /// - note: The first value is always forwarded. + /// + /// - returns: A property which conditionally forwards values from `self`. + public func skipRepeats() -> SignalProducer { + return lift { $0.skipRepeats() } + } +} + +extension SignalProducer { + /// Forward only those values from `self` that have unique identities across + /// the set of all values that have been seen. + /// + /// - note: This causes the identities to be retained to check for + /// uniqueness. + /// + /// - parameters: + /// - transform: A closure that accepts a value and returns identity + /// value. + /// + /// - returns: A producer that sends unique values during its lifetime. + public func uniqueValues(_ transform: @escaping (Value) -> Identity) -> SignalProducer { + return lift { $0.uniqueValues(transform) } + } +} + +extension SignalProducer where Value: Hashable { + /// Forward only those values from `self` that are unique across the set of + /// all values that have been seen. + /// + /// - note: This causes the values to be retained to check for uniqueness. + /// Providing a function that returns a unique value for each sent + /// value can help you reduce the memory footprint. + /// + /// - returns: A producer that sends unique values during its lifetime. + public func uniqueValues() -> SignalProducer { + return lift { $0.uniqueValues() } + } +} + +extension SignalProducer { + /// Injects side effects to be performed upon the specified producer events. + /// + /// - note: In a composed producer, `starting` is invoked in the reverse + /// direction of the flow of events. + /// + /// - parameters: + /// - starting: A closure that is invoked before the producer is started. + /// - started: A closure that is invoked after the producer is started. + /// - event: A closure that accepts an event and is invoked on every + /// received event. + /// - failed: A closure that accepts error object and is invoked for + /// `failed` event. + /// - completed: A closure that is invoked for `completed` event. + /// - interrupted: A closure that is invoked for `interrupted` event. + /// - terminated: A closure that is invoked for any terminating event. + /// - disposed: A closure added as disposable when signal completes. + /// - value: A closure that accepts a value from `value` event. + /// + /// - returns: A producer with attached side-effects for given event cases. + public func on( + starting: (() -> Void)? = nil, + started: (() -> Void)? = nil, + event: ((ProducedSignal.Event) -> Void)? = nil, + failed: ((Error) -> Void)? = nil, + completed: (() -> Void)? = nil, + interrupted: (() -> Void)? = nil, + terminated: (() -> Void)? = nil, + disposed: (() -> Void)? = nil, + value: ((Value) -> Void)? = nil + ) -> SignalProducer { + return SignalProducer { () -> Instance in + let instance = self.producer.builder() + let signal = instance.producedSignal.on(event: event, + failed: failed, + completed: completed, + interrupted: interrupted, + terminated: terminated, + disposed: disposed, + value: value) + + return Instance(producedSignal: signal, + observerDidSetup: { starting?(); instance.observerDidSetup(); started?() }, + interruptHandle: instance.interruptHandle) + } + } + + /// Start the returned producer on the given `Scheduler`. + /// + /// - note: This implies that any side effects embedded in the producer will + /// be performed on the given scheduler as well. + /// + /// - note: Events may still be sent upon other schedulers — this merely + /// affects where the `start()` method is run. + /// + /// - parameters: + /// - scheduler: A scheduler to deliver events on. + /// + /// - returns: A producer that will deliver events on given `scheduler` when + /// started. + public func start(on scheduler: Scheduler) -> SignalProducer { + return SignalProducer { observer, lifetime in + let disposable = scheduler.schedule { + self.startWithSignal { signal, signalDisposable in + lifetime.observeEnded(signalDisposable.dispose) + signal.observe(observer) + } + } + + if let d = disposable { lifetime.observeEnded(d.dispose) } + } + } +} + +extension SignalProducer { + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B) -> SignalProducer<(Value, B.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer) { Signal.combineLatest($0, $1).observe(observer) } + } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C) -> SignalProducer<(Value, B.Value, C.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer) { Signal.combineLatest($0, $1, $2).observe(observer) } + } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D) -> SignalProducer<(Value, B.Value, C.Value, D.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer) { Signal.combineLatest($0, $1, $2, $3).observe(observer) } + } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value), Error> where A.Value == Value, A.Error == Error , B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer) { Signal.combineLatest($0, $1, $2, $3, $4).observe(observer) } + } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer) { Signal.combineLatest($0, $1, $2, $3, $4, $5).observe(observer) } + } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error, G.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer) { Signal.combineLatest($0, $1, $2, $3, $4, $5, $6).observe(observer) } + } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error, G.Error == Error, H.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer) { Signal.combineLatest($0, $1, $2, $3, $4, $5, $6, $7).observe(observer) } + } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error, G.Error == Error, H.Error == Error, I.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer, i.producer) { Signal.combineLatest($0, $1, $2, $3, $4, $5, $6, $7, $8).observe(observer) } + } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. + public static func combineLatest(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I, _ j: J) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value, J.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error, G.Error == Error, H.Error == Error, I.Error == Error, J.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer, i.producer, j.producer) { Signal.combineLatest($0, $1, $2, $3, $4, $5, $6, $7, $8, $9).observe(observer) } + } + } + + /// Combines the values of all the given producers, in the manner described by + /// `combineLatest(with:)`. Will return an empty `SignalProducer` if the sequence is empty. + public static func combineLatest(_ producers: S) -> SignalProducer<[Value], Error> where S.Iterator.Element: SignalProducerConvertible, S.Iterator.Element.Value == Value, S.Iterator.Element.Error == Error { + return start(producers, Signal.combineLatest) + } + + /// Zips the values of all the given producers, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B) -> SignalProducer<(Value, B.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer) { Signal.zip($0, $1).observe(observer) } + } + } + + /// Zips the values of all the given producers, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C) -> SignalProducer<(Value, B.Value, C.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer) { Signal.zip($0, $1, $2).observe(observer) } + } + } + + /// Zips the values of all the given producers, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D) -> SignalProducer<(Value, B.Value, C.Value, D.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer) { Signal.zip($0, $1, $2, $3).observe(observer) } + } + } + + /// Zips the values of all the given producers, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer) { Signal.zip($0, $1, $2, $3, $4).observe(observer) } + } + } + + /// Zips the values of all the given producers, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer) { Signal.zip($0, $1, $2, $3, $4, $5).observe(observer) } + } + } + + /// Zips the values of all the given producers, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error, G.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer) { Signal.zip($0, $1, $2, $3, $4, $5, $6).observe(observer) } + } + } + + /// Zips the values of all the given producers, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error, G.Error == Error, H.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer) { Signal.zip($0, $1, $2, $3, $4, $5, $6, $7).observe(observer) } + } + } + + /// Zips the values of all the given producers, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error, G.Error == Error, H.Error == Error, I.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer, i.producer) { Signal.zip($0, $1, $2, $3, $4, $5, $6, $7, $8).observe(observer) } + } + } + + /// Zips the values of all the given producers, in the manner described by + /// `zip(with:)`. + public static func zip(_ a: A, _ b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h: H, _ i: I, _ j: J) -> SignalProducer<(Value, B.Value, C.Value, D.Value, E.Value, F.Value, G.Value, H.Value, I.Value, J.Value), Error> where A.Value == Value, A.Error == Error, B.Error == Error, C.Error == Error, D.Error == Error, E.Error == Error, F.Error == Error, G.Error == Error, H.Error == Error, I.Error == Error, J.Error == Error { + return .init { observer, lifetime in + flattenStart(lifetime, a.producer, b.producer, c.producer, d.producer, e.producer, f.producer, g.producer, h.producer, i.producer, j.producer) { Signal.zip($0, $1, $2, $3, $4, $5, $6, $7, $8, $9).observe(observer) } + } + } + + /// Zips the values of all the given producers, in the manner described by + /// `zipWith`. Will return an empty `SignalProducer` if the sequence is empty. + public static func zip(_ producers: S) -> SignalProducer<[Value], Error> where S.Iterator.Element: SignalProducerConvertible, S.Iterator.Element.Value == Value, S.Iterator.Element.Error == Error { + return start(producers, Signal.zip) + } + + private static func start(_ producers: S, _ transform: @escaping (ReversedRandomAccessCollection<[Signal]>) -> Signal<[Value], Error>) -> SignalProducer<[Value], Error> where S.Iterator.Element: SignalProducerConvertible, S.Iterator.Element.Value == Value, S.Iterator.Element.Error == Error { + return SignalProducer<[Value], Error> { observer, lifetime in + var producers = Array(producers) + var signals: [Signal] = [] + + guard !producers.isEmpty else { + observer.sendCompleted() + return + } + + func start() { + guard !producers.isEmpty else { + transform(signals.reversed()).observe(observer) + return + } + + producers.removeLast().producer.startWithSignal { signal, interruptHandle in + lifetime.observeEnded(interruptHandle.dispose) + signals.append(signal) + + start() + } + } + + start() + } + } +} + +extension SignalProducer { + /// Repeat `self` a total of `count` times. In other words, start producer + /// `count` number of times, each one after previously started producer + /// completes. + /// + /// - note: Repeating `1` time results in an equivalent signal producer. + /// + /// - note: Repeating `0` times results in a producer that instantly + /// completes. + /// + /// - precondition: `count` must be non-negative integer. + /// + /// - parameters: + /// - count: Number of repetitions. + /// + /// - returns: A signal producer start sequentially starts `self` after + /// previously started producer completes. + public func `repeat`(_ count: Int) -> SignalProducer { + precondition(count >= 0) + + if count == 0 { + return .empty + } else if count == 1 { + return producer + } + + return SignalProducer { observer, lifetime in + let serialDisposable = SerialDisposable() + lifetime.observeEnded(serialDisposable.dispose) + + func iterate(_ current: Int) { + self.startWithSignal { signal, signalDisposable in + serialDisposable.inner = signalDisposable + + signal.observe { event in + if case .completed = event { + let remainingTimes = current - 1 + if remainingTimes > 0 { + iterate(remainingTimes) + } else { + observer.sendCompleted() + } + } else { + observer.action(event) + } + } + } + } + + iterate(count) + } + } + + /// Ignore failures up to `count` times. + /// + /// - precondition: `count` must be non-negative integer. + /// + /// - parameters: + /// - count: Number of retries. + /// + /// - returns: A signal producer that restarts up to `count` times. + public func retry(upTo count: Int) -> SignalProducer { + precondition(count >= 0) + + if count == 0 { + return producer + } else { + return flatMapError { _ in + self.retry(upTo: count - 1) + } + } + } + + /// Wait for completion of `self`, *then* forward all events from + /// `replacement`. Any failure or interruption sent from `self` is + /// forwarded immediately, in which case `replacement` will not be started, + /// and none of its events will be be forwarded. + /// + /// - note: All values sent from `self` are ignored. + /// + /// - parameters: + /// - replacement: A producer to start when `self` completes. + /// + /// - returns: A producer that sends events from `self` and then from + /// `replacement` when `self` completes. + public func then(_ replacement: SignalProducer) -> SignalProducer { + return _then(replacement.promoteError(Error.self)) + } + + /// Wait for completion of `self`, *then* forward all events from + /// `replacement`. Any failure or interruption sent from `self` is + /// forwarded immediately, in which case `replacement` will not be started, + /// and none of its events will be be forwarded. + /// + /// - note: All values sent from `self` are ignored. + /// + /// - parameters: + /// - replacement: A producer to start when `self` completes. + /// + /// - returns: A producer that sends events from `self` and then from + /// `replacement` when `self` completes. + public func then(_ replacement: SignalProducer) -> SignalProducer { + return _then(replacement) + } + + // NOTE: The overload below is added to disambiguate compile-time selection of + // `then(_:)`. + + /// Wait for completion of `self`, *then* forward all events from + /// `replacement`. Any failure or interruption sent from `self` is + /// forwarded immediately, in which case `replacement` will not be started, + /// and none of its events will be be forwarded. + /// + /// - note: All values sent from `self` are ignored. + /// + /// - parameters: + /// - replacement: A producer to start when `self` completes. + /// + /// - returns: A producer that sends events from `self` and then from + /// `replacement` when `self` completes. + public func then(_ replacement: SignalProducer) -> SignalProducer { + return _then(replacement) + } + + // NOTE: The method below is the shared implementation of `then(_:)`. The underscore + // prefix is added to avoid self referencing in `then(_:)` overloads with + // regard to the most specific rule of overload selection in Swift. + + internal func _then(_ replacement: SignalProducer) -> SignalProducer { + return SignalProducer { observer, lifetime in + self.startWithSignal { signal, signalDisposable in + lifetime.observeEnded(signalDisposable.dispose) + + signal.observe { event in + switch event { + case let .failed(error): + observer.send(error: error) + case .completed: + let interruptHandle = replacement.start(observer) + lifetime.observeEnded(interruptHandle.dispose) + case .interrupted: + observer.sendInterrupted() + case .value: + break + } + } + } + } + } +} + +extension SignalProducer where Error == NoError { + /// Wait for completion of `self`, *then* forward all events from + /// `replacement`. + /// + /// - note: All values sent from `self` are ignored. + /// + /// - parameters: + /// - replacement: A producer to start when `self` completes. + /// + /// - returns: A producer that sends events from `self` and then from + /// `replacement` when `self` completes. + public func then(_ replacement: SignalProducer) -> SignalProducer { + return promoteError(NewError.self)._then(replacement) + } + + // NOTE: The overload below is added to disambiguate compile-time selection of + // `then(_:)`. + + /// Wait for completion of `self`, *then* forward all events from + /// `replacement`. + /// + /// - note: All values sent from `self` are ignored. + /// + /// - parameters: + /// - replacement: A producer to start when `self` completes. + /// + /// - returns: A producer that sends events from `self` and then from + /// `replacement` when `self` completes. + public func then(_ replacement: SignalProducer) -> SignalProducer { + return _then(replacement) + } +} + +extension SignalProducer { + /// Start the producer, then block, waiting for the first value. + /// + /// When a single value or error is sent, the returned `Result` will + /// represent those cases. However, when no values are sent, `nil` will be + /// returned. + /// + /// - returns: Result when single `value` or `failed` event is received. + /// `nil` when no events are received. + public func first() -> Result? { + return take(first: 1).single() + } + + /// Start the producer, then block, waiting for events: `value` and + /// `completed`. + /// + /// When a single value or error is sent, the returned `Result` will + /// represent those cases. However, when no values are sent, or when more + /// than one value is sent, `nil` will be returned. + /// + /// - returns: Result when single `value` or `failed` event is received. + /// `nil` when 0 or more than 1 events are received. + public func single() -> Result? { + let semaphore = DispatchSemaphore(value: 0) + var result: Result? + + take(first: 2).start { event in + switch event { + case let .value(value): + if result != nil { + // Move into failure state after recieving another value. + result = nil + return + } + result = .success(value) + case let .failed(error): + result = .failure(error) + semaphore.signal() + case .completed, .interrupted: + semaphore.signal() + } + } + + semaphore.wait() + return result + } + + /// Start the producer, then block, waiting for the last value. + /// + /// When a single value or error is sent, the returned `Result` will + /// represent those cases. However, when no values are sent, `nil` will be + /// returned. + /// + /// - returns: Result when single `value` or `failed` event is received. + /// `nil` when no events are received. + public func last() -> Result? { + return take(last: 1).single() + } + + /// Starts the producer, then blocks, waiting for completion. + /// + /// When a completion or error is sent, the returned `Result` will represent + /// those cases. + /// + /// - returns: Result when single `completion` or `failed` event is + /// received. + public func wait() -> Result<(), Error> { + return then(SignalProducer<(), Error>(value: ())).last() ?? .success(()) + } + + /// Creates a new `SignalProducer` that will multicast values emitted by + /// the underlying producer, up to `capacity`. + /// This means that all clients of this `SignalProducer` will see the same + /// version of the emitted values/errors. + /// + /// The underlying `SignalProducer` will not be started until `self` is + /// started for the first time. When subscribing to this producer, all + /// previous values (up to `capacity`) will be emitted, followed by any new + /// values. + /// + /// If you find yourself needing *the current value* (the last buffered + /// value) you should consider using `PropertyType` instead, which, unlike + /// this operator, will guarantee at compile time that there's always a + /// buffered value. This operator is not recommended in most cases, as it + /// will introduce an implicit relationship between the original client and + /// the rest, so consider alternatives like `PropertyType`, or representing + /// your stream using a `Signal` instead. + /// + /// This operator is only recommended when you absolutely need to introduce + /// a layer of caching in front of another `SignalProducer`. + /// + /// - precondition: `capacity` must be non-negative integer. + /// + /// - parameters: + /// - capacity: Number of values to hold. + /// + /// - returns: A caching producer that will hold up to last `capacity` + /// values. + public func replayLazily(upTo capacity: Int) -> SignalProducer { + precondition(capacity >= 0, "Invalid capacity: \(capacity)") + + // This will go "out of scope" when the returned `SignalProducer` goes + // out of scope. This lets us know when we're supposed to dispose the + // underlying producer. This is necessary because `struct`s don't have + // `deinit`. + let lifetimeToken = Lifetime.Token() + let lifetime = Lifetime(lifetimeToken) + + let state = Atomic(ReplayState(upTo: capacity)) + + let start: Atomic<(() -> Void)?> = Atomic { + // Start the underlying producer. + self + .take(during: lifetime) + .start { event in + let observers: Bag.Observer>? = state.modify { state in + defer { state.enqueue(event) } + return state.observers + } + observers?.forEach { $0.action(event) } + } + } + + return SignalProducer { observer, lifetime in + // Don't dispose of the original producer until all observers + // have terminated. + lifetime.observeEnded { _ = lifetimeToken } + + while true { + var result: Result.Observer>.Token?, ReplayError>! + state.modify { + result = $0.observe(observer) + } + + switch result! { + case let .success(token): + if let token = token { + lifetime.observeEnded { + state.modify { + $0.removeObserver(using: token) + } + } + } + + // Start the underlying producer if it has never been started. + start.swap(nil)?() + + // Terminate the replay loop. + return + + case let .failure(error): + error.values.forEach(observer.send(value:)) + } + } + } + } +} + +extension SignalProducer where Value == Bool { + /// Create a producer that computes a logical NOT in the latest values of `self`. + /// + /// - returns: A producer that emits the logical NOT results. + public func negate() -> SignalProducer { + return self.lift { $0.negate() } + } + + /// Create a producer that computes a logical AND between the latest values of `self` + /// and `producer`. + /// + /// - parameters: + /// - booleans: A producer of booleans to be combined with `self`. + /// + /// - returns: A producer that emits the logical AND results. + public func and(_ booleans: Booleans) -> SignalProducer where Booleans.Value == Value, Booleans.Error == Error { + return self.liftLeft(Signal.and)(booleans.producer) + } + + /// Create a producer that computes a logical OR between the latest values of `self` + /// and `producer`. + /// + /// - parameters: + /// - booleans: A producer of booleans to be combined with `self`. + /// + /// - returns: A producer that emits the logical OR results. + public func or(_ booleans: Booleans) -> SignalProducer where Booleans.Value == Value, Booleans.Error == Error { + return self.liftLeft(Signal.or)(booleans.producer) + } +} + +/// Represents a recoverable error of an observer not being ready for an +/// attachment to a `ReplayState`, and the observer should replay the supplied +/// values before attempting to observe again. +private struct ReplayError: Error { + /// The values that should be replayed by the observer. + let values: [Value] +} + +private struct ReplayState { + let capacity: Int + + /// All cached values. + var values: [Value] = [] + + /// A termination event emitted by the underlying producer. + /// + /// This will be nil if termination has not occurred. + var terminationEvent: Signal.Event? + + /// The observers currently attached to the caching producer, or `nil` if the + /// caching producer was terminated. + var observers: Bag.Observer>? = Bag() + + /// The set of in-flight replay buffers. + var replayBuffers: [ObjectIdentifier: [Value]] = [:] + + /// Initialize the replay state. + /// + /// - parameters: + /// - capacity: The maximum amount of values which can be cached by the + /// replay state. + init(upTo capacity: Int) { + self.capacity = capacity + } + + /// Attempt to observe the replay state. + /// + /// - warning: Repeatedly observing the replay state with the same observer + /// should be avoided. + /// + /// - parameters: + /// - observer: The observer to be registered. + /// + /// - returns: If the observer is successfully attached, a `Result.success` + /// with the corresponding removal token would be returned. + /// Otherwise, a `Result.failure` with a `ReplayError` would be + /// returned. + mutating func observe(_ observer: Signal.Observer) -> Result.Observer>.Token?, ReplayError> { + // Since the only use case is `replayLazily`, which always creates a unique + // `Observer` for every produced signal, we can use the ObjectIdentifier of + // the `Observer` to track them directly. + let id = ObjectIdentifier(observer) + + switch replayBuffers[id] { + case .none where !values.isEmpty: + // No in-flight replay buffers was found, but the `ReplayState` has one or + // more cached values in the `ReplayState`. The observer should replay + // them before attempting to observe again. + replayBuffers[id] = [] + return .failure(ReplayError(values: values)) + + case let .some(buffer) where !buffer.isEmpty: + // An in-flight replay buffer was found with one or more buffered values. + // The observer should replay them before attempting to observe again. + defer { replayBuffers[id] = [] } + return .failure(ReplayError(values: buffer)) + + case let .some(buffer) where buffer.isEmpty: + // Since an in-flight but empty replay buffer was found, the observer is + // ready to be attached to the `ReplayState`. + replayBuffers.removeValue(forKey: id) + + default: + // No values has to be replayed. The observer is ready to be attached to + // the `ReplayState`. + break + } + + if let event = terminationEvent { + observer.action(event) + } + + return .success(observers?.insert(observer)) + } + + /// Enqueue the supplied event to the replay state. + /// + /// - parameter: + /// - event: The event to be cached. + mutating func enqueue(_ event: Signal.Event) { + switch event { + case let .value(value): + for key in replayBuffers.keys { + replayBuffers[key]!.append(value) + } + + switch capacity { + case 0: + // With a capacity of zero, `state.values` can never be filled. + break + + case 1: + values = [value] + + default: + values.append(value) + + let overflow = values.count - capacity + if overflow > 0 { + values.removeFirst(overflow) + } + } + + case .completed, .failed, .interrupted: + // Disconnect all observers and prevent future attachments. + terminationEvent = event + observers = nil + } + } + + /// Remove the observer represented by the supplied token. + /// + /// - parameters: + /// - token: The token of the observer to be removed. + mutating func removeObserver(using token: Bag.Observer>.Token) { + observers?.remove(using: token) + } +} + +extension SignalProducer where Value == Date, Error == NoError { + /// Create a repeating timer of the given interval, with a reasonable default + /// leeway, sending updates on the given scheduler. + /// + /// - note: This timer will never complete naturally, so all invocations of + /// `start()` must be disposed to avoid leaks. + /// + /// - precondition: `interval` must be non-negative number. + /// + /// - note: If you plan to specify an `interval` value greater than 200,000 + /// seconds, use `timer(interval:on:leeway:)` instead + /// and specify your own `leeway` value to avoid potential overflow. + /// + /// - parameters: + /// - interval: An interval between invocations. + /// - scheduler: A scheduler to deliver events on. + /// + /// - returns: A producer that sends `NSDate` values every `interval` seconds. + public static func timer(interval: DispatchTimeInterval, on scheduler: DateScheduler) -> SignalProducer { + // Apple's "Power Efficiency Guide for Mac Apps" recommends a leeway of + // at least 10% of the timer interval. + return timer(interval: interval, on: scheduler, leeway: interval * 0.1) + } + + /// Creates a repeating timer of the given interval, sending updates on the + /// given scheduler. + /// + /// - note: This timer will never complete naturally, so all invocations of + /// `start()` must be disposed to avoid leaks. + /// + /// - precondition: `interval` must be non-negative number. + /// + /// - precondition: `leeway` must be non-negative number. + /// + /// - parameters: + /// - interval: An interval between invocations. + /// - scheduler: A scheduler to deliver events on. + /// - leeway: Interval leeway. Apple's "Power Efficiency Guide for Mac Apps" + /// recommends a leeway of at least 10% of the timer interval. + /// + /// - returns: A producer that sends `NSDate` values every `interval` seconds. + public static func timer(interval: DispatchTimeInterval, on scheduler: DateScheduler, leeway: DispatchTimeInterval) -> SignalProducer { + precondition(interval.timeInterval >= 0) + precondition(leeway.timeInterval >= 0) + + return SignalProducer { observer, lifetime in + let disposable = scheduler.schedule(after: scheduler.currentDate.addingTimeInterval(interval), + interval: interval, + leeway: leeway, + action: { observer.send(value: scheduler.currentDate) }) + if let d = disposable { lifetime.observeEnded(d.dispose)} + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/UnidirectionalBinding.swift b/Carthage/Checkouts/ReactiveSwift/Sources/UnidirectionalBinding.swift new file mode 100644 index 0000000..96ca7ef --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/UnidirectionalBinding.swift @@ -0,0 +1,151 @@ +import Foundation +import Dispatch +import enum Result.NoError + +precedencegroup BindingPrecedence { + associativity: right + + // Binds tighter than assignment but looser than everything else + higherThan: AssignmentPrecedence +} + +infix operator <~ : BindingPrecedence + +// FIXME: Swift 4 - associated type arbitrary requirements +// public protocol BindingSource: SignalProducerConvertible where Error == NoError {} + +/// Describes a source which can be bound. +public protocol BindingSource: SignalProducerConvertible { + // FIXME: Swift 4 compiler regression. + // All requirements are replicated to workaround the type checker issue. + // https://bugs.swift.org/browse/SR-5090 + + associatedtype Value + associatedtype Error + + var producer: SignalProducer { get } +} +extension Signal: BindingSource {} +extension SignalProducer: BindingSource {} + +/// Describes an entity which be bond towards. +public protocol BindingTargetProvider { + associatedtype Value + + var bindingTarget: BindingTarget { get } +} + +extension BindingTargetProvider { + /// Binds a source to a target, updating the target's value to the latest + /// value sent by the source. + /// + /// - note: The binding will automatically terminate when the target is + /// deinitialized, or when the source sends a `completed` event. + /// + /// ```` + /// let property = MutableProperty(0) + /// let signal = Signal({ /* do some work after some time */ }) + /// property <~ signal + /// ```` + /// + /// ```` + /// let property = MutableProperty(0) + /// let signal = Signal({ /* do some work after some time */ }) + /// let disposable = property <~ signal + /// ... + /// // Terminates binding before property dealloc or signal's + /// // `completed` event. + /// disposable.dispose() + /// ```` + /// + /// - parameters: + /// - target: A target to be bond to. + /// - source: A source to bind. + /// + /// - returns: A disposable that can be used to terminate binding before the + /// deinitialization of the target or the source's `completed` + /// event. + @discardableResult + public static func <~ + + (provider: Self, source: Source) -> Disposable? + where Source.Value == Value, Source.Error == NoError + { + return source.producer + .take(during: provider.bindingTarget.lifetime) + .startWithValues(provider.bindingTarget.action) + } + + /// Binds a source to a target, updating the target's value to the latest + /// value sent by the source. + /// + /// - note: The binding will automatically terminate when the target is + /// deinitialized, or when the source sends a `completed` event. + /// + /// ```` + /// let property = MutableProperty(0) + /// let signal = Signal({ /* do some work after some time */ }) + /// property <~ signal + /// ```` + /// + /// ```` + /// let property = MutableProperty(0) + /// let signal = Signal({ /* do some work after some time */ }) + /// let disposable = property <~ signal + /// ... + /// // Terminates binding before property dealloc or signal's + /// // `completed` event. + /// disposable.dispose() + /// ```` + /// + /// - parameters: + /// - target: A target to be bond to. + /// - source: A source to bind. + /// + /// - returns: A disposable that can be used to terminate binding before the + /// deinitialization of the target or the source's `completed` + /// event. + @discardableResult + public static func <~ + + (provider: Self, source: Source) -> Disposable? + where Value == Source.Value?, Source.Error == NoError + { + return provider <~ source.producer.optionalize() + } +} + +/// A binding target that can be used with the `<~` operator. +public struct BindingTarget: BindingTargetProvider { + public let lifetime: Lifetime + public let action: (Value) -> Void + + public var bindingTarget: BindingTarget { + return self + } + + /// Creates a binding target. + /// + /// - parameters: + /// - lifetime: The expected lifetime of any bindings towards `self`. + /// - action: The action to consume values. + public init(lifetime: Lifetime, action: @escaping (Value) -> Void) { + self.action = action + self.lifetime = lifetime + } + + /// Creates a binding target which consumes values on the specified scheduler. + /// + /// - parameters: + /// - scheduler: The scheduler on which the `setter` consumes the values. + /// - lifetime: The expected lifetime of any bindings towards `self`. + /// - action: The action to consume values. + public init(on scheduler: Scheduler, lifetime: Lifetime, action: @escaping (Value) -> Void) { + let setter: (Value) -> Void = { value in + scheduler.schedule { + action(value) + } + } + self.init(lifetime: lifetime, action: setter) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Sources/ValidatingProperty.swift b/Carthage/Checkouts/ReactiveSwift/Sources/ValidatingProperty.swift new file mode 100644 index 0000000..c6a409e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Sources/ValidatingProperty.swift @@ -0,0 +1,327 @@ +import Result + +/// A mutable property that validates mutations before committing them. +/// +/// If the property wraps an arbitrary mutable property, changes originated from +/// the inner property are monitored, and would be automatically validated. +/// Note that these would still appear as committed values even if they fail the +/// validation. +/// +/// ``` +/// let root = MutableProperty("Valid") +/// let outer = ValidatingProperty(root) { +/// $0 == "Valid" ? .valid : .invalid(.outerInvalid) +/// } +/// +/// outer.result.value // `.valid("Valid") +/// +/// root.value = "🎃" +/// outer.result.value // `.invalid("🎃", .outerInvalid)` +/// ``` +public final class ValidatingProperty: MutablePropertyProtocol { + private let getter: () -> Value + private let setter: (Value) -> Void + + /// The result of the last attempted edit of the root property. + public let result: Property> + + /// The current value of the property. + /// + /// The value could have failed the validation. Refer to `result` for the + /// latest validation result. + public var value: Value { + get { return getter() } + set { setter(newValue) } + } + + /// A producer for Signals that will send the property's current value, + /// followed by all changes over time, then complete when the property has + /// deinitialized. + public let producer: SignalProducer + + /// A signal that will send the property's changes over time, + /// then complete when the property has deinitialized. + public let signal: Signal + + /// The lifetime of the property. + public let lifetime: Lifetime + + /// Create a `ValidatingProperty` that presents a mutable validating + /// view for an inner mutable property. + /// + /// The proposed value is only committed when `valid` is returned by the + /// `validator` closure. + /// + /// - note: `inner` is retained by the created property. + /// + /// - parameters: + /// - inner: The inner property which validated values are committed to. + /// - validator: The closure to invoke for any proposed value to `self`. + public init( + _ inner: Inner, + _ validator: @escaping (Value) -> ValidatorOutput + ) where Inner.Value == Value { + getter = { inner.value } + producer = inner.producer + signal = inner.signal + lifetime = inner.lifetime + + // This flag temporarily suspends the monitoring on the inner property for + // writebacks that are triggered by successful validations. + var isSettingInnerValue = false + + (result, setter) = inner.withValue { initial in + let mutableResult = MutableProperty(ValidationResult(initial, validator(initial))) + + mutableResult <~ inner.signal + .filter { _ in !isSettingInnerValue } + .map { ValidationResult($0, validator($0)) } + + return (Property(capturing: mutableResult), { input in + // Acquire the lock of `inner` to ensure no modification happens until + // the validation logic here completes. + inner.withValue { _ in + let writebackValue: Value? = mutableResult.modify { result in + result = ValidationResult(input, validator(input)) + return result.value + } + + if let value = writebackValue { + isSettingInnerValue = true + inner.value = value + isSettingInnerValue = false + } + } + }) + } + } + + /// Create a `ValidatingProperty` that validates mutations before + /// committing them. + /// + /// The proposed value is only committed when `valid` is returned by the + /// `validator` closure. + /// + /// - parameters: + /// - initial: The initial value of the property. It is not required to + /// pass the validation as specified by `validator`. + /// - validator: The closure to invoke for any proposed value to `self`. + public convenience init( + _ initial: Value, + _ validator: @escaping (Value) -> ValidatorOutput + ) { + self.init(MutableProperty(initial), validator) + } + + /// Create a `ValidatingProperty` that presents a mutable validating + /// view for an inner mutable property. + /// + /// The proposed value is only committed when `valid` is returned by the + /// `validator` closure. + /// + /// - note: `inner` is retained by the created property. + /// + /// - parameters: + /// - inner: The inner property which validated values are committed to. + /// - other: The property that `validator` depends on. + /// - validator: The closure to invoke for any proposed value to `self`. + public convenience init( + _ inner: MutableProperty, + with other: Other, + _ validator: @escaping (Value, Other.Value) -> ValidatorOutput + ) { + // Capture a copy that reflects `other` without influencing the lifetime of + // `other`. + let other = Property(other) + + self.init(inner) { input in + return validator(input, other.value) + } + + // When `other` pushes out a new value, the resulting property would react + // by revalidating itself with its last attempted value, regardless of + // success or failure. + other.signal + .take(during: lifetime) + .observeValues { [weak self] _ in + guard let s = self else { return } + + switch s.result.value { + case let .invalid(value, _): + s.value = value + + case let .coerced(_, value, _): + s.value = value + + case let .valid(value): + s.value = value + } + } + } + + /// Create a `ValidatingProperty` that validates mutations before + /// committing them. + /// + /// The proposed value is only committed when `valid` is returned by the + /// `validator` closure. + /// + /// - parameters: + /// - initial: The initial value of the property. It is not required to + /// pass the validation as specified by `validator`. + /// - other: The property that `validator` depends on. + /// - validator: The closure to invoke for any proposed value to `self`. + public convenience init( + _ initial: Value, + with other: Other, + _ validator: @escaping (Value, Other.Value) -> ValidatorOutput + ) { + self.init(MutableProperty(initial), with: other, validator) + } + + /// Create a `ValidatingProperty` that presents a mutable validating + /// view for an inner mutable property. + /// + /// The proposed value is only committed when `valid` is returned by the + /// `validator` closure. + /// + /// - note: `inner` is retained by the created property. + /// + /// - parameters: + /// - inner: The inner property which validated values are committed to. + /// - other: The property that `validator` depends on. + /// - validator: The closure to invoke for any proposed value to `self`. + public convenience init( + _ inner: MutableProperty, + with other: ValidatingProperty, + _ validator: @escaping (Value, U) -> ValidatorOutput + ) { + self.init(inner, with: other, validator) + } + + /// Create a `ValidatingProperty` that validates mutations before + /// committing them. + /// + /// The proposed value is only committed when `valid` is returned by the + /// `validator` closure. + /// + /// - parameters: + /// - initial: The initial value of the property. It is not required to + /// pass the validation as specified by `validator`. + /// - other: The property that `validator` depends on. + /// - validator: The closure to invoke for any proposed value to `self`. + public convenience init( + _ initial: Value, + with other: ValidatingProperty, + _ validator: @escaping (Value, U) -> ValidatorOutput + ) { + // Capture only `other.result` but not `other`. + let otherValidations = other.result + + self.init(initial) { input in + let otherValue: U + + switch otherValidations.value { + case let .valid(value): + otherValue = value + + case let .coerced(_, value, _): + otherValue = value + + case let .invalid(value, _): + otherValue = value + } + + return validator(input, otherValue) + } + + // When `other` pushes out a new validation result, the resulting property + // would react by revalidating itself with its last attempted value, + // regardless of success or failure. + otherValidations.signal + .take(during: lifetime) + .observeValues { [weak self] _ in + guard let s = self else { return } + + switch s.result.value { + case let .invalid(value, _): + s.value = value + + case let .coerced(_, value, _): + s.value = value + + case let .valid(value): + s.value = value + } + } + } +} + +/// Represents a decision of a validator of a validating property made on a +/// proposed value. +public enum ValidatorOutput { + /// The proposed value is valid. + case valid + + /// The proposed value is invalid, but the validator coerces it into a + /// replacement which it deems valid. + case coerced(Value, Error?) + + /// The proposed value is invalid. + case invalid(Error) +} + +/// Represents the result of the validation performed by a validating property. +public enum ValidationResult { + /// The proposed value is valid. + case valid(Value) + + /// The proposed value is invalid, but the validator was able to coerce it + /// into a replacement which it deemed valid. + case coerced(replacement: Value, proposed: Value, error: Error?) + + /// The proposed value is invalid. + case invalid(Value, Error) + + /// Whether the value is invalid. + public var isInvalid: Bool { + if case .invalid = self { + return true + } else { + return false + } + } + + /// Extract the valid value, or `nil` if the value is invalid. + public var value: Value? { + switch self { + case let .valid(value): + return value + case let .coerced(value, _, _): + return value + case .invalid: + return nil + } + } + + /// Extract the error if the value is invalid. + public var error: Error? { + if case let .invalid(_, error) = self { + return error + } else { + return nil + } + } + + fileprivate init(_ value: Value, _ output: ValidatorOutput) { + switch output { + case .valid: + self = .valid(value) + + case let .coerced(replacement, error): + self = .coerced(replacement: replacement, proposed: value, error: error) + + case let .invalid(error): + self = .invalid(value, error) + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/LinuxMain.swift b/Carthage/Checkouts/ReactiveSwift/Tests/LinuxMain.swift new file mode 100644 index 0000000..3c79b7b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/LinuxMain.swift @@ -0,0 +1,21 @@ +import XCTest +import Quick + +@testable import ReactiveSwiftTests + +Quick.QCKMain([ + ActionSpec.self, + AtomicSpec.self, + BagSpec.self, + DisposableSpec.self, + DeprecationSpec.self, + FlattenSpec.self, + FoundationExtensionsSpec.self, + LifetimeSpec.self, + PropertySpec.self, + SchedulerSpec.self, + SignalLifetimeSpec.self, + SignalProducerLiftingSpec.self, + SignalProducerSpec.self, + SignalSpec.self, +]) diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ActionSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ActionSpec.swift new file mode 100755 index 0000000..a04dccc --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ActionSpec.swift @@ -0,0 +1,336 @@ +// +// ActionSpec.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-12-11. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +import Foundation +import Dispatch +import Result +import Nimble +import Quick +import ReactiveSwift + +class ActionSpec: QuickSpec { + override func spec() { + describe("Action") { + var action: Action! + var enabled: MutableProperty! + + var executionCount = 0 + var completedCount = 0 + var values: [String] = [] + var errors: [NSError] = [] + + var scheduler: TestScheduler! + let testError = NSError(domain: "ActionSpec", code: 1, userInfo: nil) + + beforeEach { + executionCount = 0 + completedCount = 0 + values = [] + errors = [] + enabled = MutableProperty(false) + + scheduler = TestScheduler() + action = Action(enabledIf: enabled) { number in + return SignalProducer { observer, disposable in + executionCount += 1 + + if number % 2 == 0 { + observer.send(value: "\(number)") + observer.send(value: "\(number)\(number)") + + disposable += scheduler.schedule { + observer.sendCompleted() + } + } else { + disposable += scheduler.schedule { + observer.send(error: testError) + } + } + } + } + + action.values.observeValues { values.append($0) } + action.errors.observeValues { errors.append($0) } + action.completed.observeValues { _ in completedCount += 1 } + } + + it("should retain the state property") { + var property: MutableProperty? = MutableProperty(false) + weak var weakProperty = property + + var action: Action<(), (), NoError>? = Action(state: property!, enabledIf: { _ in true }) { _, _ in + return .empty + } + + expect(weakProperty).toNot(beNil()) + + property = nil + expect(weakProperty).toNot(beNil()) + + action = nil + expect(weakProperty).to(beNil()) + + // Mute "unused variable" warning. + _ = action + } + + it("should be disabled and not executing after initialization") { + expect(action.isEnabled.value) == false + expect(action.isExecuting.value) == false + } + + it("should error if executed while disabled") { + var receivedError: ActionError? + var disabledErrorsTriggered = false + + action.disabledErrors.observeValues { _ in + disabledErrorsTriggered = true + } + + action.apply(0).startWithFailed { + receivedError = $0 + } + + expect(receivedError).notTo(beNil()) + expect(disabledErrorsTriggered) == true + if let error = receivedError { + let expectedError = ActionError.disabled + expect(error == expectedError) == true + } + } + + it("should enable and disable based on the given property") { + enabled.value = true + expect(action.isEnabled.value) == true + expect(action.isExecuting.value) == false + + enabled.value = false + expect(action.isEnabled.value) == false + expect(action.isExecuting.value) == false + } + + it("should not deadlock when its executing state affects its state property without constituting a feedback loop") { + enabled <~ action.isExecuting.negate() + expect(enabled.value) == true + expect(action.isEnabled.value) == true + expect(action.isExecuting.value) == false + + let disposable = action.apply(0).start() + expect(enabled.value) == false + expect(action.isEnabled.value) == false + expect(action.isExecuting.value) == true + + disposable.dispose() + expect(enabled.value) == true + expect(action.isEnabled.value) == true + expect(action.isExecuting.value) == false + } + + it("should not deadlock") { + final class ViewModel { + let action2 = Action<(), (), NoError> { _ in SignalProducer(value: ()) } + } + + let action1 = Action<(), ViewModel, NoError> { _ in SignalProducer(value: ViewModel()) } + + // Fixed in #267. (https://github.com/ReactiveCocoa/ReactiveSwift/pull/267) + // + // The deadlock happened as the observer disposable releases the closure + // `{ _ in viewModel }` here without releasing the mapped signal's + // `updateLock` first. The deinitialization of the closure triggered the + // propagation of terminal event of the `Action`, which eventually hit + // the mapped signal and attempted to acquire `updateLock` to transition + // the signal's state. + action1.values + .flatMap(.latest) { viewModel in viewModel.action2.values.map { _ in viewModel } } + .observeValues { _ in } + + action1.apply().start() + action1.apply().start() + } + + if #available(macOS 10.10, *) { + it("should not loop indefinitely") { + let condition = MutableProperty(1) + + let action = Action(state: condition, enabledIf: { $0 == 0 }) { _, _ in + return .empty + } + + var count = 0 + + action.isExecuting.producer + .startWithValues { _ in + condition.value = 10 + + count += 1 + expect(count) == 1 + } + } + } + + describe("completed") { + beforeEach { + enabled.value = true + } + + it("should send a value whenever the producer completes") { + action.apply(0).start() + expect(completedCount) == 0 + + scheduler.run() + expect(completedCount) == 1 + + action.apply(2).start() + scheduler.run() + expect(completedCount) == 2 + } + + it("should not send a value when the producer fails") { + action.apply(1).start() + scheduler.run() + expect(completedCount) == 0 + } + + it("should not send a value when the producer is interrupted") { + let disposable = action.apply(0).start() + disposable.dispose() + scheduler.run() + expect(completedCount) == 0 + } + + it("should not send a value when the action is disabled") { + enabled.value = false + action.apply(0).start() + scheduler.run() + expect(completedCount) == 0 + } + } + + describe("execution") { + beforeEach { + enabled.value = true + } + + it("should execute successfully") { + var receivedValue: String? + + action.apply(0) + .assumeNoErrors() + .startWithValues { + receivedValue = $0 + } + + expect(executionCount) == 1 + expect(action.isExecuting.value) == true + expect(action.isEnabled.value) == false + + expect(receivedValue) == "00" + expect(values) == [ "0", "00" ] + expect(errors) == [] + + scheduler.run() + expect(action.isExecuting.value) == false + expect(action.isEnabled.value) == true + + expect(values) == [ "0", "00" ] + expect(errors) == [] + } + + it("should execute with an error") { + var receivedError: ActionError? + + action.apply(1).startWithFailed { + receivedError = $0 + } + + expect(executionCount) == 1 + expect(action.isExecuting.value) == true + expect(action.isEnabled.value) == false + + scheduler.run() + expect(action.isExecuting.value) == false + expect(action.isEnabled.value) == true + + expect(receivedError).notTo(beNil()) + if let error = receivedError { + let expectedError = ActionError.producerFailed(testError) + expect(error == expectedError) == true + } + + expect(values) == [] + expect(errors) == [ testError ] + } + } + + describe("bindings") { + it("should execute successfully") { + var receivedValue: String? + let (signal, observer) = Signal.pipe() + + action.values.observeValues { receivedValue = $0 } + + action <~ signal + + enabled.value = true + + expect(executionCount) == 0 + expect(action.isExecuting.value) == false + expect(action.isEnabled.value) == true + + observer.send(value: 0) + + expect(executionCount) == 1 + expect(action.isExecuting.value) == true + expect(action.isEnabled.value) == false + + expect(receivedValue) == "00" + expect(values) == [ "0", "00" ] + expect(errors) == [] + + scheduler.run() + expect(action.isExecuting.value) == false + expect(action.isEnabled.value) == true + + expect(values) == [ "0", "00" ] + expect(errors) == [] + } + } + } + + describe("using a property as input") { + let echo: (Int) -> SignalProducer = SignalProducer.init(value:) + + it("executes the action with the property's current value") { + let input = MutableProperty(0) + let action = Action(state: input, execute: echo) + + var values: [Int] = [] + action.values.observeValues { values.append($0) } + + input.value = 1 + action.apply().start() + input.value = 2 + action.apply().start() + input.value = 3 + action.apply().start() + + expect(values) == [1, 2, 3] + } + + it("is disabled if the property is nil") { + let input = MutableProperty(1) + let action = Action(state: input, execute: echo) + + expect(action.isEnabled.value) == true + input.value = nil + expect(action.isEnabled.value) == false + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/AtomicSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/AtomicSpec.swift new file mode 100644 index 0000000..8234f5b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/AtomicSpec.swift @@ -0,0 +1,44 @@ +// +// AtomicSpec.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-07-13. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +import Nimble +import Quick +import ReactiveSwift + +class AtomicSpec: QuickSpec { + override func spec() { + var atomic: Atomic! + + beforeEach { + atomic = Atomic(1) + } + + it("should read and write the value directly") { + expect(atomic.value) == 1 + + atomic.value = 2 + expect(atomic.value) == 2 + } + + it("should swap the value atomically") { + expect(atomic.swap(2)) == 1 + expect(atomic.value) == 2 + } + + it("should modify the value atomically") { + atomic.modify { $0 += 1 } + expect(atomic.value) == 2 + } + + it("should perform an action with the value") { + let result: Bool = atomic.withValue { $0 == 1 } + expect(result) == true + expect(atomic.value) == 1 + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/BagSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/BagSpec.swift new file mode 100644 index 0000000..706e781 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/BagSpec.swift @@ -0,0 +1,54 @@ +// +// BagSpec.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-07-13. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +import Nimble +import Quick +import ReactiveSwift + +class BagSpec: QuickSpec { + override func spec() { + var bag = Bag() + + beforeEach { + bag = Bag() + } + + it("should insert values") { + bag.insert("foo") + bag.insert("bar") + bag.insert("buzz") + + expect(bag).to(contain("foo")) + expect(bag).to(contain("bar")) + expect(bag).to(contain("buzz")) + expect(bag).toNot(contain("fuzz")) + expect(bag).toNot(contain("foobar")) + } + + it("should remove values given the token from insertion") { + let a = bag.insert("foo") + let b = bag.insert("bar") + let c = bag.insert("buzz") + + bag.remove(using: b) + expect(bag).to(contain("foo")) + expect(bag).toNot(contain("bar")) + expect(bag).to(contain("buzz")) + + bag.remove(using: a) + expect(bag).toNot(contain("foo")) + expect(bag).toNot(contain("bar")) + expect(bag).to(contain("buzz")) + + bag.remove(using: c) + expect(bag).toNot(contain("foo")) + expect(bag).toNot(contain("bar")) + expect(bag).toNot(contain("buzz")) + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/DeprecationSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/DeprecationSpec.swift new file mode 100644 index 0000000..b4ae17d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/DeprecationSpec.swift @@ -0,0 +1,8 @@ +import Quick +import Nimble +import ReactiveSwift +import Result + +class DeprecationSpec: QuickSpec { + override func spec() {} +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/DisposableSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/DisposableSpec.swift new file mode 100644 index 0000000..f225cb9 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/DisposableSpec.swift @@ -0,0 +1,149 @@ +// +// DisposableSpec.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-07-13. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +import Nimble +import Quick +import ReactiveSwift + +class DisposableSpec: QuickSpec { + override func spec() { + describe("SimpleDisposable") { + it("should set disposed to true") { + let disposable = AnyDisposable() + expect(disposable.isDisposed) == false + + disposable.dispose() + expect(disposable.isDisposed) == true + } + } + + describe("ActionDisposable") { + it("should run the given action upon disposal") { + var didDispose = false + let disposable = AnyDisposable { + didDispose = true + } + + expect(didDispose) == false + expect(disposable.isDisposed) == false + + disposable.dispose() + expect(didDispose) == true + expect(disposable.isDisposed) == true + } + } + + describe("CompositeDisposable") { + var disposable = CompositeDisposable() + + beforeEach { + disposable = CompositeDisposable() + } + + it("should ignore the addition of nil") { + disposable.add(nil) + return + } + + it("should dispose of added disposables") { + let simpleDisposable = AnyDisposable() + disposable += simpleDisposable + + var didDispose = false + disposable += { + didDispose = true + } + + expect(simpleDisposable.isDisposed) == false + expect(didDispose) == false + expect(disposable.isDisposed) == false + + disposable.dispose() + expect(simpleDisposable.isDisposed) == true + expect(didDispose) == true + expect(disposable.isDisposed) == true + } + + it("should not dispose of removed disposables") { + let simpleDisposable = AnyDisposable() + let handle = disposable += simpleDisposable + + // We should be allowed to call this any number of times. + handle?.dispose() + handle?.dispose() + expect(simpleDisposable.isDisposed) == false + + disposable.dispose() + expect(simpleDisposable.isDisposed) == false + } + } + + describe("ScopedDisposable") { + it("should be initialized with an instance of `Disposable` protocol type") { + let d: Disposable = AnyDisposable() + let scoped = ScopedDisposable(d) + expect(type(of: scoped) == ScopedDisposable.self) == true + } + + it("should dispose of the inner disposable upon deinitialization") { + let simpleDisposable = AnyDisposable() + + func runScoped() { + let scopedDisposable = ScopedDisposable(simpleDisposable) + expect(simpleDisposable.isDisposed) == false + expect(scopedDisposable.isDisposed) == false + } + + expect(simpleDisposable.isDisposed) == false + + runScoped() + expect(simpleDisposable.isDisposed) == true + } + } + + describe("SerialDisposable") { + var disposable: SerialDisposable! + + beforeEach { + disposable = SerialDisposable() + } + + it("should dispose of the inner disposable") { + let simpleDisposable = AnyDisposable() + disposable.inner = simpleDisposable + + expect(disposable.inner).notTo(beNil()) + expect(simpleDisposable.isDisposed) == false + expect(disposable.isDisposed) == false + + disposable.dispose() + expect(disposable.inner).to(beNil()) + expect(simpleDisposable.isDisposed) == true + expect(disposable.isDisposed) == true + } + + it("should dispose of the previous disposable when swapping innerDisposable") { + let oldDisposable = AnyDisposable() + let newDisposable = AnyDisposable() + + disposable.inner = oldDisposable + expect(oldDisposable.isDisposed) == false + expect(newDisposable.isDisposed) == false + + disposable.inner = newDisposable + expect(oldDisposable.isDisposed) == true + expect(newDisposable.isDisposed) == false + expect(disposable.isDisposed) == false + + disposable.inner = nil + expect(newDisposable.isDisposed) == true + expect(disposable.isDisposed) == false + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/FlattenSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/FlattenSpec.swift new file mode 100644 index 0000000..ab92fa3 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/FlattenSpec.swift @@ -0,0 +1,1065 @@ +// +// FlattenSpec.swift +// ReactiveSwift +// +// Created by Oleg Shnitko on 1/22/16. +// Copyright © 2016 GitHub. All rights reserved. +// + +import Result +import Nimble +import Quick +import ReactiveSwift +import Dispatch + +private extension Signal { + typealias Pipe = (output: Signal, input: Signal.Observer) +} + +private typealias Pipe = Signal, TestError>.Pipe + +class FlattenSpec: QuickSpec { + override func spec() { + func describeSignalFlattenDisposal(_ flattenStrategy: FlattenStrategy, name: String) { + describe(name) { + var pipe: Pipe! + var disposable: Disposable? + + beforeEach { + pipe = Signal.pipe() + disposable = pipe.output + .flatten(flattenStrategy) + .observe { _ in } + } + + afterEach { + disposable?.dispose() + } + + context("disposal") { + var disposed = false + + beforeEach { + disposed = false + pipe.input.send(value: SignalProducer { _, lifetime in + lifetime.observeEnded { disposed = true } + }) + } + + it("should dispose inner signals when outer signal interrupted") { + pipe.input.sendInterrupted() + expect(disposed) == true + } + + it("should dispose inner signals when outer signal failed") { + pipe.input.send(error: .default) + expect(disposed) == true + } + + it("should not dispose inner signals when outer signal completed") { + pipe.input.sendCompleted() + expect(disposed) == false + } + } + } + } + + context("Signal") { + describeSignalFlattenDisposal(.latest, name: "switchToLatest") + describeSignalFlattenDisposal(.merge, name: "merge") + describeSignalFlattenDisposal(.concat, name: "concat") + describeSignalFlattenDisposal(.concurrent(limit: 1024), name: "concurrent(limit: 1024)") + describeSignalFlattenDisposal(.race, name: "race") + } + + func describeSignalProducerFlattenDisposal(_ flattenStrategy: FlattenStrategy, name: String) { + describe(name) { + it("disposes original signal when result signal interrupted") { + var disposed = false + + let disposable = SignalProducer, NoError> { _, lifetime in + lifetime.observeEnded { disposed = true } + } + .flatten(flattenStrategy) + .start() + + disposable.dispose() + expect(disposed) == true + } + } + } + + context("SignalProducer") { + describeSignalProducerFlattenDisposal(.latest, name: "switchToLatest") + describeSignalProducerFlattenDisposal(.merge, name: "merge") + describeSignalProducerFlattenDisposal(.concat, name: "concat") + describeSignalProducerFlattenDisposal(.concurrent(limit: 1024), name: "concurrent(limit: 1024)") + describeSignalProducerFlattenDisposal(.race, name: "race") + } + + describe("Signal.flatten()") { + it("works with TestError and a TestError Signal") { + typealias Inner = Signal + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a TestError Signal") { + typealias Inner = Signal + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a NoError Signal") { + typealias Inner = Signal + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .observeValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a NoError Signal") { + typealias Inner = Signal + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a TestError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a TestError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a NoError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .observeValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a NoError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with Sequence as a value") { + let (signal, innerObserver) = Signal<[Int], NoError>.pipe() + let sequence = [1, 2, 3] + var observedValues = [Int]() + + signal + .flatten() + .observeValues { value in + observedValues.append(value) + } + + innerObserver.send(value: sequence) + expect(observedValues) == sequence + } + + it("works with Sequence as a value and any arbitrary error") { + _ = Signal<[Int], TestError>.empty + .flatten() + } + + it("works with Property and any arbitrary error") { + _ = Signal, TestError>.empty + .flatten(.latest) + } + + it("works with Property and NoError") { + _ = Signal, NoError>.empty + .flatten(.latest) + } + } + + describe("SignalProducer.flatten()") { + it("works with TestError and a TestError Signal") { + typealias Inner = Signal + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a TestError Signal") { + typealias Inner = Signal + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a NoError Signal") { + typealias Inner = Signal + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .startWithValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a NoError Signal") { + typealias Inner = Signal + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a TestError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a TestError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a NoError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .startWithValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a NoError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatten(.latest) + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: inner) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with Sequence as a value") { + let sequence = [1, 2, 3] + var observedValues = [Int]() + + let producer = SignalProducer<[Int], NoError>(value: sequence) + producer + .flatten() + .startWithValues { value in + observedValues.append(value) + } + + expect(observedValues) == sequence + } + + it("works with Sequence as a value and any arbitrary error") { + _ = SignalProducer<[Int], TestError>.empty + .flatten() + } + + it("works with Property and any arbitrary error") { + _ = SignalProducer, TestError>.empty + .flatten(.latest) + } + + it("works with Property and NoError") { + _ = SignalProducer, NoError>.empty + .flatten(.latest) + } + } + + describe("Signal.flatMap()") { + it("works with TestError and a TestError Signal") { + typealias Inner = Signal + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a TestError Signal") { + typealias Inner = Signal + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a NoError Signal") { + typealias Inner = Signal + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .observeValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a NoError Signal") { + typealias Inner = Signal + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a TestError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a TestError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a NoError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .observeValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a NoError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = Signal + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .observeValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with Property and any arbitrary error") { + _ = Signal.empty + .flatMap(.latest) { _ in Property(value: 0) } + } + + it("works with Property and NoError") { + _ = Signal.empty + .flatMap(.latest) { _ in Property(value: 0) } + } + } + + describe("SignalProducer.flatMap()") { + it("works with TestError and a TestError Signal") { + typealias Inner = Signal + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a TestError Signal") { + typealias Inner = Signal + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a NoError Signal") { + typealias Inner = Signal + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .startWithValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a NoError Signal") { + typealias Inner = Signal + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a TestError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a TestError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with NoError and a NoError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .startWithValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with TestError and a NoError SignalProducer") { + typealias Inner = SignalProducer + typealias Outer = SignalProducer + + let (inner, innerObserver) = Inner.pipe() + let (outer, outerObserver) = Outer.pipe() + + var observed: Int? = nil + outer + .flatMap(.latest) { _ in inner } + .assumeNoErrors() + .startWithValues { value in + observed = value + } + + outerObserver.send(value: 4) + innerObserver.send(value: 4) + expect(observed) == 4 + } + + it("works with Property and any arbitrary error") { + _ = SignalProducer.empty + .flatMap(.latest) { _ in Property(value: 0) } + } + + it("works with Property and NoError") { + _ = SignalProducer.empty + .flatMap(.latest) { _ in Property(value: 0) } + } + } + + describe("Signal.merge()") { + it("should emit values from all signals") { + let (signal1, observer1) = Signal.pipe() + let (signal2, observer2) = Signal.pipe() + + let mergedSignals = Signal.merge([signal1, signal2]) + + var lastValue: Int? + mergedSignals.observeValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer1.send(value: 1) + expect(lastValue) == 1 + + observer2.send(value: 2) + expect(lastValue) == 2 + + observer1.send(value: 3) + expect(lastValue) == 3 + } + + it("should not stop when one signal completes") { + let (signal1, observer1) = Signal.pipe() + let (signal2, observer2) = Signal.pipe() + + let mergedSignals = Signal.merge([signal1, signal2]) + + var lastValue: Int? + mergedSignals.observeValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer1.send(value: 1) + expect(lastValue) == 1 + + observer1.sendCompleted() + expect(lastValue) == 1 + + observer2.send(value: 2) + expect(lastValue) == 2 + } + + it("should complete when all signals complete") { + let (signal1, observer1) = Signal.pipe() + let (signal2, observer2) = Signal.pipe() + + let mergedSignals = Signal.merge([signal1, signal2]) + + var completed = false + mergedSignals.observeCompleted { completed = true } + + expect(completed) == false + + observer1.send(value: 1) + expect(completed) == false + + observer1.sendCompleted() + expect(completed) == false + + observer2.sendCompleted() + expect(completed) == true + } + } + + describe("SignalProducer.merge()") { + it("should emit values from all producers") { + let (signal1, observer1) = SignalProducer.pipe() + let (signal2, observer2) = SignalProducer.pipe() + + let mergedSignals = SignalProducer.merge([signal1, signal2]) + + var lastValue: Int? + mergedSignals.startWithValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer1.send(value: 1) + expect(lastValue) == 1 + + observer2.send(value: 2) + expect(lastValue) == 2 + + observer1.send(value: 3) + expect(lastValue) == 3 + } + + it("should not stop when one producer completes") { + let (signal1, observer1) = SignalProducer.pipe() + let (signal2, observer2) = SignalProducer.pipe() + + let mergedSignals = SignalProducer.merge([signal1, signal2]) + + var lastValue: Int? + mergedSignals.startWithValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer1.send(value: 1) + expect(lastValue) == 1 + + observer1.sendCompleted() + expect(lastValue) == 1 + + observer2.send(value: 2) + expect(lastValue) == 2 + } + + it("should complete when all producers complete") { + let (signal1, observer1) = SignalProducer.pipe() + let (signal2, observer2) = SignalProducer.pipe() + + let mergedSignals = SignalProducer.merge([signal1, signal2]) + + var completed = false + mergedSignals.startWithCompleted { completed = true } + + expect(completed) == false + + observer1.send(value: 1) + expect(completed) == false + + observer1.sendCompleted() + expect(completed) == false + + observer2.sendCompleted() + expect(completed) == true + } + } + + describe("SignalProducer.prefix()") { + it("should emit initial value") { + let (signal, observer) = SignalProducer.pipe() + + let mergedSignals = signal.prefix(value: 0) + + var lastValue: Int? + mergedSignals.startWithValues { lastValue = $0 } + + expect(lastValue) == 0 + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + + observer.send(value: 3) + expect(lastValue) == 3 + } + + it("should emit initial value") { + let (signal, observer) = SignalProducer.pipe() + + let mergedSignals = signal.prefix(SignalProducer(value: 0)) + + var lastValue: Int? + mergedSignals.startWithValues { lastValue = $0 } + + expect(lastValue) == 0 + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + + observer.send(value: 3) + expect(lastValue) == 3 + } + } + + describe("SignalProducer.concat(value:)") { + it("should emit final value") { + let (signal, observer) = SignalProducer.pipe() + + let mergedSignals = signal.concat(value: 4) + + var lastValue: Int? + mergedSignals.startWithValues { lastValue = $0 } + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + + observer.send(value: 3) + expect(lastValue) == 3 + + observer.sendCompleted() + expect(lastValue) == 4 + } + } + + describe("FlattenStrategy.concurrent") { + func run(_ modifier: (SignalProducer) -> SignalProducer) { + let concurrentLimit: UInt = 4 + let extra: UInt = 100 + + let (outer, outerObserver) = Signal, NoError>.pipe() + + var values: [UInt] = [] + outer.flatten(.concurrent(limit: concurrentLimit)).observeValues { values.append($0) } + + var started: [UInt] = [] + var observers: [Signal.Observer] = [] + + for i in 0 ..< (concurrentLimit + extra) { + let (signal, observer) = Signal.pipe() + observers.append(observer) + + let producer = modifier(SignalProducer(signal).prefix(value: i).on(started: { started.append(i) })) + outerObserver.send(value: producer) + } + + // The producers may be started asynchronously. So these + // expectations have to be asynchronous too. + expect(values).toEventually(equal(Array(0 ..< concurrentLimit))) + expect(started).toEventually(equal(Array(0 ..< concurrentLimit))) + + for i in 0 ..< extra { + observers[Int(i)].sendCompleted() + + expect(values).toEventually(equal(Array(0 ... (concurrentLimit + i)))) + expect(started).toEventually(equal(Array(0 ... (concurrentLimit + i)))) + } + } + + it("should synchronously merge up to the stated limit, buffer any subsequent producers and dequeue them in the submission order") { + run { $0 } + } + + it("should asynchronously merge up to the stated limit, buffer any subsequent producers and dequeue them in the submission order") { + let scheduler: QueueScheduler + + if #available(macOS 10.10, *) { + scheduler = QueueScheduler() + } else { + scheduler = QueueScheduler(queue: DispatchQueue.global(priority: .default)) + } + + run { $0.start(on: scheduler) } + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/FoundationExtensionsSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/FoundationExtensionsSpec.swift new file mode 100644 index 0000000..199364a --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/FoundationExtensionsSpec.swift @@ -0,0 +1,116 @@ +// +// FoundationExtensionsSpec.swift +// ReactiveSwift +// +// Created by Neil Pankey on 5/22/15. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +import Foundation +import Dispatch +import Result +import Nimble +import Quick +@testable import ReactiveSwift + +extension Notification.Name { + static let racFirst = Notification.Name(rawValue: "rac_notifications_test") + static let racAnother = Notification.Name(rawValue: "rac_notifications_another") +} + +class FoundationExtensionsSpec: QuickSpec { + override func spec() { + describe("NotificationCenter.reactive.notifications") { + let center = NotificationCenter.default + + it("should send notifications on the signal") { + let signal = center.reactive.notifications(forName: .racFirst) + + var notif: Notification? = nil + let disposable = signal.observeValues { notif = $0 } + + center.post(name: .racAnother, object: nil) + expect(notif).to(beNil()) + + center.post(name: .racFirst, object: nil) + expect(notif?.name) == .racFirst + + notif = nil + disposable?.dispose() + + center.post(name: .racFirst, object: nil) + expect(notif).to(beNil()) + } + + it("should be disposed of if it is not reachable and no observer is attached") { + weak var signal: Signal? + var isDisposed = false + + let disposable: Disposable? = { + let innerSignal = center.reactive.notifications(forName: nil) + .on(disposed: { isDisposed = true }) + + signal = innerSignal + return innerSignal.observe { _ in } + }() + + expect(isDisposed) == false + expect(signal).to(beNil()) + + disposable?.dispose() + + expect(isDisposed) == true + expect(signal).to(beNil()) + } + + it("should be not disposed of if it still has one or more active observers") { + weak var signal: Signal? + var isDisposed = false + + let disposable: Disposable? = { + let innerSignal = center.reactive.notifications(forName: nil) + .on(disposed: { isDisposed = true }) + + signal = innerSignal + innerSignal.observe { _ in } + return innerSignal.observe { _ in } + }() + + expect(isDisposed) == false + expect(signal).to(beNil()) + + disposable?.dispose() + + expect(isDisposed) == false + expect(signal).to(beNil()) + } + } + + describe("DispatchTimeInterval") { + it("should scale time values as expected") { + expect((DispatchTimeInterval.seconds(1) * 0.1).timeInterval).to(beCloseTo(DispatchTimeInterval.milliseconds(100).timeInterval)) + expect((DispatchTimeInterval.milliseconds(100) * 0.1).timeInterval).to(beCloseTo(DispatchTimeInterval.microseconds(10000).timeInterval)) + + expect((DispatchTimeInterval.seconds(5) * 0.5).timeInterval).to(beCloseTo(DispatchTimeInterval.milliseconds(2500).timeInterval)) + expect((DispatchTimeInterval.seconds(1) * 0.25).timeInterval).to(beCloseTo(DispatchTimeInterval.milliseconds(250).timeInterval)) + } + + it("should produce the expected TimeInterval values") { + expect(DispatchTimeInterval.seconds(1).timeInterval).to(beCloseTo(1.0)) + expect(DispatchTimeInterval.milliseconds(1).timeInterval).to(beCloseTo(0.001)) + expect(DispatchTimeInterval.microseconds(1).timeInterval).to(beCloseTo(0.000001, within: 0.0000001)) + expect(DispatchTimeInterval.nanoseconds(1).timeInterval).to(beCloseTo(0.000000001, within: 0.0000000001)) + + expect(DispatchTimeInterval.milliseconds(500).timeInterval).to(beCloseTo(0.5)) + expect(DispatchTimeInterval.milliseconds(250).timeInterval).to(beCloseTo(0.25)) + } + + it("should negate as you'd hope") { + expect(-DispatchTimeInterval.seconds(1).timeInterval).to(beCloseTo(-1.0)) + expect(-DispatchTimeInterval.milliseconds(1).timeInterval).to(beCloseTo(-0.001)) + expect(-DispatchTimeInterval.microseconds(1).timeInterval).to(beCloseTo(-0.000001, within: 0.0000001)) + expect(-DispatchTimeInterval.nanoseconds(1).timeInterval).to(beCloseTo(-0.000000001, within: 0.0000000001)) + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/Info.plist b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/Info.plist new file mode 100644 index 0000000..f931463 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 2.0.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/LifetimeSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/LifetimeSpec.swift new file mode 100644 index 0000000..3067149 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/LifetimeSpec.swift @@ -0,0 +1,94 @@ +import Quick +import Nimble +import ReactiveSwift +import Result + +final class LifetimeSpec: QuickSpec { + override func spec() { + describe("Lifetime") { + it("should complete its lifetime ended signal when the it deinitializes") { + let object = MutableReference(TestObject()) + + var isCompleted = false + + object.value!.lifetime.ended.observeCompleted { isCompleted = true } + expect(isCompleted) == false + + object.value = nil + expect(isCompleted) == true + } + + it("should complete its lifetime ended signal even if the lifetime object is being retained") { + let object = MutableReference(TestObject()) + let lifetime = object.value!.lifetime + + var isCompleted = false + + lifetime.ended.observeCompleted { isCompleted = true } + expect(isCompleted) == false + + object.value = nil + expect(isCompleted) == true + } + + it("should provide a convenience factory method") { + let lifetime: Lifetime + var token: Lifetime.Token + + (lifetime, token) = Lifetime.make() + + var isEnded = false + lifetime.observeEnded { isEnded = true } + + token = Lifetime.Token() + _ = token + + expect(isEnded) == true + } + + it("should notify its observers when the underlying token deinitializes") { + let object = MutableReference(TestObject()) + + var isEnded = false + + object.value!.lifetime.observeEnded { isEnded = true } + expect(isEnded) == false + + object.value = nil + expect(isEnded) == true + } + + it("should notify its observers of the deinitialization of the underlying token even if the `Lifetime` object is retained") { + let object = MutableReference(TestObject()) + let lifetime = object.value!.lifetime + + var isEnded = false + + lifetime.observeEnded { isEnded = true } + expect(isEnded) == false + + object.value = nil + expect(isEnded) == true + } + + it("should notify its observers of its deinitialization if it has already ended") { + var isEnded = false + + Lifetime.empty.observeEnded { isEnded = true } + expect(isEnded) == true + } + } + } +} + +internal final class MutableReference { + var value: Value? + init(_ value: Value?) { + self.value = value + } +} + +internal final class TestObject { + private let token = Lifetime.Token() + var lifetime: Lifetime { return Lifetime(token) } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/PropertySpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/PropertySpec.swift new file mode 100644 index 0000000..f9dd756 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/PropertySpec.swift @@ -0,0 +1,1756 @@ +// +// PropertySpec.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2015-01-23. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +import Foundation +import Dispatch +import Result +import Nimble +import Quick +@testable import ReactiveSwift + +private let initialPropertyValue = "InitialValue" +private let subsequentPropertyValue = "SubsequentValue" +private let finalPropertyValue = "FinalValue" + +private let initialOtherPropertyValue = "InitialOtherValue" +private let subsequentOtherPropertyValue = "SubsequentOtherValue" +private let finalOtherPropertyValue = "FinalOtherValue" + +class PropertySpec: QuickSpec { + override func spec() { + describe("MutableProperty") { + it("should have the value given at initialization") { + let mutableProperty = MutableProperty(initialPropertyValue) + + expect(mutableProperty.value) == initialPropertyValue + } + + it("should yield a producer that sends the current value then all changes") { + let mutableProperty = MutableProperty(initialPropertyValue) + var sentValue: String? + + mutableProperty.producer.startWithValues { sentValue = $0 } + + expect(sentValue) == initialPropertyValue + + mutableProperty.value = subsequentPropertyValue + expect(sentValue) == subsequentPropertyValue + + mutableProperty.value = finalPropertyValue + expect(sentValue) == finalPropertyValue + } + + it("should yield a producer that sends the current value then all changes, even if the value actually remains unchanged") { + let mutableProperty = MutableProperty(initialPropertyValue) + var count = 0 + + mutableProperty.producer.startWithValues { _ in count = count + 1 } + + expect(count) == 1 + + mutableProperty.value = initialPropertyValue + expect(count) == 2 + + mutableProperty.value = initialPropertyValue + expect(count) == 3 + } + + it("should yield a signal that emits subsequent changes to the value") { + let mutableProperty = MutableProperty(initialPropertyValue) + var sentValue: String? + + mutableProperty.signal.observeValues { sentValue = $0 } + + expect(sentValue).to(beNil()) + + mutableProperty.value = subsequentPropertyValue + expect(sentValue) == subsequentPropertyValue + + mutableProperty.value = finalPropertyValue + expect(sentValue) == finalPropertyValue + } + + it("should yield a signal that emits subsequent changes to the value, even if the value actually remains unchanged") { + let mutableProperty = MutableProperty(initialPropertyValue) + var count = 0 + + mutableProperty.signal.observeValues { _ in count = count + 1 } + + expect(count) == 0 + + mutableProperty.value = initialPropertyValue + expect(count) == 1 + + mutableProperty.value = initialPropertyValue + expect(count) == 2 + } + + it("should complete its producer when deallocated") { + var mutableProperty: MutableProperty? = MutableProperty(initialPropertyValue) + var producerCompleted = false + + mutableProperty!.producer.startWithCompleted { producerCompleted = true } + + mutableProperty = nil + expect(producerCompleted) == true + } + + it("should complete its signal when deallocated") { + var mutableProperty: MutableProperty? = MutableProperty(initialPropertyValue) + var signalCompleted = false + + mutableProperty!.signal.observeCompleted { signalCompleted = true } + + mutableProperty = nil + expect(signalCompleted) == true + } + + it("should yield a producer which emits the latest value and complete even if the property is deallocated") { + var mutableProperty: MutableProperty? = MutableProperty(initialPropertyValue) + let producer = mutableProperty!.producer + + var producerCompleted = false + var hasUnanticipatedEvent = false + var latestValue = mutableProperty?.value + + mutableProperty!.value = subsequentPropertyValue + mutableProperty = nil + + producer.start { event in + switch event { + case let .value(value): + latestValue = value + case .completed: + producerCompleted = true + case .interrupted, .failed: + hasUnanticipatedEvent = true + } + } + + expect(hasUnanticipatedEvent) == false + expect(producerCompleted) == true + expect(latestValue) == subsequentPropertyValue + } + + it("should modify the value atomically") { + let property = MutableProperty(initialPropertyValue) + + property.modify { $0 = subsequentPropertyValue } + expect(property.value) == subsequentPropertyValue + } + + it("should modify the value atomically and subsquently send out a Value event with the new value") { + let property = MutableProperty(initialPropertyValue) + var value: String? + + property.producer.startWithValues { + value = $0 + } + + expect(value) == initialPropertyValue + + property.modify { $0 = subsequentPropertyValue } + expect(property.value) == subsequentPropertyValue + expect(value) == subsequentPropertyValue + } + + it("should swap the value atomically") { + let property = MutableProperty(initialPropertyValue) + + expect(property.swap(subsequentPropertyValue)) == initialPropertyValue + expect(property.value) == subsequentPropertyValue + } + + it("should swap the value atomically and subsquently send out a Value event with the new value") { + let property = MutableProperty(initialPropertyValue) + var value: String? + + property.producer.startWithValues { + value = $0 + } + + expect(value) == initialPropertyValue + expect(property.swap(subsequentPropertyValue)) == initialPropertyValue + + expect(property.value) == subsequentPropertyValue + expect(value) == subsequentPropertyValue + } + + it("should perform an action with the value") { + let property = MutableProperty(initialPropertyValue) + + let result: Bool = property.withValue { $0.isEmpty } + + expect(result) == false + expect(property.value) == initialPropertyValue + } + + it("should not deadlock on recursive value access") { + let (producer, observer) = SignalProducer.pipe() + let property = MutableProperty(0) + var value: Int? + + property <~ producer + property.producer.startWithValues { _ in + value = property.value + } + + observer.send(value: 10) + expect(value) == 10 + } + + it("should not deadlock on recursive value access with a closure") { + let (producer, observer) = SignalProducer.pipe() + let property = MutableProperty(0) + var value: Int? + + property <~ producer + property.producer.startWithValues { _ in + value = property.withValue { $0 + 1 } + } + + observer.send(value: 10) + expect(value) == 11 + } + + it("should not deadlock on recursive observation") { + let property = MutableProperty(0) + + var value: Int? + property.producer.startWithValues { _ in + property.producer.startWithValues { x in value = x } + } + + expect(value) == 0 + + property.value = 1 + expect(value) == 1 + } + + it("should not deadlock on recursive ABA observation") { + let propertyA = MutableProperty(0) + let propertyB = MutableProperty(0) + + var value: Int? + propertyA.producer.startWithValues { _ in + propertyB.producer.startWithValues { _ in + propertyA.producer.startWithValues { x in value = x } + } + } + + expect(value) == 0 + + propertyA.value = 1 + expect(value) == 1 + } + + it("should expose a lifetime that ends upon its deinitialization") { + var property = Optional(MutableProperty(1)) + + var isEnded = false + property!.lifetime.observeEnded { + isEnded = true + } + + expect(isEnded) == false + + property!.value = 2 + expect(isEnded) == false + + property = nil + expect(isEnded) == true + } + + it("should not deadlock") { + let queue: DispatchQueue + + if #available(macOS 10.10, *) { + queue = DispatchQueue.global(qos: .userInteractive) + } else { + queue = DispatchQueue.global(priority: .high) + } + + let group = DispatchGroup() + + DispatchQueue.concurrentPerform(iterations: 500) { _ in + let source = MutableProperty(1) + var target = Optional(MutableProperty(1)) + + target! <~ source + + queue.async(group: group, flags: .barrier) {} + + queue.async(group: group) { + source.value = 2 + } + + queue.async(group: group) { + target = nil + } + } + + waitUntil { done in + group.notify(queue: queue, execute: done) + } + } + } + + describe("Property") { + describe("constant property") { + it("should have the value given at initialization") { + let constantProperty = Property(value: initialPropertyValue) + + expect(constantProperty.value) == initialPropertyValue + } + + it("should yield a signal that interrupts observers without emitting any value.") { + let constantProperty = Property(value: initialPropertyValue) + + var signalInterrupted = false + var hasUnexpectedEventsEmitted = false + + constantProperty.signal.observe { event in + switch event { + case .interrupted: + signalInterrupted = true + case .value, .failed, .completed: + hasUnexpectedEventsEmitted = true + } + } + + expect(signalInterrupted) == true + expect(hasUnexpectedEventsEmitted) == false + } + + it("should yield a producer that sends the current value then completes") { + let constantProperty = Property(value: initialPropertyValue) + + var sentValue: String? + var signalCompleted = false + var hasUnexpectedEventsEmitted = false + + constantProperty.producer.start { event in + switch event { + case let .value(value): + sentValue = value + case .completed: + signalCompleted = true + case .failed, .interrupted: + hasUnexpectedEventsEmitted = true + } + } + + expect(sentValue) == initialPropertyValue + expect(signalCompleted) == true + expect(hasUnexpectedEventsEmitted) == false + } + } + + describe("existential property") { + describe("Property(capturing:)") { + it("should pass through behaviors of the wrapped property") { + let constantProperty = Property(value: initialPropertyValue) + let property = Property(capturing: constantProperty) + + var sentValue: String? + var signalSentValue: String? + var producerCompleted = false + var signalInterrupted = false + var hasUnexpectedEventsEmitted = false + + property.producer.start { event in + switch event { + case let .value(value): + sentValue = value + case .completed: + producerCompleted = true + case .failed, .interrupted: + hasUnexpectedEventsEmitted = true + } + } + + property.signal.observe { event in + switch event { + case .interrupted: + signalInterrupted = true + case .value, .failed, .completed: + hasUnexpectedEventsEmitted = true + } + } + + expect(sentValue) == initialPropertyValue + expect(signalSentValue).to(beNil()) + expect(producerCompleted) == true + expect(signalInterrupted) == true + expect(hasUnexpectedEventsEmitted) == false + } + + it("should retain the wrapped property") { + var property = Optional(MutableProperty(1)) + weak var weakProperty = property + var existential = Optional(Property(capturing: property!)) + + expect(weakProperty).toNot(beNil()) + + property = nil + expect(weakProperty).toNot(beNil()) + + existential = nil + expect(weakProperty).to(beNil()) + } + } + } + + describe("composed properties") { + describe("Property(_:)") { + it("should pass through behaviors of the wrapped property") { + let constantProperty = Property(value: initialPropertyValue) + let property = Property(constantProperty) + + var sentValue: String? + var signalSentValue: String? + var producerCompleted = false + var signalInterrupted = false + var hasUnexpectedEventsEmitted = false + + property.producer.start { event in + switch event { + case let .value(value): + sentValue = value + case .completed: + producerCompleted = true + case .failed, .interrupted: + hasUnexpectedEventsEmitted = true + } + } + + property.signal.observe { event in + switch event { + case .interrupted: + signalInterrupted = true + case .value, .failed, .completed: + hasUnexpectedEventsEmitted = true + } + } + + expect(sentValue) == initialPropertyValue + expect(signalSentValue).to(beNil()) + expect(producerCompleted) == true + expect(signalInterrupted) == true + expect(hasUnexpectedEventsEmitted) == false + } + + it("should not retain the wrapped property, and remain accessible after its the property being reflected has deinitialized.") { + var property = Optional(MutableProperty(initialPropertyValue)) + weak var weakProperty = property + let reflected = Property(property!) + + expect(weakProperty).toNot(beNil()) + + property!.value = subsequentPropertyValue + expect(reflected.value) == subsequentPropertyValue + + property = nil + expect(weakProperty).to(beNil()) + expect(reflected.value) == subsequentPropertyValue + + var hasUnexpectedEvents = false + var completed = false + var latestValue: String? + + reflected.producer.start { event in + switch event { + case let .value(value): + latestValue = value + + case .completed: + completed = true + + case .interrupted, .failed: + hasUnexpectedEvents = true + } + } + + expect(latestValue) == subsequentPropertyValue + expect(completed) == true + expect(hasUnexpectedEvents) == false + } + } + + describe("from properties") { + it("should have the latest value available before sending any value") { + var latestValue: Int! + + let property = MutableProperty(1) + let mappedProperty = property.map { $0 + 1 } + mappedProperty.producer.startWithValues { _ in latestValue = mappedProperty.value } + + expect(latestValue) == 2 + + property.value = 2 + expect(latestValue) == 3 + + property.value = 3 + expect(latestValue) == 4 + } + + it("should not retain its source property") { + var property = Optional(MutableProperty(1)) + weak var weakProperty = property + + let mapped = Optional(property!.map { $0 + 2 }) + + // Suppress the "written to but never read" warning on `secondMappedProperty`. + _ = mapped + + property = nil + expect(weakProperty).to(beNil()) + } + + it("should transform property from a property that has a terminated producer") { + let property = Property(value: 1) + let transformedProperty = property.map { $0 + 1 } + + expect(transformedProperty.value) == 2 + } + + it("should return a producer and a signal which respect the lifetime of the source property instead of the read-only view itself") { + var signalCompleted = 0 + var producerCompleted = 0 + + var property = Optional(MutableProperty(1)) + var firstMappedProperty = Optional(property!.map { $0 + 1 }) + var secondMappedProperty = Optional(firstMappedProperty!.map { $0 + 2 }) + var thirdMappedProperty = Optional(secondMappedProperty!.map { $0 + 2 }) + + firstMappedProperty!.signal.observeCompleted { signalCompleted += 1 } + secondMappedProperty!.signal.observeCompleted { signalCompleted += 1 } + thirdMappedProperty!.signal.observeCompleted { signalCompleted += 1 } + + firstMappedProperty!.producer.startWithCompleted { producerCompleted += 1 } + secondMappedProperty!.producer.startWithCompleted { producerCompleted += 1 } + thirdMappedProperty!.producer.startWithCompleted { producerCompleted += 1 } + + firstMappedProperty = nil + expect(signalCompleted) == 0 + expect(producerCompleted) == 0 + + secondMappedProperty = nil + expect(signalCompleted) == 0 + expect(producerCompleted) == 0 + + property = nil + expect(signalCompleted) == 3 + expect(producerCompleted) == 3 + + thirdMappedProperty = nil + expect(signalCompleted) == 3 + expect(producerCompleted) == 3 + } + + it("should capture no properties") { + func increment(input: Int) -> Int { + return input + 1 + } + + weak var weakSourceProperty: MutableProperty? + weak var weakPropertyA: Property? + weak var weakPropertyB: Property? + weak var weakPropertyC: Property? + + var finalProperty: Property! + + func scope() { + let property = MutableProperty(1) + weakSourceProperty = property + + let propertyA = property.map(increment) + weakPropertyA = propertyA + + let propertyB = propertyA.map(increment) + weakPropertyB = propertyB + + let propertyC = propertyB.map(increment) + weakPropertyC = propertyC + + finalProperty = propertyC.map(increment) + } + + scope() + + expect(finalProperty.value) == 5 + expect(weakSourceProperty).to(beNil()) + expect(weakPropertyA).to(beNil()) + expect(weakPropertyB).to(beNil()) + expect(weakPropertyC).to(beNil()) + } + } + + describe("from a value and SignalProducer") { + it("should initially take on the supplied value") { + let property = Property(initial: initialPropertyValue, + then: SignalProducer.never) + + expect(property.value) == initialPropertyValue + } + + it("should take on each value sent on the producer") { + let property = Property(initial: initialPropertyValue, + then: SignalProducer(value: subsequentPropertyValue)) + + expect(property.value) == subsequentPropertyValue + } + + it("should complete its producer and signal even if the upstream interrupts") { + let (signal, observer) = Signal.pipe() + + let property = Property(initial: initialPropertyValue, then: SignalProducer(signal)) + + var isProducerCompleted = false + var isSignalCompleted = false + + property.producer.startWithCompleted { isProducerCompleted = true } + property.signal.observeCompleted { isSignalCompleted = true } + expect(isProducerCompleted) == false + expect(isSignalCompleted) == false + + observer.sendInterrupted() + expect(isProducerCompleted) == true + expect(isSignalCompleted) == true + } + + it("should return a producer and a signal that respect the lifetime of its ultimate source") { + var signalCompleted = false + var producerCompleted = false + var signalInterrupted = false + + let (signal, observer) = Signal.pipe() + var property: Property? = Property(initial: 1, then: SignalProducer(signal)) + let propertySignal = property!.signal + + propertySignal.observeCompleted { signalCompleted = true } + property!.producer.startWithCompleted { producerCompleted = true } + + expect(property!.value) == 1 + + observer.send(value: 2) + expect(property!.value) == 2 + expect(producerCompleted) == false + expect(signalCompleted) == false + + property = nil + expect(producerCompleted) == false + expect(signalCompleted) == false + + observer.sendCompleted() + expect(producerCompleted) == true + expect(signalCompleted) == true + + propertySignal.observeInterrupted { signalInterrupted = true } + expect(signalInterrupted) == true + } + } + + describe("from a value and Signal") { + it("should initially take on the supplied value, then values sent on the signal") { + let (signal, observer) = Signal.pipe() + + let property = Property(initial: initialPropertyValue, then: signal) + + expect(property.value) == initialPropertyValue + + observer.send(value: subsequentPropertyValue) + + expect(property.value) == subsequentPropertyValue + } + + it("should complete its producer and signal even if the upstream interrupts") { + let (signal, observer) = Signal.pipe() + + let property = Property(initial: initialPropertyValue, then: signal) + + var isProducerCompleted = false + var isSignalCompleted = false + + property.producer.startWithCompleted { isProducerCompleted = true } + property.signal.observeCompleted { isSignalCompleted = true } + expect(isProducerCompleted) == false + expect(isSignalCompleted) == false + + observer.sendInterrupted() + expect(isProducerCompleted) == true + expect(isSignalCompleted) == true + } + + it("should return a producer and a signal that respect the lifetime of its ultimate source") { + var signalCompleted = false + var producerCompleted = false + var signalInterrupted = false + + let (signal, observer) = Signal.pipe() + var property: Property? = Property(initial: 1, then: signal) + let propertySignal = property!.signal + + propertySignal.observeCompleted { signalCompleted = true } + property!.producer.startWithCompleted { producerCompleted = true } + + expect(property!.value) == 1 + + observer.send(value: 2) + expect(property!.value) == 2 + expect(producerCompleted) == false + expect(signalCompleted) == false + + property = nil + expect(producerCompleted) == false + expect(signalCompleted) == false + + observer.sendCompleted() + expect(producerCompleted) == true + expect(signalCompleted) == true + + propertySignal.observeInterrupted { signalInterrupted = true } + expect(signalInterrupted) == true + } + } + } + } + + describe("PropertyProtocol") { + describe("map") { + it("should transform the current value and all subsequent values") { + let property = MutableProperty(1) + let mappedProperty = property + .map { $0 + 1 } + expect(mappedProperty.value) == 2 + + property.value = 2 + expect(mappedProperty.value) == 3 + } + +#if swift(>=3.2) + it("should work with key paths") { + let property = MutableProperty("foo") + let mappedProperty = property.map(\.count) + expect(mappedProperty.value) == 3 + + property.value = "foobar" + expect(mappedProperty.value) == 6 + } +#endif + } + + describe("combineLatest") { + var property: MutableProperty! + var otherProperty: MutableProperty! + + beforeEach { + property = MutableProperty(initialPropertyValue) + otherProperty = MutableProperty(initialOtherPropertyValue) + } + + it("should forward the latest values from both inputs") { + let combinedProperty = property.combineLatest(with: otherProperty) + var latest: (String, String)? + combinedProperty.signal.observeValues { latest = $0 } + + property.value = subsequentPropertyValue + expect(latest?.0) == subsequentPropertyValue + expect(latest?.1) == initialOtherPropertyValue + + // is there a better way to test tuples? + otherProperty.value = subsequentOtherPropertyValue + expect(latest?.0) == subsequentPropertyValue + expect(latest?.1) == subsequentOtherPropertyValue + + property.value = finalPropertyValue + expect(latest?.0) == finalPropertyValue + expect(latest?.1) == subsequentOtherPropertyValue + } + + it("should complete when the source properties are deinitialized") { + var completed = false + + var combinedProperty = Optional(property.combineLatest(with: otherProperty)) + combinedProperty!.signal.observeCompleted { completed = true } + + combinedProperty = nil + expect(completed) == false + + property = nil + expect(completed) == false + + otherProperty = nil + expect(completed) == true + } + + it("should be consistent between its cached value and its values producer") { + var firstResult: String! + var secondResult: String! + + let combined = property.combineLatest(with: otherProperty) + combined.producer.startWithValues { firstResult = $0.0 + $0.1 } + + func getValue() -> String { + return combined.value.0 + combined.value.1 + } + + expect(getValue()) == initialPropertyValue + initialOtherPropertyValue + expect(firstResult) == initialPropertyValue + initialOtherPropertyValue + + property.value = subsequentPropertyValue + expect(getValue()) == subsequentPropertyValue + initialOtherPropertyValue + expect(firstResult) == subsequentPropertyValue + initialOtherPropertyValue + + combined.producer.startWithValues { secondResult = $0.0 + $0.1 } + expect(secondResult) == subsequentPropertyValue + initialOtherPropertyValue + + otherProperty.value = subsequentOtherPropertyValue + expect(getValue()) == subsequentPropertyValue + subsequentOtherPropertyValue + expect(firstResult) == subsequentPropertyValue + subsequentOtherPropertyValue + expect(secondResult) == subsequentPropertyValue + subsequentOtherPropertyValue + } + + it("should be consistent between nested combined properties") { + let A = MutableProperty(1) + let B = MutableProperty(100) + let C = MutableProperty(10000) + + var firstResult: Int! + + let combined = A.combineLatest(with: B) + combined.producer.startWithValues { firstResult = $0.0 + $0.1 } + + func getValue() -> Int { + return combined.value.0 + combined.value.1 + } + + /// Initial states + expect(getValue()) == 101 + expect(firstResult) == 101 + + A.value = 2 + expect(getValue()) == 102 + expect(firstResult) == 102 + + B.value = 200 + expect(getValue()) == 202 + expect(firstResult) == 202 + + /// Setup + A.value = 3 + expect(getValue()) == 203 + expect(firstResult) == 203 + + /// Zip another property now. + var secondResult: Int! + let anotherCombined = combined.combineLatest(with: C) + anotherCombined.producer.startWithValues { secondResult = ($0.0.0 + $0.0.1) + $0.1 } + + func getAnotherValue() -> Int { + return (anotherCombined.value.0.0 + anotherCombined.value.0.1) + anotherCombined.value.1 + } + + expect(getAnotherValue()) == 10203 + + A.value = 4 + expect(getValue()) == 204 + expect(getAnotherValue()) == 10204 + } + } + + describe("zip") { + var property: MutableProperty! + var otherProperty: MutableProperty! + + beforeEach { + property = MutableProperty(initialPropertyValue) + otherProperty = MutableProperty(initialOtherPropertyValue) + } + + it("should combine pairs") { + var result: [String] = [] + + let zippedProperty = property.zip(with: otherProperty) + zippedProperty.producer.startWithValues { result.append("\($0.0)\($0.1)") } + + let firstResult = [ "\(initialPropertyValue)\(initialOtherPropertyValue)" ] + let secondResult = firstResult + [ "\(subsequentPropertyValue)\(subsequentOtherPropertyValue)" ] + let thirdResult = secondResult + [ "\(finalPropertyValue)\(finalOtherPropertyValue)" ] + let finalResult = thirdResult + [ "\(initialPropertyValue)\(initialOtherPropertyValue)" ] + + expect(result) == firstResult + + property.value = subsequentPropertyValue + expect(result) == firstResult + + otherProperty.value = subsequentOtherPropertyValue + expect(result) == secondResult + + property.value = finalPropertyValue + otherProperty.value = finalOtherPropertyValue + expect(result) == thirdResult + + property.value = initialPropertyValue + expect(result) == thirdResult + + property.value = subsequentPropertyValue + expect(result) == thirdResult + + otherProperty.value = initialOtherPropertyValue + expect(result) == finalResult + } + + it("should be consistent between its cached value and its values producer") { + var firstResult: String! + var secondResult: String! + + let zippedProperty = property.zip(with: otherProperty) + zippedProperty.producer.startWithValues { firstResult = $0.0 + $0.1 } + + func getValue() -> String { + return zippedProperty.value.0 + zippedProperty.value.1 + } + + expect(getValue()) == initialPropertyValue + initialOtherPropertyValue + expect(firstResult) == initialPropertyValue + initialOtherPropertyValue + + property.value = subsequentPropertyValue + expect(getValue()) == initialPropertyValue + initialOtherPropertyValue + expect(firstResult) == initialPropertyValue + initialOtherPropertyValue + + // It should still be the tuple with initial property values, + // since `otherProperty` isn't changed yet. + zippedProperty.producer.startWithValues { secondResult = $0.0 + $0.1 } + expect(secondResult) == initialPropertyValue + initialOtherPropertyValue + + otherProperty.value = subsequentOtherPropertyValue + expect(getValue()) == subsequentPropertyValue + subsequentOtherPropertyValue + expect(firstResult) == subsequentPropertyValue + subsequentOtherPropertyValue + expect(secondResult) == subsequentPropertyValue + subsequentOtherPropertyValue + } + + it("should be consistent between nested zipped properties") { + let A = MutableProperty(1) + let B = MutableProperty(100) + let C = MutableProperty(10000) + + var firstResult: Int! + + let zipped = A.zip(with: B) + zipped.producer.startWithValues { firstResult = $0.0 + $0.1 } + + func getValue() -> Int { + return zipped.value.0 + zipped.value.1 + } + + /// Initial states + expect(getValue()) == 101 + expect(firstResult) == 101 + + A.value = 2 + expect(getValue()) == 101 + expect(firstResult) == 101 + + B.value = 200 + expect(getValue()) == 202 + expect(firstResult) == 202 + + /// Setup + A.value = 3 + expect(getValue()) == 202 + expect(firstResult) == 202 + + /// Zip another property now. + var secondResult: Int! + let anotherZipped = zipped.zip(with: C) + anotherZipped.producer.startWithValues { secondResult = ($0.0.0 + $0.0.1) + $0.1 } + + func getAnotherValue() -> Int { + return (anotherZipped.value.0.0 + anotherZipped.value.0.1) + anotherZipped.value.1 + } + + /// Since `zipped` is 202 now, and `C` is 10000, + /// shouldn't this be 10202? + + /// Verify `zipped` again. + expect(getValue()) == 202 + expect(firstResult) == 202 + + /// Then... well, no. Surprise! (Only before #3042) + /// We get 10203 here. + /// + /// https://github.com/ReactiveCocoa/ReactiveCocoa/pull/3042 + expect(getAnotherValue()) == 10202 + } + + it("should be consistent between combined and nested zipped properties") { + let A = MutableProperty(1) + let B = MutableProperty(100) + let C = MutableProperty(10000) + let D = MutableProperty(1000000) + + var firstResult: Int! + + let zipped = A.zip(with: B) + zipped.producer.startWithValues { firstResult = $0.0 + $0.1 } + + func getValue() -> Int { + return zipped.value.0 + zipped.value.1 + } + + /// Initial states + expect(getValue()) == 101 + expect(firstResult) == 101 + + A.value = 2 + expect(getValue()) == 101 + expect(firstResult) == 101 + + B.value = 200 + expect(getValue()) == 202 + expect(firstResult) == 202 + + /// Setup + A.value = 3 + expect(getValue()) == 202 + expect(firstResult) == 202 + + /// Zip another property now. + var secondResult: Int! + let anotherZipped = zipped.zip(with: C) + anotherZipped.producer.startWithValues { secondResult = ($0.0.0 + $0.0.1) + $0.1 } + + func getAnotherValue() -> Int { + return (anotherZipped.value.0.0 + anotherZipped.value.0.1) + anotherZipped.value.1 + } + + /// Verify `zipped` again. + expect(getValue()) == 202 + expect(firstResult) == 202 + + expect(getAnotherValue()) == 10202 + + /// Zip `D` with `anotherZipped`. + let yetAnotherZipped = anotherZipped.zip(with: D) + + /// Combine with another property. + /// (((Int, Int), Int), (((Int, Int), Int), Int)) + let combined = anotherZipped.combineLatest(with: yetAnotherZipped) + + var thirdResult: Int! + combined.producer.startWithValues { + let leftResult = $0.0.0.0 + $0.0.0.1 + $0.0.1 + let rightResult = $0.1.0.0.0 + $0.1.0.0.1 + $0.1.0.1 + $0.1.1 + thirdResult = leftResult + rightResult + } + + expect(thirdResult) == 1020404 + } + + it("should complete its producer only when the source properties are deinitialized") { + var result: [String] = [] + var completed = false + + var zippedProperty = Optional(property.zip(with: otherProperty)) + zippedProperty!.producer.start { event in + switch event { + case let .value(left, right): + result.append("\(left)\(right)") + case .completed: + completed = true + default: + break + } + } + + expect(completed) == false + expect(result) == [ "\(initialPropertyValue)\(initialOtherPropertyValue)" ] + + property.value = subsequentPropertyValue + expect(result) == [ "\(initialPropertyValue)\(initialOtherPropertyValue)" ] + + zippedProperty = nil + expect(completed) == false + + property = nil + otherProperty = nil + expect(completed) == true + } + } + + describe("unary operators") { + var property: MutableProperty! + + beforeEach { + property = MutableProperty(initialPropertyValue) + } + + describe("combinePrevious") { + it("should pack the current value and the previous value a tuple") { + let transformedProperty = property.combinePrevious(initialPropertyValue) + + expect(transformedProperty.value.0) == initialPropertyValue + expect(transformedProperty.value.1) == initialPropertyValue + + property.value = subsequentPropertyValue + + expect(transformedProperty.value.0) == initialPropertyValue + expect(transformedProperty.value.1) == subsequentPropertyValue + + property.value = finalPropertyValue + + expect(transformedProperty.value.0) == subsequentPropertyValue + expect(transformedProperty.value.1) == finalPropertyValue + } + + it("should complete its producer only when the source property is deinitialized") { + var result: (String, String)? + var completed = false + + var transformedProperty = Optional(property.combinePrevious(initialPropertyValue)) + transformedProperty!.producer.start { event in + switch event { + case let .value(tuple): + result = tuple + case .completed: + completed = true + default: + break + } + } + + expect(result?.0) == initialPropertyValue + expect(result?.1) == initialPropertyValue + + property.value = subsequentPropertyValue + + expect(result?.0) == initialPropertyValue + expect(result?.1) == subsequentPropertyValue + + transformedProperty = nil + expect(completed) == false + + property = nil + expect(completed) == true + } + } + + describe("skipRepeats") { + it("should not emit events for subsequent equatable values that are the same as the current value") { + let transformedProperty = property.skipRepeats() + + var counter = 0 + transformedProperty.signal.observeValues { _ in + counter += 1 + } + + property.value = initialPropertyValue + property.value = initialPropertyValue + property.value = initialPropertyValue + + expect(counter) == 0 + + property.value = subsequentPropertyValue + property.value = subsequentPropertyValue + property.value = subsequentPropertyValue + + expect(counter) == 1 + + property.value = finalPropertyValue + property.value = initialPropertyValue + property.value = subsequentPropertyValue + + expect(counter) == 4 + } + + it("should not emit events for subsequent values that are regarded as the same as the current value by the supplied closure") { + var counter = 0 + let transformedProperty = property.skipRepeats { _, newValue in newValue == initialPropertyValue } + + transformedProperty.signal.observeValues { _ in + counter += 1 + } + + property.value = initialPropertyValue + expect(counter) == 0 + + property.value = subsequentPropertyValue + expect(counter) == 1 + + property.value = finalPropertyValue + expect(counter) == 2 + + property.value = initialPropertyValue + expect(counter) == 2 + } + + it("should complete its producer only when the source property is deinitialized") { + var counter = 0 + var completed = false + + var transformedProperty = Optional(property.skipRepeats()) + transformedProperty!.producer.start { event in + switch event { + case .value: + counter += 1 + case .completed: + completed = true + default: + break + } + } + + expect(counter) == 1 + + property.value = initialPropertyValue + expect(counter) == 1 + + transformedProperty = nil + expect(completed) == false + + property = nil + expect(completed) == true + } + } + + describe("uniqueValues") { + it("should emit hashable values that have not been emited before") { + let transformedProperty = property.uniqueValues() + + var counter = 0 + transformedProperty.signal.observeValues { _ in + counter += 1 + } + + property.value = initialPropertyValue + expect(counter) == 0 + + property.value = subsequentPropertyValue + property.value = subsequentPropertyValue + + expect(counter) == 1 + + property.value = finalPropertyValue + property.value = initialPropertyValue + property.value = subsequentPropertyValue + + expect(counter) == 2 + } + + it("should emit only the values of which the computed identity have not been captured before") { + let transformedProperty = property.uniqueValues { _ in 0 } + + var counter = 0 + transformedProperty.signal.observeValues { _ in + counter += 1 + } + + property.value = initialPropertyValue + property.value = subsequentPropertyValue + property.value = finalPropertyValue + expect(counter) == 0 + } + + it("should complete its producer only when the source property is deinitialized") { + var counter = 0 + var completed = false + + var transformedProperty = Optional(property.uniqueValues()) + transformedProperty!.producer.start { event in + switch event { + case .value: + counter += 1 + case .completed: + completed = true + default: + break + } + } + + expect(counter) == 1 + + property.value = initialPropertyValue + expect(counter) == 1 + + transformedProperty = nil + expect(completed) == false + + property = nil + expect(completed) == true + } + } + } + + describe("flattening") { + describe("flatten") { + describe("FlattenStrategy.concat") { + it("should concatenate the values as the inner property is replaced and deinitialized") { + var firstProperty = Optional(MutableProperty(0)) + var secondProperty = Optional(MutableProperty(10)) + var thirdProperty = Optional(MutableProperty(20)) + + var outerProperty = Optional(MutableProperty(firstProperty!)) + + var receivedValues: [Int] = [] + var errored = false + var completed = false + + let flattenedProperty = outerProperty!.flatten(.concat) + + flattenedProperty.producer.start { event in + switch event { + case let .value(value): + receivedValues.append(value) + case .completed: + completed = true + case .failed: + errored = true + case .interrupted: + break + } + } + + expect(receivedValues) == [ 0 ] + + outerProperty!.value = secondProperty! + secondProperty!.value = 11 + outerProperty!.value = thirdProperty! + thirdProperty!.value = 21 + + expect(receivedValues) == [ 0 ] + expect(completed) == false + + secondProperty!.value = 12 + thirdProperty!.value = 22 + + expect(receivedValues) == [ 0 ] + expect(completed) == false + + firstProperty = nil + + expect(receivedValues) == [ 0, 12 ] + expect(completed) == false + + secondProperty = nil + + expect(receivedValues) == [ 0, 12, 22 ] + expect(completed) == false + + outerProperty = nil + expect(completed) == false + + thirdProperty = nil + expect(completed) == true + expect(errored) == false + } + } + + describe("FlattenStrategy.merge") { + it("should merge the values of all inner properties") { + var firstProperty = Optional(MutableProperty(0)) + var secondProperty = Optional(MutableProperty(10)) + var thirdProperty = Optional(MutableProperty(20)) + + var outerProperty = Optional(MutableProperty(firstProperty!)) + + var receivedValues: [Int] = [] + var errored = false + var completed = false + + let flattenedProperty = outerProperty!.flatten(.merge) + + flattenedProperty.producer.start { event in + switch event { + case let .value(value): + receivedValues.append(value) + case .completed: + completed = true + case .failed: + errored = true + case .interrupted: + break + } + } + + expect(receivedValues) == [ 0 ] + + outerProperty!.value = secondProperty! + secondProperty!.value = 11 + outerProperty!.value = thirdProperty! + thirdProperty!.value = 21 + + expect(receivedValues) == [ 0, 10, 11, 20, 21 ] + expect(completed) == false + + secondProperty!.value = 12 + thirdProperty!.value = 22 + + expect(receivedValues) == [ 0, 10, 11, 20, 21, 12, 22 ] + expect(completed) == false + + firstProperty = nil + + expect(receivedValues) == [ 0, 10, 11, 20, 21, 12, 22 ] + expect(completed) == false + + secondProperty = nil + + expect(receivedValues) == [ 0, 10, 11, 20, 21, 12, 22 ] + expect(completed) == false + + outerProperty = nil + expect(completed) == false + + thirdProperty = nil + expect(completed) == true + expect(errored) == false + } + } + + describe("FlattenStrategy.latest") { + it("should forward values from the latest inner property") { + let firstProperty = Optional(MutableProperty(0)) + var secondProperty = Optional(MutableProperty(10)) + var thirdProperty = Optional(MutableProperty(20)) + + var outerProperty = Optional(MutableProperty(firstProperty!)) + + var receivedValues: [Int] = [] + var errored = false + var completed = false + + outerProperty!.flatten(.latest).producer.start { event in + switch event { + case let .value(value): + receivedValues.append(value) + case .completed: + completed = true + case .failed: + errored = true + case .interrupted: + break + } + } + + expect(receivedValues) == [ 0 ] + + outerProperty!.value = secondProperty! + secondProperty!.value = 11 + outerProperty!.value = thirdProperty! + thirdProperty!.value = 21 + + expect(receivedValues) == [ 0, 10, 11, 20, 21 ] + expect(errored) == false + expect(completed) == false + + secondProperty!.value = 12 + secondProperty = nil + thirdProperty!.value = 22 + thirdProperty = nil + + expect(receivedValues) == [ 0, 10, 11, 20, 21, 22 ] + expect(errored) == false + expect(completed) == false + + outerProperty = nil + expect(errored) == false + expect(completed) == true + } + + it("should release the old properties when switched or deallocated") { + var firstProperty = Optional(MutableProperty(0)) + var secondProperty = Optional(MutableProperty(10)) + var thirdProperty = Optional(MutableProperty(20)) + + weak var weakFirstProperty = firstProperty + weak var weakSecondProperty = secondProperty + weak var weakThirdProperty = thirdProperty + + var outerProperty = Optional(MutableProperty(firstProperty!)) + var flattened = Optional(outerProperty!.flatten(.latest)) + + var errored = false + var completed = false + + flattened!.producer.start { event in + switch event { + case .completed: + completed = true + case .failed: + errored = true + case .interrupted, .value: + break + } + } + + firstProperty = nil + outerProperty!.value = secondProperty! + expect(weakFirstProperty).to(beNil()) + + secondProperty = nil + outerProperty!.value = thirdProperty! + expect(weakSecondProperty).to(beNil()) + + thirdProperty = nil + outerProperty = nil + flattened = nil + expect(weakThirdProperty).to(beNil()) + expect(errored) == false + expect(completed) == true + } + } + } + + describe("flatMap") { + describe("PropertyFlattenStrategy.latest") { + it("should forward values from the latest inner transformed property") { + let firstProperty = Optional(MutableProperty(0)) + var secondProperty = Optional(MutableProperty(10)) + var thirdProperty = Optional(MutableProperty(20)) + + var outerProperty = Optional(MutableProperty(firstProperty!)) + + var receivedValues: [String] = [] + var errored = false + var completed = false + + outerProperty!.flatMap(.latest) { $0.map { "\($0)" } }.producer.start { event in + switch event { + case let .value(value): + receivedValues.append(value) + case .completed: + completed = true + case .failed: + errored = true + case .interrupted: + break + } + } + + expect(receivedValues) == [ "0" ] + + outerProperty!.value = secondProperty! + secondProperty!.value = 11 + outerProperty!.value = thirdProperty! + thirdProperty!.value = 21 + + expect(receivedValues) == [ "0", "10", "11", "20", "21" ] + expect(errored) == false + expect(completed) == false + + secondProperty!.value = 12 + secondProperty = nil + thirdProperty!.value = 22 + thirdProperty = nil + + expect(receivedValues) == [ "0", "10", "11", "20", "21", "22" ] + expect(errored) == false + expect(completed) == false + + outerProperty = nil + expect(errored) == false + expect(completed) == true + } + } + } + } + + describe("negated attribute") { + it("should return the negate of a value in a Boolean property") { + let property = MutableProperty(true) + expect(property.negate().value).to(beFalse()) + } + } + + describe("and attribute") { + it("should emit true when both properties contains the same value") { + let property1 = MutableProperty(true) + let property2 = Property(MutableProperty(true)) + expect(property1.and(property2).value).to(beTrue()) + } + + it("should emit false when both properties contains opposite values") { + let property1 = MutableProperty(true) + let property2 = Property(MutableProperty(false)) + expect(property1.and(property2).value).to(beFalse()) + } + } + + describe("or attribute") { + it("should emit true when at least one of the properties contains true") { + let property1 = MutableProperty(true) + let property2 = Property(MutableProperty(false)) + expect(property1.or(property2).value).to(beTrue()) + } + + it("should emit false when both properties contains false") { + let property1 = MutableProperty(false) + let property2 = Property(MutableProperty(false)) + expect(property1.or(property2).value).to(beFalse()) + } + } + } + + describe("binding") { + describe("from a Signal") { + it("should update the property with values sent from the signal") { + let (signal, observer) = Signal.pipe() + + let mutableProperty = MutableProperty(initialPropertyValue) + + mutableProperty <~ signal + + // Verify that the binding hasn't changed the property value: + expect(mutableProperty.value) == initialPropertyValue + + observer.send(value: subsequentPropertyValue) + expect(mutableProperty.value) == subsequentPropertyValue + } + + it("should tear down the binding when disposed") { + let (signal, observer) = Signal.pipe() + + let mutableProperty = MutableProperty(initialPropertyValue) + + let bindingDisposable = mutableProperty <~ signal + bindingDisposable!.dispose() + + observer.send(value: subsequentPropertyValue) + expect(mutableProperty.value) == initialPropertyValue + } + + it("should tear down the binding when the property deallocates") { + var isDisposed = false + + var outerObserver: Signal.Observer! + var signal: Signal? = { + let (signal, observer) = Signal.pipe() + outerObserver = observer + return signal.on(disposed: { isDisposed = true }) + }() + weak var weakSignal = signal + + var mutableProperty: MutableProperty? = MutableProperty(initialPropertyValue) + + mutableProperty! <~ signal! + signal = nil + + // The binding attached an observer to the signal, so it cannot + // be disposed of. + expect(weakSignal).to(beNil()) + expect(isDisposed) == false + + // The deinitialization should tear down the binding, which would + // remove the last observer from the signal, causing it to + // dispose of itself. + mutableProperty = nil + expect(weakSignal).to(beNil()) + expect(isDisposed) == true + } + } + + describe("from a SignalProducer") { + it("should start a signal and update the property with its values") { + let signalValues = [initialPropertyValue, subsequentPropertyValue] + let signalProducer = SignalProducer(signalValues) + + let mutableProperty = MutableProperty(initialPropertyValue) + + mutableProperty <~ signalProducer + + expect(mutableProperty.value) == signalValues.last! + } + + it("should tear down the binding when disposed") { + let (signalProducer, observer) = SignalProducer.pipe() + + let mutableProperty = MutableProperty(initialPropertyValue) + let disposable = mutableProperty <~ signalProducer + + disposable?.dispose() + + observer.send(value: subsequentPropertyValue) + expect(mutableProperty.value) == initialPropertyValue + } + + it("should tear down the binding when the property deallocates") { + let (signal, _) = Signal.pipe() + let signalProducer = SignalProducer(signal) + + var mutableProperty: MutableProperty? = MutableProperty(initialPropertyValue) + + var isDisposed = false + mutableProperty! <~ signalProducer.on(disposed: { isDisposed = true }) + expect(isDisposed) == false + + mutableProperty = nil + expect(isDisposed) == true + } + } + + describe("from another property") { + it("should take the source property's current value") { + let sourceProperty = Property(value: initialPropertyValue) + + let destinationProperty = MutableProperty("") + + destinationProperty <~ sourceProperty.producer + + expect(destinationProperty.value) == initialPropertyValue + } + + it("should update with changes to the source property's value") { + let sourceProperty = MutableProperty(initialPropertyValue) + + let destinationProperty = MutableProperty("") + + destinationProperty <~ sourceProperty.producer + + sourceProperty.value = subsequentPropertyValue + expect(destinationProperty.value) == subsequentPropertyValue + } + + it("should tear down the binding when disposed") { + let sourceProperty = MutableProperty(initialPropertyValue) + + let destinationProperty = MutableProperty("") + + let bindingDisposable = destinationProperty <~ sourceProperty.producer + bindingDisposable?.dispose() + + sourceProperty.value = subsequentPropertyValue + + expect(destinationProperty.value) == initialPropertyValue + } + + it("should tear down the binding when the source property deallocates") { + var sourceProperty: MutableProperty? = MutableProperty(initialPropertyValue) + + let destinationProperty = MutableProperty("") + destinationProperty <~ sourceProperty!.producer + + sourceProperty = nil + // TODO: Assert binding was torn down? + } + + it("should tear down the binding when the destination property deallocates") { + let sourceProperty = MutableProperty(initialPropertyValue) + var destinationProperty: MutableProperty? = MutableProperty("") + + var isDisposed = false + destinationProperty! <~ sourceProperty.producer.on(disposed: { isDisposed = true }) + expect(isDisposed) == false + + destinationProperty = nil + expect(isDisposed) == true + } + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ReactiveExtensionsSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ReactiveExtensionsSpec.swift new file mode 100644 index 0000000..70fbe4d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ReactiveExtensionsSpec.swift @@ -0,0 +1,33 @@ +import Nimble +import Quick +import ReactiveSwift +import Result + +private final class TestExtensionProvider: ReactiveExtensionsProvider { + let instanceProperty = "instance" + static let staticProperty = "static" +} + +extension Reactive where Base: TestExtensionProvider { + var instanceProperty: SignalProducer { + return SignalProducer(value: base.instanceProperty) + } + + static var staticProperty: SignalProducer { + return SignalProducer(value: Base.staticProperty) + } +} + +final class ReactiveExtensionsSpec: QuickSpec { + override func spec() { + describe("ReactiveExtensions") { + it("allows reactive extensions of instances") { + expect(TestExtensionProvider().reactive.instanceProperty.first()?.value) == "instance" + } + + it("allows reactive extensions of types") { + expect(TestExtensionProvider.reactive.staticProperty.first()?.value) == "static" + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SchedulerSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SchedulerSpec.swift new file mode 100644 index 0000000..c4b8fe7 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SchedulerSpec.swift @@ -0,0 +1,311 @@ +// +// SchedulerSpec.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2014-07-13. +// Copyright (c) 2014 GitHub. All rights reserved. +// + +import Dispatch +import Foundation + +import Nimble +import Quick +@testable +import ReactiveSwift + +#if os(Linux) + import func CoreFoundation._CFIsMainThread + + private extension Thread { + // `isMainThread` is not implemented yet in swift-corelibs-foundation. + static var isMainThread: Bool { + return _CFIsMainThread() + } + } +#endif + +class SchedulerSpec: QuickSpec { + override func spec() { + describe("ImmediateScheduler") { + it("should run enqueued actions immediately") { + var didRun = false + ImmediateScheduler().schedule { + didRun = true + } + + expect(didRun) == true + } + } + + describe("UIScheduler") { + func dispatchSyncInBackground(_ action: @escaping () -> Void) { + let group = DispatchGroup() + + let globalQueue: DispatchQueue + if #available(*, OSX 10.10) { + globalQueue = DispatchQueue.global() + } else { + globalQueue = DispatchQueue.global(priority: .default) + } + + globalQueue.async(group: group, execute: action) + group.wait() + } + + it("should run actions immediately when on the main thread") { + let scheduler = UIScheduler() + var values: [Int] = [] + expect(Thread.isMainThread) == true + + scheduler.schedule { + values.append(0) + } + + expect(values) == [ 0 ] + + scheduler.schedule { + values.append(1) + } + + scheduler.schedule { + values.append(2) + } + + expect(values) == [ 0, 1, 2 ] + } + + it("should enqueue actions scheduled from the background") { + let scheduler = UIScheduler() + var values: [Int] = [] + + dispatchSyncInBackground { + scheduler.schedule { + expect(Thread.isMainThread) == true + values.append(0) + } + + return + } + + expect(values) == [] + expect(values).toEventually(equal([ 0 ])) + + dispatchSyncInBackground { + scheduler.schedule { + expect(Thread.isMainThread) == true + values.append(1) + } + + scheduler.schedule { + expect(Thread.isMainThread) == true + values.append(2) + } + + return + } + + expect(values) == [ 0 ] + expect(values).toEventually(equal([ 0, 1, 2 ])) + } + + it("should run actions enqueued from the main thread after those from the background") { + let scheduler = UIScheduler() + var values: [Int] = [] + + dispatchSyncInBackground { + scheduler.schedule { + expect(Thread.isMainThread) == true + values.append(0) + } + + return + } + + scheduler.schedule { + expect(Thread.isMainThread) == true + values.append(1) + } + + scheduler.schedule { + expect(Thread.isMainThread) == true + values.append(2) + } + + expect(values) == [] + expect(values).toEventually(equal([ 0, 1, 2 ])) + } + } + + describe("QueueScheduler") { + it("should run enqueued actions on a global queue") { + var didRun = false + + let scheduler: QueueScheduler + if #available(OSX 10.10, *) { + scheduler = QueueScheduler(qos: .default, name: "\(#file):\(#line)") + } else { + scheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + + scheduler.schedule { + didRun = true + expect(Thread.isMainThread) == false + } + + expect{didRun}.toEventually(beTruthy()) + } + + describe("on a given queue") { + var scheduler: QueueScheduler! + + beforeEach { + if #available(OSX 10.10, *) { + scheduler = QueueScheduler(qos: .default, name: "\(#file):\(#line)") + } else { + scheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + scheduler.queue.suspend() + } + + it("should run enqueued actions serially on the given queue") { + var value = 0 + + for _ in 0..<5 { + scheduler.schedule { + expect(Thread.isMainThread) == false + value += 1 + } + } + + expect(value) == 0 + + scheduler.queue.resume() + expect{value}.toEventually(equal(5)) + } + + it("should run enqueued actions after a given date") { + var didRun = false + scheduler.schedule(after: Date()) { + didRun = true + expect(Thread.isMainThread) == false + } + + expect(didRun) == false + + scheduler.queue.resume() + expect{didRun}.toEventually(beTruthy()) + } + + it("should repeatedly run actions after a given date") { + let disposable = SerialDisposable() + + var count = 0 + let timesToRun = 3 + + disposable.inner = scheduler.schedule(after: Date(), interval: .milliseconds(10), leeway: .seconds(0)) { + expect(Thread.isMainThread) == false + + count += 1 + + if count == timesToRun { + disposable.dispose() + } + } + + expect(count) == 0 + + scheduler.queue.resume() + expect{count}.toEventually(equal(timesToRun)) + } + } + } + + describe("TestScheduler") { + var scheduler: TestScheduler! + var startDate: Date! + + // How much dates are allowed to differ when they should be "equal." + let dateComparisonDelta = 0.00001 + + beforeEach { + startDate = Date() + + scheduler = TestScheduler(startDate: startDate) + expect(scheduler.currentDate) == startDate + } + + it("should run immediately enqueued actions upon advancement") { + var string = "" + + scheduler.schedule { + string += "foo" + expect(Thread.isMainThread) == true + } + + scheduler.schedule { + string += "bar" + expect(Thread.isMainThread) == true + } + + expect(string) == "" + + scheduler.advance() + expect(scheduler.currentDate).to(beCloseTo(startDate)) + + expect(string) == "foobar" + } + + it("should run actions when advanced past the target date") { + var string = "" + + scheduler.schedule(after: .seconds(15)) { [weak scheduler] in + string += "bar" + expect(Thread.isMainThread) == true + expect(scheduler?.currentDate).to(beCloseTo(startDate.addingTimeInterval(15), within: dateComparisonDelta)) + } + + scheduler.schedule(after: .seconds(5)) { [weak scheduler] in + string += "foo" + expect(Thread.isMainThread) == true + expect(scheduler?.currentDate).to(beCloseTo(startDate.addingTimeInterval(5), within: dateComparisonDelta)) + } + + expect(string) == "" + + scheduler.advance(by: .seconds(10)) + expect(scheduler.currentDate).to(beCloseTo(startDate.addingTimeInterval(10), within: TimeInterval(dateComparisonDelta))) + expect(string) == "foo" + + scheduler.advance(by: .seconds(10)) + expect(scheduler.currentDate).to(beCloseTo(startDate.addingTimeInterval(20), within: dateComparisonDelta)) + expect(string) == "foobar" + } + + it("should run all remaining actions in order") { + var string = "" + + scheduler.schedule(after: .seconds(15)) { + string += "bar" + expect(Thread.isMainThread) == true + } + + scheduler.schedule(after: .seconds(5)) { + string += "foo" + expect(Thread.isMainThread) == true + } + + scheduler.schedule { + string += "fuzzbuzz" + expect(Thread.isMainThread) == true + } + + expect(string) == "" + + scheduler.run() + expect(scheduler.currentDate) == NSDate.distantFuture + expect(string) == "fuzzbuzzfoobar" + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalLifetimeSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalLifetimeSpec.swift new file mode 100644 index 0000000..fbfa3f0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalLifetimeSpec.swift @@ -0,0 +1,441 @@ +// +// SignalLifetimeSpec.swift +// ReactiveSwift +// +// Created by Vadim Yelagin on 2015-12-13. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +import Foundation + +import Result +import Nimble +import Quick +import ReactiveSwift + +class SignalLifetimeSpec: QuickSpec { + override func spec() { + describe("init") { + var testScheduler: TestScheduler! + + beforeEach { + testScheduler = TestScheduler() + } + + it("should be disposed of if it does not have any observers") { + var isDisposed = false + + weak var signal: Signal? = { + let signal: Signal = Signal { _ in nil } + return signal.on(disposed: { isDisposed = true }) + }() + expect(signal).to(beNil()) + expect(isDisposed) == true + } + + it("should be disposed of if no one retains it") { + var isDisposed = false + var signal: Signal? = Signal { _ in nil }.on(disposed: { isDisposed = true }) + weak var weakSignal = signal + + expect(weakSignal).toNot(beNil()) + expect(isDisposed) == false + + var reference = signal + signal = nil + expect(weakSignal).toNot(beNil()) + expect(isDisposed) == false + + reference = nil + expect(weakSignal).to(beNil()) + expect(isDisposed) == true + } + + it("should be disposed of when the signal shell has deinitialized with no active observer regardless of whether the generator observer is retained or not") { + var observer: Signal.Observer? + var isDisposed = false + + weak var signal: Signal? = { + let signal: Signal = Signal { innerObserver in + observer = innerObserver + return nil + } + return signal.on(disposed: { isDisposed = true }) + }() + expect(observer).toNot(beNil()) + expect(signal).to(beNil()) + expect(isDisposed) == true + } + + it("should be disposed of when the generator observer has deinitialized even if it has an observer") { + var isDisposed = false + + var disposable: Disposable? = nil + weak var signal: Signal? = { + let signal: Signal = Signal { _ in nil } + disposable = signal.on(disposed: { isDisposed = true }).observe(Signal.Observer()) + return signal + }() + expect(signal).to(beNil()) + expect(isDisposed) == true + + disposable?.dispose() + expect(signal).to(beNil()) + expect(isDisposed) == true + } + + it("should be alive until erroring if it has at least one observer, despite not being explicitly retained") { + var errored = false + var isDisposed = false + + weak var signal: Signal? = { + let signal = Signal { observer in + testScheduler.schedule { + observer.send(error: TestError.default) + } + return nil + } + signal.on(disposed: { isDisposed = true }).observeFailed { _ in errored = true } + return signal + }() + + expect(errored) == false + expect(signal).to(beNil()) + expect(isDisposed) == false + + testScheduler.run() + + expect(errored) == true + expect(signal).to(beNil()) + expect(isDisposed) == true + } + + it("should be alive until completion if it has at least one observer, despite not being explicitly retained") { + var completed = false + var isDisposed = false + + weak var signal: Signal? = { + let signal = Signal { observer in + testScheduler.schedule { + observer.sendCompleted() + } + return nil + } + signal.on(disposed: { isDisposed = true }).observeCompleted { completed = true } + return signal + }() + + expect(completed) == false + expect(signal).to(beNil()) + expect(isDisposed) == false + + testScheduler.run() + + expect(completed) == true + expect(signal).to(beNil()) + expect(isDisposed) == true + } + + it("should be alive until interruption if it has at least one observer, despite not being explicitly retained") { + var interrupted = false + var isDisposed = false + + weak var signal: Signal? = { + let signal = Signal { observer in + testScheduler.schedule { + observer.sendInterrupted() + } + + return nil + } + signal.on(disposed: { isDisposed = true }).observeInterrupted { interrupted = true } + return signal + }() + + expect(interrupted) == false + expect(signal).to(beNil()) + expect(isDisposed) == false + + testScheduler.run() + + expect(interrupted) == true + expect(signal).to(beNil()) + expect(isDisposed) == true + } + } + + describe("Signal.pipe") { + it("should deallocate") { + weak var signal = Signal<(), NoError>.pipe().0 + + expect(signal).to(beNil()) + } + + it("should be alive until erroring if it has at least one observer, despite not being explicitly retained") { + let testScheduler = TestScheduler() + var errored = false + weak var weakSignal: Signal<(), TestError>? + var isDisposed = false + + // Use an inner closure to help ARC deallocate things as we + // expect. + let test = { + let (signal, observer) = Signal<(), TestError>.pipe() + weakSignal = signal + testScheduler.schedule { + // Note that the input observer has a weak reference to the signal. + observer.send(error: TestError.default) + } + signal.on(disposed: { isDisposed = true }).observeFailed { _ in errored = true } + } + test() + + expect(weakSignal).to(beNil()) + expect(isDisposed) == false + expect(errored) == false + + testScheduler.run() + + expect(weakSignal).to(beNil()) + expect(isDisposed) == true + expect(errored) == true + } + + it("should be alive until completion if it has at least one observer, despite not being explicitly retained") { + let testScheduler = TestScheduler() + var completed = false + weak var weakSignal: Signal<(), TestError>? + var isDisposed = false + + // Use an inner closure to help ARC deallocate things as we + // expect. + let test = { + let (signal, observer) = Signal<(), TestError>.pipe() + weakSignal = signal + testScheduler.schedule { + // Note that the input observer has a weak reference to the signal. + observer.sendCompleted() + } + signal.on(disposed: { isDisposed = true }).observeCompleted { completed = true } + } + test() + + expect(weakSignal).to(beNil()) + expect(isDisposed) == false + expect(completed) == false + + testScheduler.run() + + expect(weakSignal).to(beNil()) + expect(isDisposed) == true + expect(completed) == true + } + + it("should be alive until interruption if it has at least one observer, despite not being explicitly retained") { + let testScheduler = TestScheduler() + var interrupted = false + weak var weakSignal: Signal<(), NoError>? + var isDisposed = false + + let test = { + let (signal, observer) = Signal<(), NoError>.pipe() + weakSignal = signal + + testScheduler.schedule { + // Note that the input observer has a weak reference to the signal. + observer.sendInterrupted() + } + + signal.on(disposed: { isDisposed = true }).observeInterrupted { interrupted = true } + } + + test() + expect(weakSignal).to(beNil()) + expect(isDisposed) == false + expect(interrupted) == false + + testScheduler.run() + + expect(weakSignal).to(beNil()) + expect(isDisposed) == true + expect(interrupted) == true + } + } + + describe("testTransform") { + it("should be disposed of") { + var isDisposed = false + weak var signal: Signal? = Signal { _ in nil } + .testTransform() + .on(disposed: { isDisposed = true }) + + expect(signal).to(beNil()) + expect(isDisposed) == true + } + + it("should be disposed of if it is not explicitly retained and its generator observer is not retained") { + var disposable: Disposable? = nil + var isDisposed = false + + weak var signal: Signal? = { + let signal: Signal = Signal { _ in nil }.testTransform() + disposable = signal.on(disposed: { isDisposed = true }).observe(Signal.Observer()) + return signal + }() + expect(signal).to(beNil()) + expect(isDisposed) == true + } + + it("should deallocate if it is unreachable and has no observer") { + let (sourceSignal, sourceObserver) = Signal.pipe() + + var firstCounter = 0 + var secondCounter = 0 + var thirdCounter = 0 + + func run() { + _ = sourceSignal + .map { value -> Int in + firstCounter += 1 + return value + } + .map { value -> Int in + secondCounter += 1 + return value + } + .map { value -> Int in + thirdCounter += 1 + return value + } + } + + run() + + sourceObserver.send(value: 1) + expect(firstCounter) == 0 + expect(secondCounter) == 0 + expect(thirdCounter) == 0 + + sourceObserver.send(value: 2) + expect(firstCounter) == 0 + expect(secondCounter) == 0 + expect(thirdCounter) == 0 + } + + it("should not deallocate if it is unreachable but still has at least one observer") { + let (sourceSignal, sourceObserver) = Signal.pipe() + + var firstCounter = 0 + var secondCounter = 0 + var thirdCounter = 0 + + var disposable: Disposable? + + func run() { + disposable = sourceSignal + .map { value -> Int in + firstCounter += 1 + return value + } + .map { value -> Int in + secondCounter += 1 + return value + } + .map { value -> Int in + thirdCounter += 1 + return value + } + .observe { _ in } + } + + run() + + sourceObserver.send(value: 1) + expect(firstCounter) == 1 + expect(secondCounter) == 1 + expect(thirdCounter) == 1 + + sourceObserver.send(value: 2) + expect(firstCounter) == 2 + expect(secondCounter) == 2 + expect(thirdCounter) == 2 + + disposable?.dispose() + + sourceObserver.send(value: 3) + expect(firstCounter) == 2 + expect(secondCounter) == 2 + expect(thirdCounter) == 2 + } + } + + describe("observe") { + var signal: Signal! + var observer: Signal.Observer! + + var token: NSObject? = nil + weak var weakToken: NSObject? + + func expectTokenNotDeallocated() { + expect(weakToken).toNot(beNil()) + } + + func expectTokenDeallocated() { + expect(weakToken).to(beNil()) + } + + beforeEach { + let (signalTemp, observerTemp) = Signal.pipe() + signal = signalTemp + observer = observerTemp + + token = NSObject() + weakToken = token + + signal.observe { [token = token] _ in + _ = token!.description + } + } + + it("should deallocate observe handler when signal completes") { + expectTokenNotDeallocated() + + observer.send(value: 1) + expectTokenNotDeallocated() + + token = nil + expectTokenNotDeallocated() + + observer.send(value: 2) + expectTokenNotDeallocated() + + observer.sendCompleted() + expectTokenDeallocated() + } + + it("should deallocate observe handler when signal fails") { + expectTokenNotDeallocated() + + observer.send(value: 1) + expectTokenNotDeallocated() + + token = nil + expectTokenNotDeallocated() + + observer.send(value: 2) + expectTokenNotDeallocated() + + observer.send(error: .default) + expectTokenDeallocated() + } + } + } +} + +private extension Signal { + func testTransform() -> Signal { + return Signal { observer in + return self.observe(observer.action) + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift new file mode 100644 index 0000000..260ae6d --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerLiftingSpec.swift @@ -0,0 +1,2011 @@ +// +// SignalProducerLiftingSpec.swift +// ReactiveSwift +// +// Created by Neil Pankey on 6/14/15. +// Copyright © 2015 GitHub. All rights reserved. +// + +import Dispatch +import Foundation + +import Result +import Nimble +import Quick +@testable import ReactiveSwift + +class SignalProducerLiftingSpec: QuickSpec { + override func spec() { + describe("map") { + it("should transform the values of the signal") { + let (producer, observer) = SignalProducer.pipe() + let mappedProducer = producer.map { String($0 + 1) } + + var lastValue: String? + + mappedProducer.startWithValues { + lastValue = $0 + return + } + + expect(lastValue).to(beNil()) + + observer.send(value: 0) + expect(lastValue) == "1" + + observer.send(value: 1) + expect(lastValue) == "2" + } + } + + describe("mapError") { + it("should transform the errors of the signal") { + let (producer, observer) = SignalProducer.pipe() + let producerError = NSError(domain: "com.reactivecocoa.errordomain", code: 100, userInfo: nil) + var error: NSError? + + producer + .mapError { _ in producerError } + .startWithFailed { error = $0 } + + expect(error).to(beNil()) + + observer.send(error: TestError.default) + expect(error) == producerError + } + } + + describe("lazyMap") { + + describe("with a scheduled binding") { + var token: Lifetime.Token! + var lifetime: Lifetime! + var destination: [String] = [] + var tupleProducer: SignalProducer<(character: String, other: Int), NoError>! + var tupleObserver: Signal<(character: String, other: Int), NoError>.Observer! + var theLens: SignalProducer! + var getterCounter: Int = 0 + var lensScheduler: TestScheduler! + var targetScheduler: TestScheduler! + var target: BindingTarget! + + beforeEach { + destination = [] + token = Lifetime.Token() + lifetime = Lifetime(token) + + let (producer, observer) = SignalProducer<(character: String, other: Int), NoError>.pipe() + tupleProducer = producer + tupleObserver = observer + + lensScheduler = TestScheduler() + targetScheduler = TestScheduler() + + getterCounter = 0 + theLens = tupleProducer.lazyMap(on: lensScheduler) { (tuple: (character: String, other: Int)) -> String in + getterCounter += 1 + return tuple.character + } + + target = BindingTarget(on: targetScheduler, lifetime: lifetime) { + destination.append($0) + } + + target <~ theLens + } + + it("should not propagate values until scheduled") { + // Send a value along + tupleObserver.send(value: (character: "🎃", other: 42)) + + // The destination should not change value, and the getter + // should not have evaluated yet, as neither has been scheduled + expect(destination) == [] + expect(getterCounter) == 0 + + // Advance both schedulers + lensScheduler.advance() + targetScheduler.advance() + + // The destination receives the previously-sent value, and the + // getter obviously evaluated + expect(destination) == ["🎃"] + expect(getterCounter) == 1 + } + + it("should evaluate the getter only when scheduled") { + // Send a value along + tupleObserver.send(value: (character: "🎃", other: 42)) + + // The destination should not change value, and the getter + // should not have evaluated yet, as neither has been scheduled + expect(destination) == [] + expect(getterCounter) == 0 + + // When the getter's scheduler advances, the getter should + // be evaluated, but the destination still shouldn't accept + // the new value + lensScheduler.advance() + expect(getterCounter) == 1 + expect(destination) == [] + + // Sending other values along shouldn't evaluate the getter + tupleObserver.send(value: (character: "😾", other: 42)) + tupleObserver.send(value: (character: "🍬", other: 13)) + tupleObserver.send(value: (character: "👻", other: 17)) + expect(getterCounter) == 1 + expect(destination) == [] + + // Push the scheduler along for the lens, and the getter + // should evaluate + lensScheduler.advance() + expect(getterCounter) == 2 + + // ...but the destination still won't receive the value + expect(destination) == [] + + // Finally, pushing the target scheduler along will + // propagate only the first and last values + targetScheduler.advance() + expect(getterCounter) == 2 + expect(destination) == ["🎃", "👻"] + } + } + + it("should return the result of the getter on each value change") { + let initialValue = (character: "🎃", other: 42) + let nextValue = (character: "😾", other: 74) + + let scheduler = TestScheduler() + let (tupleProducer, tupleObserver) = SignalProducer<(character: String, other: Int), NoError>.pipe() + let theLens: SignalProducer = tupleProducer.lazyMap(on: scheduler) { $0.character } + + var output: [String] = [] + theLens.startWithValues { value in + output.append(value) + } + + tupleObserver.send(value: initialValue) + + scheduler.advance() + expect(output) == ["🎃"] + + tupleObserver.send(value: nextValue) + + scheduler.advance() + expect(output) == ["🎃", "😾"] + } + + it("should evaluate its getter lazily") { + let initialValue = (character: "🎃", other: 42) + let nextValue = (character: "😾", other: 74) + + let (tupleProducer, tupleObserver) = SignalProducer<(character: String, other: Int), NoError>.pipe() + + let scheduler = TestScheduler() + var output: [String] = [] + var getterEvaluated = false + let theLens: SignalProducer = tupleProducer.lazyMap(on: scheduler) { (tuple: (character: String, other: Int)) -> String in + getterEvaluated = true + return tuple.character + } + + // No surprise here, but the getter should not be evaluated + // since the underlying producer has yet to be started. + expect(getterEvaluated).to(beFalse()) + + // Similarly, sending values won't cause anything to happen. + tupleObserver.send(value: initialValue) + expect(output).to(beEmpty()) + expect(getterEvaluated).to(beFalse()) + + // Start the signal, appending future values to the output array + theLens.startWithValues { value in output.append(value) } + + // Even when the producer has yet to start, there should be no + // evaluation of the getter + expect(getterEvaluated).to(beFalse()) + + // Now we send a value through the producer + tupleObserver.send(value: initialValue) + + // The getter should still not be evaluated, as it has not yet + // been scheduled + expect(getterEvaluated).to(beFalse()) + + // Now advance the scheduler to allow things to proceed + scheduler.advance() + + // Now the getter gets evaluated, and the output is what we'd + // expect + expect(getterEvaluated).to(beTrue()) + expect(output) == ["🎃"] + + // And now subsequent values continue to come through + tupleObserver.send(value: nextValue) + scheduler.advance() + expect(output) == ["🎃", "😾"] + } + + it("should evaluate its getter lazily on a different scheduler") { + let initialValue = (character: "🎃", other: 42) + let nextValue = (character: "😾", other: 74) + + let (tupleProducer, tupleObserver) = SignalProducer<(character: String, other: Int), NoError>.pipe() + + let scheduler = TestScheduler() + + var output: [String] = [] + var getterEvaluated = false + let theLens: SignalProducer = tupleProducer.lazyMap(on: scheduler) { (tuple: (character: String, other: Int)) -> String in + getterEvaluated = true + return tuple.character + } + + // No surprise here, but the getter should not be evaluated + // since the underlying producer has yet to be started. + expect(getterEvaluated).to(beFalse()) + + // Similarly, sending values won't cause anything to happen. + tupleObserver.send(value: initialValue) + expect(output).to(beEmpty()) + expect(getterEvaluated).to(beFalse()) + + // Start the signal, appending future values to the output array + theLens.startWithValues { value in output.append(value) } + + // Even when the producer has yet to start, there should be no + // evaluation of the getter + expect(getterEvaluated).to(beFalse()) + + tupleObserver.send(value: initialValue) + + // The getter should still not get evaluated, as it was not yet + // scheduled + expect(getterEvaluated).to(beFalse()) + expect(output).to(beEmpty()) + + scheduler.run() + + // Now that the scheduler's run, things can continue to move forward + expect(getterEvaluated).to(beTrue()) + expect(output) == ["🎃"] + + tupleObserver.send(value: nextValue) + + // Subsequent values should still be held up by the scheduler + // not getting run + expect(output) == ["🎃"] + + scheduler.run() + + expect(output) == ["🎃", "😾"] + } + + it("should evaluate its getter lazily on the scheduler we specify") { + let initialValue = (character: "🎃", other: 42) + + let (tupleProducer, tupleObserver) = SignalProducer<(character: String, other: Int), NoError>.pipe() + + let labelKey = DispatchSpecificKey() + let testQueue = DispatchQueue(label: "test queue", target: .main) + testQueue.setSpecific(key: labelKey, value: "test queue") + testQueue.suspend() + let testScheduler = QueueScheduler(internalQueue: testQueue) + + var output: [String] = [] + var isOnTestQueue = false + let theLens = tupleProducer.lazyMap(on: testScheduler) { (tuple: (character: String, other: Int)) -> String in + isOnTestQueue = DispatchQueue.getSpecific(key: labelKey) == "test queue" + return tuple.character + } + + // Start the signal, appending future values to the output array + theLens.startWithValues { value in output.append(value) } + testQueue.resume() + + expect(isOnTestQueue).to(beFalse()) + expect(output).to(beEmpty()) + + tupleObserver.send(value: initialValue) + + expect(isOnTestQueue).toEventually(beTrue()) + expect(output).toEventually(equal(["🎃"])) + } + } + + describe("filter") { + it("should omit values from the producer") { + let (producer, observer) = SignalProducer.pipe() + let mappedProducer = producer.filter { $0 % 2 == 0 } + + var lastValue: Int? + + mappedProducer.startWithValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: 0) + expect(lastValue) == 0 + + observer.send(value: 1) + expect(lastValue) == 0 + + observer.send(value: 2) + expect(lastValue) == 2 + } + } + + describe("skipNil") { + it("should forward only non-nil values") { + let (producer, observer) = SignalProducer.pipe() + let mappedProducer = producer.skipNil() + + var lastValue: Int? + + mappedProducer.startWithValues { lastValue = $0 } + expect(lastValue).to(beNil()) + + observer.send(value: nil) + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: nil) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + } + } + + describe("scan(_:_:)") { + it("should incrementally accumulate a value") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.scan("", +) + + var lastValue: String? + + producer.startWithValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: "a") + expect(lastValue) == "a" + + observer.send(value: "bb") + expect(lastValue) == "abb" + } + } + + describe("scan(into:_:)") { + it("should incrementally accumulate a value") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.scan(into: "") { $0 += $1 } + + var lastValue: String? + + producer.startWithValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: "a") + expect(lastValue) == "a" + + observer.send(value: "bb") + expect(lastValue) == "abb" + } + } + + describe("reduce(_:_:)") { + it("should accumulate one value") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.reduce(1, +) + + var lastValue: Int? + var completed = false + + producer.start { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue).to(beNil()) + + expect(completed) == false + observer.sendCompleted() + expect(completed) == true + + expect(lastValue) == 4 + } + + it("should send the initial value if none are received") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.reduce(1, +) + + var lastValue: Int? + var completed = false + + producer.start { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + expect(lastValue).to(beNil()) + expect(completed) == false + + observer.sendCompleted() + + expect(lastValue) == 1 + expect(completed) == true + } + } + + describe("reduce(into:_:)") { + it("should accumulate one value") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.reduce(into: 1) { $0 += $1 } + + var lastValue: Int? + var completed = false + + producer.start { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue).to(beNil()) + + expect(completed) == false + observer.sendCompleted() + expect(completed) == true + + expect(lastValue) == 4 + } + + it("should send the initial value if none are received") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.reduce(into: 1) { $0 += $1 } + + var lastValue: Int? + var completed = false + + producer.start { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + expect(lastValue).to(beNil()) + expect(completed) == false + + observer.sendCompleted() + + expect(lastValue) == 1 + expect(completed) == true + } + } + + describe("skip") { + it("should skip initial values") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.skip(first: 1) + + var lastValue: Int? + producer.startWithValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue) == 2 + } + + it("should not skip any values when 0") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.skip(first: 0) + + var lastValue: Int? + producer.startWithValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + } + } + + describe("skipRepeats") { + it("should skip duplicate Equatable values") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.skipRepeats() + + var values: [Bool] = [] + producer.startWithValues { values.append($0) } + + expect(values) == [] + + observer.send(value: true) + expect(values) == [ true ] + + observer.send(value: true) + expect(values) == [ true ] + + observer.send(value: false) + expect(values) == [ true, false ] + + observer.send(value: true) + expect(values) == [ true, false, true ] + } + + it("should skip values according to a predicate") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.skipRepeats { $0.characters.count == $1.characters.count } + + var values: [String] = [] + producer.startWithValues { values.append($0) } + + expect(values) == [] + + observer.send(value: "a") + expect(values) == [ "a" ] + + observer.send(value: "b") + expect(values) == [ "a" ] + + observer.send(value: "cc") + expect(values) == [ "a", "cc" ] + + observer.send(value: "d") + expect(values) == [ "a", "cc", "d" ] + } + } + + describe("skipWhile") { + var producer: SignalProducer! + var observer: Signal.Observer! + + var lastValue: Int? + + beforeEach { + let (baseProducer, incomingObserver) = SignalProducer.pipe() + + producer = baseProducer.skip { $0 < 2 } + observer = incomingObserver + lastValue = nil + + producer.startWithValues { lastValue = $0 } + } + + it("should skip while the predicate is true") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue) == 2 + + observer.send(value: 0) + expect(lastValue) == 0 + } + + it("should not skip any values when the predicate starts false") { + expect(lastValue).to(beNil()) + + observer.send(value: 3) + expect(lastValue) == 3 + + observer.send(value: 1) + expect(lastValue) == 1 + } + } + + describe("skipUntil") { + var producer: SignalProducer! + var observer: Signal.Observer! + var triggerObserver: Signal<(), NoError>.Observer! + + var lastValue: Int? = nil + + beforeEach { + let (baseProducer, baseIncomingObserver) = SignalProducer.pipe() + let (triggerProducer, incomingTriggerObserver) = SignalProducer<(), NoError>.pipe() + + producer = baseProducer.skip(until: triggerProducer) + observer = baseIncomingObserver + triggerObserver = incomingTriggerObserver + + lastValue = nil + + producer.start { event in + switch event { + case let .value(value): + lastValue = value + case .failed, .completed, .interrupted: + break + } + } + } + + it("should skip values until the trigger fires") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue).to(beNil()) + + triggerObserver.send(value: ()) + observer.send(value: 0) + expect(lastValue) == 0 + } + + it("should skip values until the trigger completes") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue).to(beNil()) + + triggerObserver.sendCompleted() + observer.send(value: 0) + expect(lastValue) == 0 + } + } + + describe("take") { + it("should take initial values") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.take(first: 2) + + var lastValue: Int? + var completed = false + producer.start { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + expect(lastValue).to(beNil()) + expect(completed) == false + + observer.send(value: 1) + expect(lastValue) == 1 + expect(completed) == false + + observer.send(value: 2) + expect(lastValue) == 2 + expect(completed) == true + } + + it("should complete immediately after taking given number of values") { + let numbers = [ 1, 2, 4, 4, 5 ] + let testScheduler = TestScheduler() + + let producer: SignalProducer = SignalProducer { observer, _ in + // workaround `Class declaration cannot close over value 'observer' defined in outer scope` + let observer = observer + + testScheduler.schedule { + for number in numbers { + observer.send(value: number) + } + } + } + + var completed = false + + producer + .take(first: numbers.count) + .startWithCompleted { completed = true } + + expect(completed) == false + testScheduler.run() + expect(completed) == true + } + + it("should interrupt when 0") { + let numbers = [ 1, 2, 4, 4, 5 ] + let testScheduler = TestScheduler() + + let producer: SignalProducer = SignalProducer { observer, _ in + // workaround `Class declaration cannot close over value 'observer' defined in outer scope` + let observer = observer + + testScheduler.schedule { + for number in numbers { + observer.send(value: number) + } + } + } + + var result: [Int] = [] + var interrupted = false + + producer + .take(first: 0) + .start { event in + switch event { + case let .value(number): + result.append(number) + case .interrupted: + interrupted = true + case .failed, .completed: + break + } + } + + expect(interrupted) == true + + testScheduler.run() + expect(result).to(beEmpty()) + } + } + + describe("collect") { + it("should collect all values") { + let (original, observer) = SignalProducer.pipe() + let producer = original.collect() + let expectedResult = [ 1, 2, 3 ] + + var result: [Int]? + + producer.startWithValues { value in + expect(result).to(beNil()) + result = value + } + + for number in expectedResult { + observer.send(value: number) + } + + expect(result).to(beNil()) + observer.sendCompleted() + expect(result) == expectedResult + } + + it("should complete with an empty array if there are no values") { + let (original, observer) = SignalProducer.pipe() + let producer = original.collect() + + var result: [Int]? + + producer.startWithValues { result = $0 } + + expect(result).to(beNil()) + observer.sendCompleted() + expect(result) == [] + } + + it("should forward errors") { + let (original, observer) = SignalProducer.pipe() + let producer = original.collect() + + var error: TestError? + + producer.startWithFailed { error = $0 } + + expect(error).to(beNil()) + observer.send(error: .default) + expect(error) == TestError.default + } + + it("should collect an exact count of values") { + let (original, observer) = SignalProducer.pipe() + + let producer = original.collect(count: 3) + + var observedValues: [[Int]] = [] + + producer.startWithValues { value in + observedValues.append(value) + } + + var expectation: [[Int]] = [] + + for i in 1...7 { + + observer.send(value: i) + + if i % 3 == 0 { + expectation.append([Int]((i - 2)...i)) + expect(observedValues._bridgeToObjectiveC()) == expectation._bridgeToObjectiveC() + } else { + expect(observedValues._bridgeToObjectiveC()) == expectation._bridgeToObjectiveC() + } + } + + observer.sendCompleted() + + expectation.append([7]) + expect(observedValues._bridgeToObjectiveC()) == expectation._bridgeToObjectiveC() + } + + it("should collect values until it matches a certain value") { + let (original, observer) = SignalProducer.pipe() + + let producer = original.collect { _, value in value != 5 } + + var expectedValues = [ + [5, 5], + [42, 5] + ] + + producer.startWithValues { value in + expect(value) == expectedValues.removeFirst() + } + + producer.startWithCompleted { + expect(expectedValues._bridgeToObjectiveC()) == []._bridgeToObjectiveC() + } + + expectedValues + .flatMap { $0 } + .forEach(observer.send(value:)) + + observer.sendCompleted() + } + + it("should collect values until it matches a certain condition on values") { + let (original, observer) = SignalProducer.pipe() + + let producer = original.collect { values in values.reduce(0, +) == 10 } + + var expectedValues = [ + [1, 2, 3, 4], + [5, 6, 7, 8, 9] + ] + + producer.startWithValues { value in + expect(value) == expectedValues.removeFirst() + } + + producer.startWithCompleted { + expect(expectedValues._bridgeToObjectiveC()) == []._bridgeToObjectiveC() + } + + expectedValues + .flatMap { $0 } + .forEach(observer.send(value:)) + + observer.sendCompleted() + } + + } + + describe("takeUntil") { + var producer: SignalProducer! + var observer: Signal.Observer! + var triggerObserver: Signal<(), NoError>.Observer! + + var lastValue: Int? = nil + var completed: Bool = false + + beforeEach { + let (baseProducer, baseIncomingObserver) = SignalProducer.pipe() + let (triggerProducer, incomingTriggerObserver) = SignalProducer<(), NoError>.pipe() + + producer = baseProducer.take(until: triggerProducer) + observer = baseIncomingObserver + triggerObserver = incomingTriggerObserver + + lastValue = nil + completed = false + + producer.start { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + } + + it("should take values until the trigger fires") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + + expect(completed) == false + triggerObserver.send(value: ()) + expect(completed) == true + } + + it("should take values until the trigger completes") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + + expect(completed) == false + triggerObserver.sendCompleted() + expect(completed) == true + } + + it("should complete if the trigger fires immediately") { + expect(lastValue).to(beNil()) + expect(completed) == false + + triggerObserver.send(value: ()) + + expect(completed) == true + expect(lastValue).to(beNil()) + } + } + + describe("takeUntilReplacement") { + var producer: SignalProducer! + var observer: Signal.Observer! + var replacementObserver: Signal.Observer! + + var lastValue: Int? = nil + var completed: Bool = false + + beforeEach { + let (baseProducer, incomingObserver) = SignalProducer.pipe() + let (replacementProducer, incomingReplacementObserver) = SignalProducer.pipe() + + producer = baseProducer.take(untilReplacement: replacementProducer) + observer = incomingObserver + replacementObserver = incomingReplacementObserver + + lastValue = nil + completed = false + + producer.start { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + } + + it("should take values from the original then the replacement") { + expect(lastValue).to(beNil()) + expect(completed) == false + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + + replacementObserver.send(value: 3) + + expect(lastValue) == 3 + expect(completed) == false + + observer.send(value: 4) + + expect(lastValue) == 3 + expect(completed) == false + + replacementObserver.send(value: 5) + expect(lastValue) == 5 + + expect(completed) == false + replacementObserver.sendCompleted() + expect(completed) == true + } + } + + describe("takeWhile") { + var producer: SignalProducer! + var observer: Signal.Observer! + + beforeEach { + let (baseProducer, incomingObserver) = SignalProducer.pipe() + producer = baseProducer.take { $0 <= 4 } + observer = incomingObserver + } + + it("should take while the predicate is true") { + var latestValue: Int! + var completed = false + + producer.start { event in + switch event { + case let .value(value): + latestValue = value + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + for value in -1...4 { + observer.send(value: value) + expect(latestValue) == value + expect(completed) == false + } + + observer.send(value: 5) + expect(latestValue) == 4 + expect(completed) == true + } + + it("should complete if the predicate starts false") { + var latestValue: Int? + var completed = false + + producer.start { event in + switch event { + case let .value(value): + latestValue = value + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + observer.send(value: 5) + expect(latestValue).to(beNil()) + expect(completed) == true + } + } + + describe("observeOn") { + it("should send events on the given scheduler") { + let testScheduler = TestScheduler() + let (producer, observer) = SignalProducer.pipe() + + var result: [Int] = [] + + producer + .observe(on: testScheduler) + .startWithValues { result.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + expect(result).to(beEmpty()) + + testScheduler.run() + expect(result) == [ 1, 2 ] + } + } + + describe("delay") { + it("should send events on the given scheduler after the interval") { + let testScheduler = TestScheduler() + let producer: SignalProducer = SignalProducer { observer, _ in + testScheduler.schedule { + observer.send(value: 1) + } + testScheduler.schedule(after: .seconds(5)) { + observer.send(value: 2) + observer.sendCompleted() + } + } + + var result: [Int] = [] + var completed = false + + producer + .delay(10, on: testScheduler) + .start { event in + switch event { + case let .value(number): + result.append(number) + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + testScheduler.advance(by: .seconds(4)) // send initial value + expect(result).to(beEmpty()) + + testScheduler.advance(by: .seconds(10)) // send second value and receive first + expect(result) == [ 1 ] + expect(completed) == false + + testScheduler.advance(by: .seconds(10)) // send second value and receive first + expect(result) == [ 1, 2 ] + expect(completed) == true + } + + it("should schedule errors immediately") { + let testScheduler = TestScheduler() + let producer: SignalProducer = SignalProducer { observer, _ in + // workaround `Class declaration cannot close over value 'observer' defined in outer scope` + let observer = observer + + testScheduler.schedule { + observer.send(error: TestError.default) + } + } + + var errored = false + + producer + .delay(10, on: testScheduler) + .startWithFailed { _ in errored = true } + + testScheduler.advance() + expect(errored) == true + } + } + + describe("throttle") { + var scheduler: TestScheduler! + var observer: Signal.Observer! + var producer: SignalProducer! + + beforeEach { + scheduler = TestScheduler() + + let (baseProducer, baseObserver) = SignalProducer.pipe() + observer = baseObserver + + producer = baseProducer.throttle(1, on: scheduler) + } + + it("should send values on the given scheduler at no less than the interval") { + var values: [Int] = [] + producer.startWithValues { value in + values.append(value) + } + + expect(values) == [] + + observer.send(value: 0) + expect(values) == [] + + scheduler.advance() + expect(values) == [ 0 ] + + observer.send(value: 1) + observer.send(value: 2) + expect(values) == [ 0 ] + + scheduler.advance(by: .milliseconds(1500)) + expect(values) == [ 0, 2 ] + + scheduler.advance(by: .seconds(3)) + expect(values) == [ 0, 2 ] + + observer.send(value: 3) + expect(values) == [ 0, 2 ] + + scheduler.advance() + expect(values) == [ 0, 2, 3 ] + + observer.send(value: 4) + observer.send(value: 5) + scheduler.advance() + expect(values) == [ 0, 2, 3 ] + + scheduler.rewind(by: .seconds(2)) + expect(values) == [ 0, 2, 3 ] + + observer.send(value: 6) + scheduler.advance() + expect(values) == [ 0, 2, 3, 6 ] + + observer.send(value: 7) + observer.send(value: 8) + scheduler.advance() + expect(values) == [ 0, 2, 3, 6 ] + + scheduler.run() + expect(values) == [ 0, 2, 3, 6, 8 ] + } + + it("should schedule completion immediately") { + var values: [Int] = [] + var completed = false + + producer.start { event in + switch event { + case let .value(value): + values.append(value) + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + observer.send(value: 0) + scheduler.advance() + expect(values) == [ 0 ] + + observer.send(value: 1) + observer.sendCompleted() + expect(completed) == false + + scheduler.run() + expect(values) == [ 0 ] + expect(completed) == true + } + } + + describe("sampleWith") { + var sampledProducer: SignalProducer<(Int, String), NoError>! + var observer: Signal.Observer! + var samplerObserver: Signal.Observer! + + beforeEach { + let (producer, incomingObserver) = SignalProducer.pipe() + let (sampler, incomingSamplerObserver) = SignalProducer.pipe() + sampledProducer = producer.sample(with: sampler) + observer = incomingObserver + samplerObserver = incomingSamplerObserver + } + + it("should forward the latest value when the sampler fires") { + var result: [String] = [] + sampledProducer.startWithValues { result.append("\($0.0)\($0.1)") } + + observer.send(value: 1) + observer.send(value: 2) + samplerObserver.send(value: "a") + expect(result) == [ "2a" ] + } + + it("should do nothing if sampler fires before signal receives value") { + var result: [String] = [] + sampledProducer.startWithValues { result.append("\($0.0)\($0.1)") } + + samplerObserver.send(value: "a") + expect(result).to(beEmpty()) + } + + it("should send lates value multiple times when sampler fires multiple times") { + var result: [String] = [] + sampledProducer.startWithValues { result.append("\($0.0)\($0.1)") } + + observer.send(value: 1) + samplerObserver.send(value: "a") + samplerObserver.send(value: "b") + expect(result) == [ "1a", "1b" ] + } + + it("should complete when both inputs have completed") { + var completed = false + sampledProducer.startWithCompleted { completed = true } + + observer.sendCompleted() + expect(completed) == false + + samplerObserver.sendCompleted() + expect(completed) == true + } + + it("should emit an initial value if the sampler is a synchronous SignalProducer") { + let producer = SignalProducer([1]) + let sampler = SignalProducer(value: "a") + + let result = producer.sample(with: sampler) + + var valueReceived: String? + result.startWithValues { valueReceived = "\($0.0)\($0.1)" } + + expect(valueReceived) == "1a" + } + } + + describe("sampleOn") { + var sampledProducer: SignalProducer! + var observer: Signal.Observer! + var samplerObserver: Signal<(), NoError>.Observer! + + beforeEach { + let (producer, incomingObserver) = SignalProducer.pipe() + let (sampler, incomingSamplerObserver) = SignalProducer<(), NoError>.pipe() + sampledProducer = producer.sample(on: sampler) + observer = incomingObserver + samplerObserver = incomingSamplerObserver + } + + it("should forward the latest value when the sampler fires") { + var result: [Int] = [] + sampledProducer.startWithValues { result.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + samplerObserver.send(value: ()) + expect(result) == [ 2 ] + } + + it("should do nothing if sampler fires before signal receives value") { + var result: [Int] = [] + sampledProducer.startWithValues { result.append($0) } + + samplerObserver.send(value: ()) + expect(result).to(beEmpty()) + } + + it("should send lates value multiple times when sampler fires multiple times") { + var result: [Int] = [] + sampledProducer.startWithValues { result.append($0) } + + observer.send(value: 1) + samplerObserver.send(value: ()) + samplerObserver.send(value: ()) + expect(result) == [ 1, 1 ] + } + + it("should complete when both inputs have completed") { + var completed = false + sampledProducer.startWithCompleted { completed = true } + + observer.sendCompleted() + expect(completed) == false + + samplerObserver.sendCompleted() + expect(completed) == true + } + + it("should emit an initial value if the sampler is a synchronous SignalProducer") { + let producer = SignalProducer([1]) + let sampler = SignalProducer<(), NoError>(value: ()) + + let result = producer.sample(on: sampler) + + var valueReceived: Int? + result.startWithValues { valueReceived = $0 } + + expect(valueReceived) == 1 + } + + describe("memory") { + class Payload { + let action: () -> Void + + init(onDeinit action: @escaping () -> Void) { + self.action = action + } + + deinit { + action() + } + } + + var sampledProducer: SignalProducer! + var observer: Signal.Observer! + + beforeEach { + let (producer, incomingObserver) = SignalProducer.pipe() + let (sampler, _) = Signal<(), NoError>.pipe() + sampledProducer = producer.sample(on: sampler) + observer = incomingObserver + } + + it("should free payload when interrupted after complete of incoming producer") { + var payloadFreed = false + + let disposable = sampledProducer.start() + + observer.send(value: Payload { payloadFreed = true }) + observer.sendCompleted() + + expect(payloadFreed) == false + + disposable.dispose() + expect(payloadFreed) == true + } + } + } + + describe("withLatest(from: signal)") { + var withLatestProducer: SignalProducer<(Int, String), NoError>! + var observer: Signal.Observer! + var sampleeObserver: Signal.Observer! + + beforeEach { + let (producer, incomingObserver) = SignalProducer.pipe() + let (samplee, incomingSampleeObserver) = Signal.pipe() + withLatestProducer = producer.withLatest(from: samplee) + observer = incomingObserver + sampleeObserver = incomingSampleeObserver + } + + it("should forward the latest value when the receiver fires") { + var result: [String] = [] + withLatestProducer.startWithValues { result.append("\($0.0)\($0.1)") } + + sampleeObserver.send(value: "a") + sampleeObserver.send(value: "b") + observer.send(value: 1) + expect(result) == [ "1b" ] + } + + it("should do nothing if receiver fires before samplee sends value") { + var result: [String] = [] + withLatestProducer.startWithValues { result.append("\($0.0)\($0.1)") } + + observer.send(value: 1) + expect(result).to(beEmpty()) + } + + it("should send latest value with samplee value multiple times when receiver fires multiple times") { + var result: [String] = [] + withLatestProducer.startWithValues { result.append("\($0.0)\($0.1)") } + + sampleeObserver.send(value: "a") + observer.send(value: 1) + observer.send(value: 2) + expect(result) == [ "1a", "2a" ] + } + + it("should complete when receiver has completed") { + var completed = false + withLatestProducer.startWithCompleted { completed = true } + + observer.sendCompleted() + expect(completed) == true + } + + it("should not affect when samplee has completed") { + var event: Signal<(Int, String), NoError>.Event? = nil + withLatestProducer.start { event = $0 } + + sampleeObserver.sendCompleted() + expect(event).to(beNil()) + } + + it("should not affect when samplee has interrupted") { + var event: Signal<(Int, String), NoError>.Event? = nil + withLatestProducer.start { event = $0 } + + sampleeObserver.sendInterrupted() + expect(event).to(beNil()) + } + } + + describe("withLatest(from: producer)") { + var withLatestProducer: SignalProducer<(Int, String), NoError>! + var observer: Signal.Observer! + var sampleeObserver: Signal.Observer! + + beforeEach { + let (producer, incomingObserver) = SignalProducer.pipe() + let (samplee, incomingSampleeObserver) = SignalProducer.pipe() + withLatestProducer = producer.withLatest(from: samplee) + observer = incomingObserver + sampleeObserver = incomingSampleeObserver + } + + it("should forward the latest value when the receiver fires") { + var result: [String] = [] + withLatestProducer.startWithValues { result.append("\($0.0)\($0.1)") } + + sampleeObserver.send(value: "a") + sampleeObserver.send(value: "b") + observer.send(value: 1) + expect(result) == [ "1b" ] + } + + it("should do nothing if receiver fires before samplee sends value") { + var result: [String] = [] + withLatestProducer.startWithValues { result.append("\($0.0)\($0.1)") } + + observer.send(value: 1) + expect(result).to(beEmpty()) + } + + it("should send latest value with samplee value multiple times when receiver fires multiple times") { + var result: [String] = [] + withLatestProducer.startWithValues { result.append("\($0.0)\($0.1)") } + + sampleeObserver.send(value: "a") + observer.send(value: 1) + observer.send(value: 2) + expect(result) == [ "1a", "2a" ] + } + + it("should complete when receiver has completed") { + var completed = false + withLatestProducer.startWithCompleted { completed = true } + + observer.sendCompleted() + expect(completed) == true + } + + it("should not affect when samplee has completed") { + var event: Signal<(Int, String), NoError>.Event? = nil + withLatestProducer.start { event = $0 } + + sampleeObserver.sendCompleted() + expect(event).to(beNil()) + } + + it("should not affect when samplee has interrupted") { + var event: Signal<(Int, String), NoError>.Event? = nil + withLatestProducer.start { event = $0 } + + sampleeObserver.sendInterrupted() + expect(event).to(beNil()) + } + } + + describe("combineLatestWith") { + var combinedProducer: SignalProducer<(Int, Double), NoError>! + var observer: Signal.Observer! + var otherObserver: Signal.Observer! + + beforeEach { + let (producer, incomingObserver) = SignalProducer.pipe() + let (otherSignal, incomingOtherObserver) = SignalProducer.pipe() + combinedProducer = producer.combineLatest(with: otherSignal) + observer = incomingObserver + otherObserver = incomingOtherObserver + } + + it("should forward the latest values from both inputs") { + var latest: (Int, Double)? + combinedProducer.startWithValues { latest = $0 } + + observer.send(value: 1) + expect(latest).to(beNil()) + + // is there a better way to test tuples? + otherObserver.send(value: 1.5) + expect(latest?.0) == 1 + expect(latest?.1) == 1.5 + + observer.send(value: 2) + expect(latest?.0) == 2 + expect(latest?.1) == 1.5 + } + + it("should complete when both inputs have completed") { + var completed = false + combinedProducer.startWithCompleted { completed = true } + + observer.sendCompleted() + expect(completed) == false + + otherObserver.sendCompleted() + expect(completed) == true + } + } + + describe("zipWith") { + var leftObserver: Signal.Observer! + var rightObserver: Signal.Observer! + var zipped: SignalProducer<(Int, String), NoError>! + + beforeEach { + let (leftProducer, incomingLeftObserver) = SignalProducer.pipe() + let (rightProducer, incomingRightObserver) = SignalProducer.pipe() + + leftObserver = incomingLeftObserver + rightObserver = incomingRightObserver + zipped = leftProducer.zip(with: rightProducer) + } + + it("should combine pairs") { + var result: [String] = [] + zipped.startWithValues { result.append("\($0.0)\($0.1)") } + + leftObserver.send(value: 1) + leftObserver.send(value: 2) + expect(result) == [] + + rightObserver.send(value: "foo") + expect(result) == [ "1foo" ] + + leftObserver.send(value: 3) + rightObserver.send(value: "bar") + expect(result) == [ "1foo", "2bar" ] + + rightObserver.send(value: "buzz") + expect(result) == [ "1foo", "2bar", "3buzz" ] + + rightObserver.send(value: "fuzz") + expect(result) == [ "1foo", "2bar", "3buzz" ] + + leftObserver.send(value: 4) + expect(result) == [ "1foo", "2bar", "3buzz", "4fuzz" ] + } + + it("should complete when the shorter signal has completed") { + var result: [String] = [] + var completed = false + + zipped.start { event in + switch event { + case let .value(left, right): + result.append("\(left)\(right)") + case .completed: + completed = true + case .failed, .interrupted: + break + } + } + + expect(completed) == false + + leftObserver.send(value: 0) + leftObserver.sendCompleted() + expect(completed) == false + expect(result) == [] + + rightObserver.send(value: "foo") + expect(completed) == true + expect(result) == [ "0foo" ] + } + } + + describe("materialize") { + it("should reify events from the signal") { + let (producer, observer) = SignalProducer.pipe() + var latestEvent: Signal.Event? + producer + .materialize() + .startWithValues { latestEvent = $0 } + + observer.send(value: 2) + + expect(latestEvent).toNot(beNil()) + if let latestEvent = latestEvent { + switch latestEvent { + case let .value(value): + expect(value) == 2 + case .failed, .completed, .interrupted: + fail() + } + } + + observer.send(error: TestError.default) + if let latestEvent = latestEvent { + switch latestEvent { + case .failed: + break + case .value, .completed, .interrupted: + fail() + } + } + } + } + + describe("dematerialize") { + typealias IntEvent = Signal.Event + var observer: Signal.Observer! + var dematerialized: SignalProducer! + + beforeEach { + let (producer, incomingObserver) = SignalProducer.pipe() + observer = incomingObserver + dematerialized = producer.dematerialize() + } + + it("should send values for Value events") { + var result: [Int] = [] + dematerialized + .assumeNoErrors() + .startWithValues { result.append($0) } + + expect(result).to(beEmpty()) + + observer.send(value: .value(2)) + expect(result) == [ 2 ] + + observer.send(value: .value(4)) + expect(result) == [ 2, 4 ] + } + + it("should error out for Error events") { + var errored = false + dematerialized.startWithFailed { _ in errored = true } + + expect(errored) == false + + observer.send(value: .failed(TestError.default)) + expect(errored) == true + } + + it("should complete early for Completed events") { + var completed = false + dematerialized.startWithCompleted { completed = true } + + expect(completed) == false + observer.send(value: IntEvent.completed) + expect(completed) == true + } + } + + describe("takeLast") { + var observer: Signal.Observer! + var lastThree: SignalProducer! + + beforeEach { + let (producer, incomingObserver) = SignalProducer.pipe() + observer = incomingObserver + lastThree = producer.take(last: 3) + } + + it("should send the last N values upon completion") { + var result: [Int] = [] + lastThree + .assumeNoErrors() + .startWithValues { result.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) + expect(result).to(beEmpty()) + + observer.sendCompleted() + expect(result) == [ 2, 3, 4 ] + } + + it("should send less than N values if not enough were received") { + var result: [Int] = [] + lastThree + .assumeNoErrors() + .startWithValues { result.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + observer.sendCompleted() + expect(result) == [ 1, 2 ] + } + + it("should send nothing when errors") { + var result: [Int] = [] + var errored = false + lastThree.start { event in + switch event { + case let .value(value): + result.append(value) + case .failed: + errored = true + case .completed, .interrupted: + break + } + } + + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + expect(errored) == false + + observer.send(error: TestError.default) + expect(errored) == true + expect(result).to(beEmpty()) + } + } + + describe("timeoutWithError") { + var testScheduler: TestScheduler! + var producer: SignalProducer! + var observer: Signal.Observer! + + beforeEach { + testScheduler = TestScheduler() + let (baseProducer, incomingObserver) = SignalProducer.pipe() + producer = baseProducer.timeout(after: 2, raising: TestError.default, on: testScheduler) + observer = incomingObserver + } + + it("should complete if within the interval") { + var completed = false + var errored = false + producer.start { event in + switch event { + case .completed: + completed = true + case .failed: + errored = true + case .value, .interrupted: + break + } + } + + testScheduler.schedule(after: .seconds(1)) { + observer.sendCompleted() + } + + expect(completed) == false + expect(errored) == false + + testScheduler.run() + expect(completed) == true + expect(errored) == false + } + + it("should error if not completed before the interval has elapsed") { + var completed = false + var errored = false + producer.start { event in + switch event { + case .completed: + completed = true + case .failed: + errored = true + case .value, .interrupted: + break + } + } + + testScheduler.schedule(after: .seconds(3)) { + observer.sendCompleted() + } + + expect(completed) == false + expect(errored) == false + + testScheduler.run() + expect(completed) == false + expect(errored) == true + } + + it("should be available for NoError") { + let producer: SignalProducer = SignalProducer.never + .timeout(after: 2, raising: TestError.default, on: testScheduler) + + _ = producer + } + } + + describe("attempt") { + it("should forward original values upon success") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.attempt { _ in + return .success(()) + } + + var current: Int? + producer + .assumeNoErrors() + .startWithValues { value in + current = value + } + + for value in 1...5 { + observer.send(value: value) + expect(current) == value + } + } + + it("should error if an attempt fails") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.attempt { _ in + return .failure(.default) + } + + var error: TestError? + producer.startWithFailed { err in + error = err + } + + observer.send(value: 42) + expect(error) == TestError.default + } + } + + describe("attemptMap") { + it("should forward mapped values upon success") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.attemptMap { num -> Result in + return .success(num % 2 == 0) + } + + var even: Bool? + producer + .assumeNoErrors() + .startWithValues { value in + even = value + } + + observer.send(value: 1) + expect(even) == false + + observer.send(value: 2) + expect(even) == true + } + + it("should error if a mapping fails") { + let (baseProducer, observer) = SignalProducer.pipe() + let producer = baseProducer.attemptMap { _ -> Result in + return .failure(.default) + } + + var error: TestError? + producer.startWithFailed { err in + error = err + } + + observer.send(value: 42) + expect(error) == TestError.default + } + } + + describe("combinePrevious") { + var observer: Signal.Observer! + let initialValue: Int = 0 + var latestValues: (Int, Int)? + + beforeEach { + latestValues = nil + + let (signal, baseObserver) = SignalProducer.pipe() + observer = baseObserver + signal.combinePrevious(initialValue).startWithValues { latestValues = $0 } + } + + it("should forward the latest value with previous value") { + expect(latestValues).to(beNil()) + + observer.send(value: 1) + expect(latestValues?.0) == initialValue + expect(latestValues?.1) == 1 + + observer.send(value: 2) + expect(latestValues?.0) == 1 + expect(latestValues?.1) == 2 + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerNimbleMatchers.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerNimbleMatchers.swift new file mode 100644 index 0000000..707387f --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerNimbleMatchers.swift @@ -0,0 +1,57 @@ +// +// SignalProducerNimbleMatchers.swift +// ReactiveSwift +// +// Created by Javier Soto on 1/25/15. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +import Foundation + +import ReactiveSwift +import Nimble + +public func sendValue(_ value: T?, sendError: E?, complete: Bool) -> NonNilMatcherFunc> { + return sendValues(value.map { [$0] } ?? [], sendError: sendError, complete: complete) +} + +public func sendValues(_ values: [T], sendError maybeSendError: E?, complete: Bool) -> NonNilMatcherFunc> { + return NonNilMatcherFunc { actualExpression, failureMessage in + precondition(maybeSendError == nil || !complete, "Signals can't both send an error and complete") + + failureMessage.postfixMessage = "Send values \(values). Send error \(String(describing: maybeSendError)). Complete: \(complete)" + let maybeProducer = try actualExpression.evaluate() + + if let signalProducer = maybeProducer { + var sentValues: [T] = [] + var sentError: E? + var signalCompleted = false + + signalProducer.start { event in + switch event { + case let .value(value): + sentValues.append(value) + case .completed: + signalCompleted = true + case let .failed(error): + sentError = error + default: + break + } + } + + if sentValues != values { + return false + } + + if sentError != maybeSendError { + return false + } + + return signalCompleted == complete + } + else { + return false + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerSpec.swift new file mode 100644 index 0000000..5605e54 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalProducerSpec.swift @@ -0,0 +1,2817 @@ +// +// SignalProducerSpec.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2015-01-23. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +import Dispatch +import Foundation + +import Result +import Nimble +import Quick +import ReactiveSwift + +class SignalProducerSpec: QuickSpec { + override func spec() { + describe("init") { + it("should run the handler once per start()") { + var handlerCalledTimes = 0 + let signalProducer = SignalProducer() { observer, lifetime in + handlerCalledTimes += 1 + + return + } + + signalProducer.start() + signalProducer.start() + + expect(handlerCalledTimes) == 2 + } + + it("should not release signal observers when given disposable is disposed") { + var lifetime: Lifetime! + + let producer = SignalProducer { observer, innerLifetime in + lifetime = innerLifetime + + innerLifetime.observeEnded { + // This is necessary to keep the observer long enough to + // even test the memory management. + observer.send(value: 0) + } + } + + weak var objectRetainedByObserver: NSObject? + + var disposable: Disposable! + producer.startWithSignal { signal, interruptHandle in + disposable = interruptHandle + + let object = NSObject() + objectRetainedByObserver = object + signal.observeValues { _ in _ = object } + } + + expect(objectRetainedByObserver).toNot(beNil()) + + disposable.dispose() + expect(objectRetainedByObserver).to(beNil()) + } + + it("should dispose of added disposables upon completion") { + let addedDisposable = AnyDisposable() + var observer: Signal<(), NoError>.Observer! + + let producer = SignalProducer<(), NoError>() { incomingObserver, lifetime in + lifetime.observeEnded(addedDisposable.dispose) + observer = incomingObserver + } + + producer.start() + expect(addedDisposable.isDisposed) == false + + observer.sendCompleted() + expect(addedDisposable.isDisposed) == true + } + + it("should dispose of added disposables upon error") { + let addedDisposable = AnyDisposable() + var observer: Signal<(), TestError>.Observer! + + let producer = SignalProducer<(), TestError>() { incomingObserver, lifetime in + lifetime.observeEnded(addedDisposable.dispose) + observer = incomingObserver + } + + producer.start() + expect(addedDisposable.isDisposed) == false + + observer.send(error: .default) + expect(addedDisposable.isDisposed) == true + } + + it("should dispose of added disposables upon interruption") { + let addedDisposable = AnyDisposable() + var observer: Signal<(), NoError>.Observer! + + let producer = SignalProducer<(), NoError>() { incomingObserver, lifetime in + lifetime.observeEnded(addedDisposable.dispose) + observer = incomingObserver + } + + producer.start() + expect(addedDisposable.isDisposed) == false + + observer.sendInterrupted() + expect(addedDisposable.isDisposed) == true + } + + it("should dispose of added disposables upon start() disposal") { + let addedDisposable = AnyDisposable() + + let producer = SignalProducer<(), TestError>() { _, lifetime in + lifetime.observeEnded(addedDisposable.dispose) + return + } + + let startDisposable = producer.start() + expect(addedDisposable.isDisposed) == false + + startDisposable.dispose() + expect(addedDisposable.isDisposed) == true + } + + it("should deliver the interrupted event with respect to the applied asynchronous operators") { + let scheduler = TestScheduler() + var signalInterrupted = false + var observerInterrupted = false + + let (signal, _) = Signal.pipe() + + SignalProducer(signal) + .observe(on: scheduler) + .on(interrupted: { signalInterrupted = true }) + .startWithInterrupted { observerInterrupted = true } + .dispose() + + expect(signalInterrupted) == false + expect(observerInterrupted) == false + + scheduler.run() + expect(signalInterrupted) == true + expect(observerInterrupted) == true + } + } + + describe("init(signal:)") { + var signal: Signal! + var observer: Signal.Observer! + + beforeEach { + // Cannot directly assign due to compiler crash on Xcode 7.0.1 + let (signalTemp, observerTemp) = Signal.pipe() + signal = signalTemp + observer = observerTemp + } + + it("should emit values then complete") { + let producer = SignalProducer(signal) + + var values: [Int] = [] + var error: TestError? + var completed = false + producer.start { event in + switch event { + case let .value(value): + values.append(value) + case let .failed(err): + error = err + case .completed: + completed = true + default: + break + } + } + + expect(values) == [] + expect(error).to(beNil()) + expect(completed) == false + + observer.send(value: 1) + expect(values) == [ 1 ] + observer.send(value: 2) + observer.send(value: 3) + expect(values) == [ 1, 2, 3 ] + + observer.sendCompleted() + expect(completed) == true + } + + it("should emit error") { + let producer = SignalProducer(signal) + + var error: TestError? + let sentError = TestError.default + + producer.start { event in + switch event { + case let .failed(err): + error = err + default: + break + } + } + + expect(error).to(beNil()) + + observer.send(error: sentError) + expect(error) == sentError + } + } + + describe("init(value:)") { + it("should immediately send the value then complete") { + let producerValue = "StringValue" + let signalProducer = SignalProducer(value: producerValue) + + expect(signalProducer).to(sendValue(producerValue, sendError: nil, complete: true)) + } + } + + describe("init closure overloading") { + it("should be inferred and overloaded without ambiguity") { + let action: () -> String = { "" } + let throwableAction: () throws -> String = { "" } + let resultAction1: () -> Result = { .success("") } + let resultAction2: () -> Result = { .success("") } + let throwableResultAction: () throws -> Result = { .success("") } + + expect(type(of: SignalProducer(action))) == SignalProducer.self + expect(type(of: SignalProducer(action))) == SignalProducer.self + expect(type(of: SignalProducer(action))) == SignalProducer.self + + expect(type(of: SignalProducer(resultAction1))) == SignalProducer.self + expect(type(of: SignalProducer(resultAction2))) == SignalProducer.self + + expect(type(of: SignalProducer(throwableAction))) == SignalProducer.self + expect(type(of: SignalProducer(throwableResultAction))) == SignalProducer, AnyError>.self + } + } + + describe("init(_:) lazy value") { + it("should not evaluate the supplied closure until started") { + var evaluated: Bool = false + func lazyGetter() -> String { + evaluated = true + return "🎃" + } + + let lazyProducer = SignalProducer(lazyGetter) + + expect(evaluated).to(beFalse()) + + expect(lazyProducer).to(sendValue("🎃", sendError: nil, complete: true)) + expect(evaluated).to(beTrue()) + } + } + + describe("init(error:)") { + it("should immediately send the error") { + let producerError = NSError(domain: "com.reactivecocoa.errordomain", code: 4815, userInfo: nil) + let signalProducer = SignalProducer(error: producerError) + + expect(signalProducer).to(sendValue(nil, sendError: producerError, complete: false)) + } + } + + describe("init(result:)") { + it("should immediately send the value then complete") { + let producerValue = "StringValue" + let producerResult = .success(producerValue) as Result + let signalProducer = SignalProducer(result: producerResult) + + expect(signalProducer).to(sendValue(producerValue, sendError: nil, complete: true)) + } + + it("should immediately send the error") { + let producerError = NSError(domain: "com.reactivecocoa.errordomain", code: 4815, userInfo: nil) + let producerResult = .failure(producerError) as Result + let signalProducer = SignalProducer(result: producerResult) + + expect(signalProducer).to(sendValue(nil, sendError: producerError, complete: false)) + } + } + + describe("init(values:)") { + it("should immediately send the sequence of values") { + let sequenceValues = [1, 2, 3] + let signalProducer = SignalProducer(sequenceValues) + + expect(signalProducer).to(sendValues(sequenceValues, sendError: nil, complete: true)) + } + } + + describe("SignalProducer.empty") { + it("should immediately complete") { + let signalProducer = SignalProducer.empty + + expect(signalProducer).to(sendValue(nil, sendError: nil, complete: true)) + } + } + + describe("SignalProducer.never") { + it("should not send any events while still being alive") { + let signalProducer = SignalProducer.never + + var numberOfEvents = 0 + var isDisposed = false + + func scope() -> Disposable { + defer { + expect(numberOfEvents) == 0 + expect(isDisposed) == false + } + return signalProducer.on(disposed: { isDisposed = true }).start { _ in numberOfEvents += 1 } + } + + let d = scope() + expect(numberOfEvents) == 0 + expect(isDisposed) == false + + d.dispose() + expect(numberOfEvents) == 1 + expect(isDisposed) == true + } + + it("should not send any events while still being alive even if the interrupt handle deinitializes") { + let signalProducer = SignalProducer.never + + var numberOfEvents = 0 + var isDisposed = false + + func scope() { + signalProducer.on(disposed: { isDisposed = false }).start { _ in numberOfEvents += 1 } + expect(numberOfEvents) == 0 + expect(isDisposed) == false + } + + scope() + expect(numberOfEvents) == 0 + expect(isDisposed) == false + } + } + + describe("trailing closure") { + it("receives next values") { + let (producer, observer) = SignalProducer.pipe() + + var values = [Int]() + producer.startWithValues { value in + values.append(value) + } + + observer.send(value: 1) + expect(values) == [1] + } + } + + describe("init(_:) lazy result") { + it("should run the operation once per start()") { + var operationRunTimes = 0 + let operation: () -> Result = { + operationRunTimes += 1 + + return .success("OperationValue") + } + + SignalProducer(operation).start() + SignalProducer(operation).start() + + expect(operationRunTimes) == 2 + } + + it("should send the value then complete") { + let operationReturnValue = "OperationValue" + let operation: () -> Result = { + return .success(operationReturnValue) + } + + let signalProducer = SignalProducer(operation) + + expect(signalProducer).to(sendValue(operationReturnValue, sendError: nil, complete: true)) + } + + it("should send the error") { + let operationError = NSError(domain: "com.reactivecocoa.errordomain", code: 4815, userInfo: nil) + let operation: () -> Result = { + return .failure(operationError) + } + + let signalProducer = SignalProducer(operation) + + expect(signalProducer).to(sendValue(nil, sendError: operationError, complete: false)) + } + } + + describe("init(_:) throwable lazy value") { + it("should send a successful value then complete") { + let operationReturnValue = "OperationValue" + + let signalProducer = SignalProducer { () throws -> String in + operationReturnValue + } + + var error: Error? + signalProducer.startWithFailed { + error = $0 + } + + expect(error).to(beNil()) + } + + it("should send the error") { + let operationError = TestError.default + + let signalProducer = SignalProducer { () throws -> String in + throw operationError + } + + var error: TestError? + signalProducer.startWithFailed { + error = $0.error as? TestError + } + + expect(error) == operationError + } + } + + describe("startWithSignal") { + it("should invoke the closure before any effects or events") { + var started = false + var value: Int? + + SignalProducer(value: 42) + .on(started: { + started = true + }, value: { + value = $0 + }) + .startWithSignal { _, _ in + expect(started) == false + expect(value).to(beNil()) + } + + expect(started) == true + expect(value) == 42 + } + + it("should dispose of added disposables if disposed") { + let addedDisposable = AnyDisposable() + var disposable: Disposable! + + let producer = SignalProducer() { _, lifetime in + lifetime.observeEnded(addedDisposable.dispose) + return + } + + producer.startWithSignal { signal, innerDisposable in + signal.observe { _ in } + disposable = innerDisposable + } + + expect(addedDisposable.isDisposed) == false + + disposable.dispose() + expect(addedDisposable.isDisposed) == true + } + + it("should send interrupted if disposed") { + var interrupted = false + var disposable: Disposable! + + SignalProducer(value: 42) + .start(on: TestScheduler()) + .startWithSignal { signal, innerDisposable in + signal.observeInterrupted { + interrupted = true + } + + disposable = innerDisposable + } + + expect(interrupted) == false + + disposable.dispose() + expect(interrupted) == true + } + + it("should release signal observers if disposed") { + weak var objectRetainedByObserver: NSObject? + var disposable: Disposable! + + let producer = SignalProducer.never + producer.startWithSignal { signal, innerDisposable in + let object = NSObject() + objectRetainedByObserver = object + signal.observeValues { _ in _ = object.description } + disposable = innerDisposable + } + + expect(objectRetainedByObserver).toNot(beNil()) + + disposable.dispose() + expect(objectRetainedByObserver).to(beNil()) + } + + it("should not trigger effects if disposed before closure return") { + var started = false + var value: Int? + + SignalProducer(value: 42) + .on(started: { + started = true + }, value: { + value = $0 + }) + .startWithSignal { _, disposable in + expect(started) == false + expect(value).to(beNil()) + + disposable.dispose() + } + + expect(started) == false + expect(value).to(beNil()) + } + + it("should send interrupted if disposed before closure return") { + var interrupted = false + + SignalProducer(value: 42) + .startWithSignal { signal, disposable in + expect(interrupted) == false + + signal.observeInterrupted { + interrupted = true + } + + disposable.dispose() + } + + expect(interrupted) == true + } + + it("should dispose of added disposables upon completion") { + let addedDisposable = AnyDisposable() + var observer: Signal.Observer! + + let producer = SignalProducer() { incomingObserver, lifetime in + lifetime.observeEnded(addedDisposable.dispose) + observer = incomingObserver + } + + producer.start() + expect(addedDisposable.isDisposed) == false + + observer.sendCompleted() + expect(addedDisposable.isDisposed) == true + } + + it("should dispose of added disposables upon error") { + let addedDisposable = AnyDisposable() + var observer: Signal.Observer! + + let producer = SignalProducer() { incomingObserver, lifetime in + lifetime.observeEnded(addedDisposable.dispose) + observer = incomingObserver + } + + producer.start() + expect(addedDisposable.isDisposed) == false + + observer.send(error: .default) + expect(addedDisposable.isDisposed) == true + } + + it("should dispose of the added disposable if the signal is unretained and unobserved upon exiting the scope") { + let addedDisposable = AnyDisposable() + + let producer = SignalProducer { _, lifetime in + lifetime.observeEnded(addedDisposable.dispose) + } + + var started = false + var disposed = false + + producer + .on(started: { started = true }, disposed: { disposed = true }) + .startWithSignal { _, _ in } + + expect(started) == true + expect(disposed) == true + expect(addedDisposable.isDisposed) == true + } + } + + describe("start") { + it("should immediately begin sending events") { + let producer = SignalProducer([1, 2]) + + var values: [Int] = [] + var completed = false + producer.start { event in + switch event { + case let .value(value): + values.append(value) + case .completed: + completed = true + default: + break + } + } + + expect(values) == [1, 2] + expect(completed) == true + } + + it("should send interrupted if disposed") { + let producer = SignalProducer<(), NoError>.never + + var interrupted = false + let disposable = producer.startWithInterrupted { + interrupted = true + } + + expect(interrupted) == false + + disposable.dispose() + expect(interrupted) == true + } + + it("should release observer when disposed") { + weak var objectRetainedByObserver: NSObject? + var disposable: Disposable! + let test = { + let producer = SignalProducer.never + let object = NSObject() + objectRetainedByObserver = object + disposable = producer.startWithValues { _ in _ = object } + } + + test() + expect(objectRetainedByObserver).toNot(beNil()) + + disposable.dispose() + expect(objectRetainedByObserver).to(beNil()) + } + + describe("trailing closure") { + it("receives next values") { + let (producer, observer) = SignalProducer.pipe() + + var values = [Int]() + producer.startWithValues { value in + values.append(value) + } + + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + + observer.sendCompleted() + + expect(values) == [1, 2, 3] + } + + it("receives results") { + let (producer, observer) = SignalProducer.pipe() + + var results: [Result] = [] + producer.startWithResult { results.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(error: .default) + + observer.sendCompleted() + + expect(results).to(haveCount(4)) + expect(results[0].value) == 1 + expect(results[1].value) == 2 + expect(results[2].value) == 3 + expect(results[3].error) == .default + } + } + } + + describe("lift") { + describe("over unary operators") { + it("should invoke transformation once per started signal") { + let baseProducer = SignalProducer([1, 2]) + + var counter = 0 + let transform = { (signal: Signal) -> Signal in + counter += 1 + return signal + } + + let producer = baseProducer.lift(transform) + expect(counter) == 0 + + producer.start() + expect(counter) == 1 + + producer.start() + expect(counter) == 2 + } + + it("should not miss any events") { + let baseProducer = SignalProducer([1, 2, 3, 4]) + + let producer = baseProducer.lift { signal in + return signal.map { $0 * $0 } + } + let result = producer.collect().single() + + expect(result?.value) == [1, 4, 9, 16] + } + } + + describe("over binary operators") { + it("should invoke transformation once per started signal") { + let baseProducer = SignalProducer([1, 2]) + let otherProducer = SignalProducer([3, 4]) + + var counter = 0 + let transform = { (signal: Signal) -> (Signal) -> Signal<(Int, Int), NoError> in + return { otherSignal in + counter += 1 + return Signal.zip(signal, otherSignal) + } + } + + let producer = baseProducer.lift(transform)(otherProducer) + expect(counter) == 0 + + producer.start() + expect(counter) == 1 + + producer.start() + expect(counter) == 2 + } + + it("should not miss any events") { + let baseProducer = SignalProducer([1, 2, 3]) + let otherProducer = SignalProducer([4, 5, 6]) + + let transform = { (signal: Signal) -> (Signal) -> Signal in + return { otherSignal in + return Signal.zip(signal, otherSignal).map { $0.0 + $0.1 } + } + } + + let producer = baseProducer.lift(transform)(otherProducer) + let result = producer.collect().single() + + expect(result?.value) == [5, 7, 9] + } + } + + describe("over binary operators with signal") { + it("should invoke transformation once per started signal") { + let baseProducer = SignalProducer([1, 2]) + let (otherSignal, otherSignalObserver) = Signal.pipe() + + var counter = 0 + let transform = { (signal: Signal) -> (Signal) -> Signal<(Int, Int), NoError> in + return { otherSignal in + counter += 1 + return Signal.zip(signal, otherSignal) + } + } + + let producer = baseProducer.lift(transform)(SignalProducer(otherSignal)) + expect(counter) == 0 + + producer.start() + otherSignalObserver.send(value: 1) + expect(counter) == 1 + + producer.start() + otherSignalObserver.send(value: 2) + expect(counter) == 2 + } + + it("should not miss any events") { + let baseProducer = SignalProducer([ 1, 2, 3 ]) + let (otherSignal, otherSignalObserver) = Signal.pipe() + + let transform = { (signal: Signal) -> (Signal) -> Signal in + return { otherSignal in + return Signal.zip(signal, otherSignal).map { $0.0 + $0.1 } + } + } + + let producer = baseProducer.lift(transform)(SignalProducer(otherSignal)) + var result: [Int] = [] + var completed: Bool = false + + producer.start { event in + switch event { + case .value(let value): result.append(value) + case .completed: completed = true + default: break + } + } + + otherSignalObserver.send(value: 4) + expect(result) == [ 5 ] + + otherSignalObserver.send(value: 5) + expect(result) == [ 5, 7 ] + + otherSignalObserver.send(value: 6) + expect(result) == [ 5, 7, 9 ] + expect(completed) == true + } + } + } + + describe("combineLatest") { + it("should combine the events to one array") { + let (producerA, observerA) = SignalProducer.pipe() + let (producerB, observerB) = SignalProducer.pipe() + + let producer = SignalProducer.combineLatest([producerA, producerB]) + + var values = [[Int]]() + producer.startWithValues { value in + values.append(value) + } + + observerA.send(value: 1) + observerB.send(value: 2) + observerA.send(value: 3) + observerA.sendCompleted() + observerB.sendCompleted() + + expect(values._bridgeToObjectiveC()) == [[1, 2], [3, 2]] + } + + it("should start signal producers in order as defined") { + var ids = [Int]() + let createProducer = { (id: Int) -> SignalProducer in + return SignalProducer { observer, lifetime in + ids.append(id) + + observer.send(value: id) + observer.sendCompleted() + } + } + + let producerA = createProducer(1) + let producerB = createProducer(2) + + let producer = SignalProducer.combineLatest([producerA, producerB]) + + var values = [[Int]]() + producer.startWithValues { value in + values.append(value) + } + + expect(ids) == [1, 2] + expect(values._bridgeToObjectiveC()) == [[1, 2]]._bridgeToObjectiveC() + } + } + + describe("zip") { + it("should zip the events to one array") { + let producerA = SignalProducer([ 1, 2 ]) + let producerB = SignalProducer([ 3, 4 ]) + + let producer = SignalProducer.zip([producerA, producerB]) + let result = producer.collect().single() + + expect(result?.value.map { $0._bridgeToObjectiveC() }) == [[1, 3], [2, 4]]._bridgeToObjectiveC() + } + + it("should start signal producers in order as defined") { + var ids = [Int]() + let createProducer = { (id: Int) -> SignalProducer in + return SignalProducer { observer, lifetime in + ids.append(id) + + observer.send(value: id) + observer.sendCompleted() + } + } + + let producerA = createProducer(1) + let producerB = createProducer(2) + + let producer = SignalProducer.zip([producerA, producerB]) + + var values = [[Int]]() + producer.startWithValues { value in + values.append(value) + } + + expect(ids) == [1, 2] + expect(values._bridgeToObjectiveC()) == [[1, 2]]._bridgeToObjectiveC() + } + } + + describe("timer") { + it("should send the current date at the given interval") { + let scheduler = TestScheduler() + let producer = SignalProducer.timer(interval: .seconds(1), on: scheduler, leeway: .seconds(0)) + + let startDate = scheduler.currentDate + let tick1 = startDate.addingTimeInterval(1) + let tick2 = startDate.addingTimeInterval(2) + let tick3 = startDate.addingTimeInterval(3) + + var dates: [Date] = [] + producer.startWithValues { dates.append($0) } + + scheduler.advance(by: .milliseconds(900)) + expect(dates) == [] + + scheduler.advance(by: .seconds(1)) + expect(dates) == [tick1] + + scheduler.advance() + expect(dates) == [tick1] + + scheduler.advance(by: .milliseconds(200)) + expect(dates) == [tick1, tick2] + + scheduler.advance(by: .seconds(1)) + expect(dates) == [tick1, tick2, tick3] + } + + it("shouldn't overflow on a real scheduler") { + let scheduler: QueueScheduler + if #available(OSX 10.10, *) { + scheduler = QueueScheduler(qos: .default, name: "\(#file):\(#line)") + } else { + scheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + + let producer = SignalProducer.timer(interval: .seconds(3), on: scheduler) + producer + .start() + .dispose() + } + + it("should dispose of the signal when disposed") { + let scheduler = TestScheduler() + let producer = SignalProducer.timer(interval: .seconds(1), on: scheduler, leeway: .seconds(0)) + var interrupted = false + + var isDisposed = false + weak var weakSignal: Signal? + producer.startWithSignal { signal, disposable in + weakSignal = signal + scheduler.schedule { + disposable.dispose() + } + signal.on(disposed: { isDisposed = true }).observeInterrupted { interrupted = true } + } + + expect(weakSignal).to(beNil()) + expect(isDisposed) == false + expect(interrupted) == false + + scheduler.run() + expect(weakSignal).to(beNil()) + expect(isDisposed) == true + expect(interrupted) == true + } + } + + describe("throttle while") { + var scheduler: ImmediateScheduler! + var shouldThrottle: MutableProperty! + var observer: Signal.Observer! + var producer: SignalProducer! + + beforeEach { + scheduler = ImmediateScheduler() + shouldThrottle = MutableProperty(false) + + let (baseSignal, baseObserver) = Signal.pipe() + observer = baseObserver + + producer = SignalProducer(baseSignal) + .throttle(while: shouldThrottle, on: scheduler) + + expect(producer).notTo(beNil()) + } + + it("doesn't extend the lifetime of the throttle property") { + var completed = false + shouldThrottle.lifetime.observeEnded { completed = true } + + observer.send(value: 1) + shouldThrottle = nil + + expect(completed) == true + } + } + + describe("on") { + it("should attach event handlers to each started signal") { + let (baseProducer, observer) = SignalProducer.pipe() + + var starting = 0 + var started = 0 + var event = 0 + var value = 0 + var completed = 0 + var terminated = 0 + + let producer = baseProducer + .on(starting: { + starting += 1 + }, started: { + started += 1 + }, event: { e in + event += 1 + }, completed: { + completed += 1 + }, terminated: { + terminated += 1 + }, value: { n in + value += 1 + }) + + producer.start() + expect(starting) == 1 + expect(started) == 1 + + producer.start() + expect(starting) == 2 + expect(started) == 2 + + observer.send(value: 1) + expect(event) == 2 + expect(value) == 2 + + observer.sendCompleted() + expect(event) == 4 + expect(completed) == 2 + expect(terminated) == 2 + } + + it("should attach event handlers for disposal") { + let (baseProducer, _) = SignalProducer.pipe() + + var disposed: Bool = false + + let producer = baseProducer + .on(disposed: { disposed = true }) + + let disposable = producer.start() + + expect(disposed) == false + disposable.dispose() + expect(disposed) == true + } + + it("should invoke the `started` action of the inner producer first") { + let (baseProducer, _) = SignalProducer.pipe() + + var numbers = [Int]() + + _ = baseProducer + .on(started: { numbers.append(1) }) + .on(started: { numbers.append(2) }) + .on(started: { numbers.append(3) }) + .start() + + expect(numbers) == [1, 2, 3] + } + + it("should invoke the `starting` action of the outer producer first") { + let (baseProducer, _) = SignalProducer.pipe() + + var numbers = [Int]() + + _ = baseProducer + .on(starting: { numbers.append(1) }) + .on(starting: { numbers.append(2) }) + .on(starting: { numbers.append(3) }) + .start() + + expect(numbers) == [3, 2, 1] + } + } + + describe("startOn") { + it("should invoke effects on the given scheduler") { + let scheduler = TestScheduler() + var invoked = false + + let producer = SignalProducer() { _, _ in + invoked = true + } + + producer.start(on: scheduler).start() + expect(invoked) == false + + scheduler.advance() + expect(invoked) == true + } + + it("should forward events on their original scheduler") { + let startScheduler = TestScheduler() + let testScheduler = TestScheduler() + + let producer = SignalProducer.timer(interval: .seconds(2), on: testScheduler, leeway: .seconds(0)) + + var value: Date? + producer.start(on: startScheduler).startWithValues { value = $0 } + + startScheduler.advance(by: .seconds(2)) + expect(value).to(beNil()) + + testScheduler.advance(by: .seconds(1)) + expect(value).to(beNil()) + + testScheduler.advance(by: .seconds(1)) + expect(value) == testScheduler.currentDate + } + } + + describe("flatMapError") { + it("should invoke the handler and start new producer for an error") { + let (baseProducer, baseObserver) = SignalProducer.pipe() + + var values: [Int] = [] + var completed = false + + baseProducer + .flatMapError { (error: TestError) -> SignalProducer in + expect(error) == TestError.default + expect(values) == [1] + + return .init(value: 2) + } + .start { event in + switch event { + case let .value(value): + values.append(value) + case .completed: + completed = true + default: + break + } + } + + baseObserver.send(value: 1) + baseObserver.send(error: .default) + + expect(values) == [1, 2] + expect(completed) == true + } + + it("should interrupt the replaced producer on disposal") { + let (baseProducer, baseObserver) = SignalProducer.pipe() + + var (disposed, interrupted) = (false, false) + let disposable = baseProducer + .flatMapError { (error: TestError) -> SignalProducer in + return SignalProducer { _, lifetime in + lifetime.observeEnded { disposed = true } + } + } + .startWithInterrupted { interrupted = true } + + baseObserver.send(error: .default) + disposable.dispose() + + expect(interrupted) == true + expect(disposed) == true + } + } + + describe("flatten") { + describe("FlattenStrategy.concat") { + describe("sequencing") { + var completePrevious: (() -> Void)! + var sendSubsequent: (() -> Void)! + var completeOuter: (() -> Void)! + + var subsequentStarted = false + + beforeEach { + let (outerProducer, outerObserver) = SignalProducer, NoError>.pipe() + let (previousProducer, previousObserver) = SignalProducer.pipe() + + subsequentStarted = false + let subsequentProducer = SignalProducer { _, _ in + subsequentStarted = true + } + + completePrevious = { previousObserver.sendCompleted() } + sendSubsequent = { outerObserver.send(value: subsequentProducer) } + completeOuter = { outerObserver.sendCompleted() } + + outerProducer.flatten(.concat).start() + outerObserver.send(value: previousProducer) + } + + it("should immediately start subsequent inner producer if previous inner producer has already completed") { + completePrevious() + sendSubsequent() + expect(subsequentStarted) == true + } + + context("with queued producers") { + beforeEach { + // Place the subsequent producer into `concat`'s queue. + sendSubsequent() + expect(subsequentStarted) == false + } + + it("should start subsequent inner producer upon completion of previous inner producer") { + completePrevious() + expect(subsequentStarted) == true + } + + it("should start subsequent inner producer upon completion of previous inner producer and completion of outer producer") { + completeOuter() + completePrevious() + expect(subsequentStarted) == true + } + } + } + + it("should forward an error from an inner producer") { + let errorProducer = SignalProducer(error: TestError.default) + let outerProducer = SignalProducer, TestError>(value: errorProducer) + + var error: TestError? + (outerProducer.flatten(.concat)).startWithFailed { e in + error = e + } + + expect(error) == TestError.default + } + + it("should forward an error from the outer producer") { + let (outerProducer, outerObserver) = SignalProducer, TestError>.pipe() + + var error: TestError? + outerProducer.flatten(.concat).startWithFailed { e in + error = e + } + + outerObserver.send(error: TestError.default) + expect(error) == TestError.default + } + + it("should not overflow the stack if inner producers complete immediately") { + typealias Inner = SignalProducer<(), NoError> + + let depth = 10000 + let inner: Inner = SignalProducer(value: ()) + let (first, firstObserver) = SignalProducer<(), NoError>.pipe() + let (outer, outerObserver) = SignalProducer.pipe() + + var value = 0 + outer + .flatten(.concat) + .startWithValues { _ in + value += 1 + } + + outerObserver.send(value: first) + for _ in 0.. Void)! + var completeInner: (() -> Void)! + + var completed = false + + beforeEach { + let (outerProducer, outerObserver) = SignalProducer, NoError>.pipe() + let (innerProducer, innerObserver) = SignalProducer.pipe() + + completeOuter = { outerObserver.sendCompleted() } + completeInner = { innerObserver.sendCompleted() } + + completed = false + outerProducer.flatten(.concat).startWithCompleted { + completed = true + } + + outerObserver.send(value: innerProducer) + } + + it("should complete when inner producers complete, then outer producer completes") { + completeInner() + expect(completed) == false + + completeOuter() + expect(completed) == true + } + + it("should complete when outer producers completes, then inner producers complete") { + completeOuter() + expect(completed) == false + + completeInner() + expect(completed) == true + } + } + } + + describe("FlattenStrategy.merge") { + describe("behavior") { + var completeA: (() -> Void)! + var sendA: (() -> Void)! + var completeB: (() -> Void)! + var sendB: (() -> Void)! + + var outerCompleted = false + + var recv = [Int]() + + beforeEach { + let (outerProducer, outerObserver) = SignalProducer, NoError>.pipe() + let (producerA, observerA) = SignalProducer.pipe() + let (producerB, observerB) = SignalProducer.pipe() + + completeA = { observerA.sendCompleted() } + completeB = { observerB.sendCompleted() } + + var a = 0 + sendA = { observerA.send(value: a); a += 1 } + + var b = 100 + sendB = { observerB.send(value: b); b += 1 } + + outerProducer.flatten(.merge).start { event in + switch event { + case let .value(i): + recv.append(i) + case .completed: + outerCompleted = true + default: + break + } + } + + outerObserver.send(value: producerA) + outerObserver.send(value: producerB) + + outerObserver.sendCompleted() + } + + it("should forward values from any inner signals") { + sendA() + sendA() + sendB() + sendA() + sendB() + expect(recv) == [0, 1, 100, 2, 101] + } + + it("should complete when all signals have completed") { + completeA() + expect(outerCompleted) == false + completeB() + expect(outerCompleted) == true + } + } + + describe("error handling") { + it("should forward an error from an inner signal") { + let errorProducer = SignalProducer(error: TestError.default) + let outerProducer = SignalProducer, TestError>(value: errorProducer) + + var error: TestError? + outerProducer.flatten(.merge).startWithFailed { e in + error = e + } + expect(error) == TestError.default + } + + it("should forward an error from the outer signal") { + let (outerProducer, outerObserver) = SignalProducer, TestError>.pipe() + + var error: TestError? + outerProducer.flatten(.merge).startWithFailed { e in + error = e + } + + outerObserver.send(error: TestError.default) + expect(error) == TestError.default + } + } + } + + describe("FlattenStrategy.latest") { + it("should forward values from the latest inner signal") { + let (outer, outerObserver) = SignalProducer, TestError>.pipe() + let (firstInner, firstInnerObserver) = SignalProducer.pipe() + let (secondInner, secondInnerObserver) = SignalProducer.pipe() + + var receivedValues: [Int] = [] + var errored = false + var completed = false + + outer.flatten(.latest).start { event in + switch event { + case let .value(value): + receivedValues.append(value) + case .completed: + completed = true + case .failed: + errored = true + case .interrupted: + break + } + } + + outerObserver.send(value: SignalProducer(value: 0)) + outerObserver.send(value: firstInner) + firstInnerObserver.send(value: 1) + outerObserver.send(value: secondInner) + secondInnerObserver.send(value: 2) + outerObserver.sendCompleted() + + expect(receivedValues) == [ 0, 1, 2 ] + expect(errored) == false + expect(completed) == false + + firstInnerObserver.send(value: 3) + firstInnerObserver.sendCompleted() + secondInnerObserver.send(value: 4) + secondInnerObserver.sendCompleted() + + expect(receivedValues) == [ 0, 1, 2, 4 ] + expect(errored) == false + expect(completed) == true + } + + it("should forward an error from an inner signal") { + let inner = SignalProducer(error: .default) + let outer = SignalProducer, TestError>(value: inner) + + let result = outer.flatten(.latest).first() + expect(result?.error) == TestError.default + } + + it("should forward an error from the outer signal") { + let outer = SignalProducer, TestError>(error: .default) + + let result = outer.flatten(.latest).first() + expect(result?.error) == TestError.default + } + + it("should complete when the original and latest signals have completed") { + let inner = SignalProducer.empty + let outer = SignalProducer, TestError>(value: inner) + + var completed = false + outer.flatten(.latest).startWithCompleted { + completed = true + } + + expect(completed) == true + } + + it("should complete when the outer signal completes before sending any signals") { + let outer = SignalProducer, TestError>.empty + + var completed = false + outer.flatten(.latest).startWithCompleted { + completed = true + } + + expect(completed) == true + } + + it("should not deadlock") { + let producer = SignalProducer(value: 1) + .flatMap(.latest) { _ in SignalProducer(value: 10) } + + let result = producer.take(first: 1).last() + expect(result?.value) == 10 + } + } + + describe("FlattenStrategy.race") { + it("should forward values from the first inner producer to send an event") { + let (outer, outerObserver) = SignalProducer, TestError>.pipe() + let (firstInner, firstInnerObserver) = SignalProducer.pipe() + let (secondInner, secondInnerObserver) = SignalProducer.pipe() + + var receivedValues: [Int] = [] + var errored = false + var completed = false + + outer.flatten(.race).start { event in + switch event { + case let .value(value): + receivedValues.append(value) + case .completed: + completed = true + case .failed: + errored = true + case .interrupted: + break + } + } + + outerObserver.send(value: firstInner) + outerObserver.send(value: secondInner) + firstInnerObserver.send(value: 1) + secondInnerObserver.send(value: 2) + outerObserver.sendCompleted() + + expect(receivedValues) == [ 1 ] + expect(errored) == false + expect(completed) == false + + secondInnerObserver.send(value: 3) + secondInnerObserver.sendCompleted() + + expect(receivedValues) == [ 1 ] + expect(errored) == false + expect(completed) == false + + firstInnerObserver.send(value: 4) + firstInnerObserver.sendCompleted() + + expect(receivedValues) == [ 1, 4 ] + expect(errored) == false + expect(completed) == true + } + + it("should forward an error from the first inner producer to send an error") { + let inner = SignalProducer(error: .default) + let outer = SignalProducer, TestError>(value: inner) + + let result = outer.flatten(.race).first() + expect(result?.error) == TestError.default + } + + it("should forward an error from the outer producer") { + let outer = SignalProducer, TestError>(error: .default) + + let result = outer.flatten(.race).first() + expect(result?.error) == TestError.default + } + + it("should complete when the 'outer producer' and 'first inner producer to send an event' have completed") { + let inner = SignalProducer.empty + let outer = SignalProducer, TestError>(value: inner) + + var completed = false + outer.flatten(.race).startWithCompleted { + completed = true + } + + expect(completed) == true + } + + it("should complete when the outer producer completes before sending any inner producers") { + let outer = SignalProducer, TestError>.empty + + var completed = false + outer.flatten(.race).startWithCompleted { + completed = true + } + + expect(completed) == true + } + + it("should not complete when the outer producer completes after sending an inner producer but it doesn't send an event") { + let inner = SignalProducer.never + let outer = SignalProducer, TestError>(value: inner) + + var completed = false + outer.flatten(.race).startWithCompleted { + completed = true + } + + expect(completed) == false + } + + it("should not deadlock") { + let producer = SignalProducer(value: 1) + .flatMap(.race) { _ in SignalProducer(value: 10) } + + let result = producer.take(first: 1).last() + expect(result?.value) == 10 + } + } + + describe("interruption") { + var innerObserver: Signal<(), NoError>.Observer! + var outerObserver: Signal, NoError>.Observer! + var execute: ((FlattenStrategy) -> Void)! + + var interrupted = false + var completed = false + + beforeEach { + let (innerProducer, incomingInnerObserver) = SignalProducer<(), NoError>.pipe() + let (outerProducer, incomingOuterObserver) = SignalProducer, NoError>.pipe() + + innerObserver = incomingInnerObserver + outerObserver = incomingOuterObserver + + execute = { strategy in + interrupted = false + completed = false + + outerProducer + .flatten(strategy) + .start { event in + switch event { + case .interrupted: + interrupted = true + case .completed: + completed = true + default: + break + } + } + } + + incomingOuterObserver.send(value: innerProducer) + } + + describe("Concat") { + it("should drop interrupted from an inner producer") { + execute(.concat) + + innerObserver.sendInterrupted() + expect(interrupted) == false + expect(completed) == false + + outerObserver.sendCompleted() + expect(completed) == true + } + + it("should forward interrupted from the outer producer") { + execute(.concat) + outerObserver.sendInterrupted() + expect(interrupted) == true + } + } + + describe("Latest") { + it("should drop interrupted from an inner producer") { + execute(.latest) + + innerObserver.sendInterrupted() + expect(interrupted) == false + expect(completed) == false + + outerObserver.sendCompleted() + expect(completed) == true + } + + it("should forward interrupted from the outer producer") { + execute(.latest) + outerObserver.sendInterrupted() + expect(interrupted) == true + } + } + + describe("Merge") { + it("should drop interrupted from an inner producer") { + execute(.merge) + + innerObserver.sendInterrupted() + expect(interrupted) == false + expect(completed) == false + + outerObserver.sendCompleted() + expect(completed) == true + } + + it("should forward interrupted from the outer producer") { + execute(.merge) + outerObserver.sendInterrupted() + expect(interrupted) == true + } + } + } + + describe("disposal") { + var completeOuter: (() -> Void)! + var disposeOuter: (() -> Void)! + var execute: ((FlattenStrategy) -> Void)! + + var innerDisposable = AnyDisposable() + var isInnerInterrupted = false + var isInnerDisposed = false + var interrupted = false + + beforeEach { + execute = { strategy in + let (outerProducer, outerObserver) = SignalProducer, NoError>.pipe() + + innerDisposable = AnyDisposable() + isInnerInterrupted = false + isInnerDisposed = false + let innerProducer = SignalProducer { $1.observeEnded(innerDisposable.dispose) } + .on(interrupted: { isInnerInterrupted = true }, disposed: { isInnerDisposed = true }) + + interrupted = false + let outerDisposable = outerProducer.flatten(strategy).startWithInterrupted { + interrupted = true + } + + completeOuter = outerObserver.sendCompleted + disposeOuter = outerDisposable.dispose + + outerObserver.send(value: innerProducer) + } + } + + describe("Concat") { + it("should cancel inner work when disposed before the outer producer completes") { + execute(.concat) + + expect(innerDisposable.isDisposed) == false + expect(interrupted) == false + expect(isInnerInterrupted) == false + expect(isInnerDisposed) == false + + disposeOuter() + + expect(innerDisposable.isDisposed) == true + expect(interrupted) == true + expect(isInnerInterrupted) == true + expect(isInnerDisposed) == true + } + + it("should cancel inner work when disposed after the outer producer completes") { + execute(.concat) + + completeOuter() + + expect(innerDisposable.isDisposed) == false + expect(interrupted) == false + expect(isInnerInterrupted) == false + expect(isInnerDisposed) == false + + disposeOuter() + + expect(innerDisposable.isDisposed) == true + expect(interrupted) == true + expect(isInnerInterrupted) == true + expect(isInnerDisposed) == true + } + } + + describe("Latest") { + it("should cancel inner work when disposed before the outer producer completes") { + execute(.latest) + + expect(innerDisposable.isDisposed) == false + expect(interrupted) == false + expect(isInnerInterrupted) == false + expect(isInnerDisposed) == false + + disposeOuter() + + expect(innerDisposable.isDisposed) == true + expect(interrupted) == true + expect(isInnerInterrupted) == true + expect(isInnerDisposed) == true + } + + it("should cancel inner work when disposed after the outer producer completes") { + execute(.latest) + + completeOuter() + + expect(innerDisposable.isDisposed) == false + expect(interrupted) == false + expect(isInnerInterrupted) == false + expect(isInnerDisposed) == false + + disposeOuter() + + expect(innerDisposable.isDisposed) == true + expect(interrupted) == true + expect(isInnerInterrupted) == true + expect(isInnerDisposed) == true + } + } + + describe("Merge") { + it("should cancel inner work when disposed before the outer producer completes") { + execute(.merge) + + expect(innerDisposable.isDisposed) == false + expect(interrupted) == false + expect(isInnerInterrupted) == false + expect(isInnerDisposed) == false + + disposeOuter() + + expect(innerDisposable.isDisposed) == true + expect(interrupted) == true + expect(isInnerInterrupted) == true + expect(isInnerDisposed) == true + + } + + it("should cancel inner work when disposed after the outer producer completes") { + execute(.merge) + + completeOuter() + + expect(innerDisposable.isDisposed) == false + expect(interrupted) == false + expect(isInnerInterrupted) == false + expect(isInnerDisposed) == false + + disposeOuter() + + expect(innerDisposable.isDisposed) == true + expect(interrupted) == true + expect(isInnerInterrupted) == true + expect(isInnerDisposed) == true + } + } + } + } + + describe("times") { + it("should start a signal N times upon completion") { + let original = SignalProducer([ 1, 2, 3 ]) + let producer = original.repeat(3) + + let result = producer.collect().single() + expect(result?.value) == [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ] + } + + it("should produce an equivalent signal producer if count is 1") { + let original = SignalProducer(value: 1) + let producer = original.repeat(1) + + let result = producer.collect().single() + expect(result?.value) == [ 1 ] + } + + it("should produce an empty signal if count is 0") { + let original = SignalProducer(value: 1) + let producer = original.repeat(0) + + let result = producer.first() + expect(result).to(beNil()) + } + + it("should not repeat upon error") { + let results: [Result] = [ + .success(1), + .success(2), + .failure(.default) + ] + + let original = SignalProducer.attemptWithResults(results) + let producer = original.repeat(3) + + let events = producer + .materialize() + .collect() + .single() + let result = events?.value + + let expectedEvents: [Signal.Event] = [ + .value(1), + .value(2), + .failed(.default) + ] + + // TODO: if let result = result where result.count == expectedEvents.count + if result?.count != expectedEvents.count { + fail("Invalid result: \(String(describing: result))") + } else { + // Can't test for equality because Array is not Equatable, + // and neither is Signal.Event. + expect(result![0] == expectedEvents[0]) == true + expect(result![1] == expectedEvents[1]) == true + expect(result![2] == expectedEvents[2]) == true + } + } + + it("should evaluate lazily") { + let original = SignalProducer(value: 1) + let producer = original.repeat(Int.max) + + let result = producer.take(first: 1).single() + expect(result?.value) == 1 + } + } + + describe("retry") { + it("should start a signal N times upon error") { + let results: [Result] = [ + .failure(.error1), + .failure(.error2), + .success(1) + ] + + let original = SignalProducer.attemptWithResults(results) + let producer = original.retry(upTo: 2) + + let result = producer.single() + + expect(result?.value) == 1 + } + + it("should forward errors that occur after all retries") { + let results: [Result] = [ + .failure(.default), + .failure(.error1), + .failure(.error2), + ] + + let original = SignalProducer.attemptWithResults(results) + let producer = original.retry(upTo: 2) + + let result = producer.single() + + expect(result?.error) == TestError.error2 + } + + it("should not retry upon completion") { + let results: [Result] = [ + .success(1), + .success(2), + .success(3) + ] + + let original = SignalProducer.attemptWithResults(results) + let producer = original.retry(upTo: 2) + + let result = producer.single() + expect(result?.value) == 1 + } + } + + describe("then") { + it("should start the subsequent producer after the completion of the original") { + let (original, observer) = SignalProducer.pipe() + + var subsequentStarted = false + let subsequent = SignalProducer { observer, _ in + subsequentStarted = true + } + + let producer = original.then(subsequent) + producer.start() + expect(subsequentStarted) == false + + observer.sendCompleted() + expect(subsequentStarted) == true + } + + it("should forward errors from the original producer") { + let original = SignalProducer(error: .default) + let subsequent = SignalProducer.empty + + let result = original.then(subsequent).first() + expect(result?.error) == TestError.default + } + + it("should forward errors from the subsequent producer") { + let original = SignalProducer.empty + let subsequent = SignalProducer(error: .default) + + let result = original.then(subsequent).first() + expect(result?.error) == TestError.default + } + + it("should forward interruptions from the original producer") { + let (original, observer) = SignalProducer.pipe() + + var subsequentStarted = false + let subsequent = SignalProducer { observer, _ in + subsequentStarted = true + } + + var interrupted = false + let producer = original.then(subsequent) + producer.startWithInterrupted { + interrupted = true + } + expect(subsequentStarted) == false + + observer.sendInterrupted() + expect(interrupted) == true + } + + it("should complete when both inputs have completed") { + let (original, originalObserver) = SignalProducer.pipe() + let (subsequent, subsequentObserver) = SignalProducer.pipe() + + let producer = original.then(subsequent) + + var completed = false + producer.startWithCompleted { + completed = true + } + + originalObserver.sendCompleted() + expect(completed) == false + + subsequentObserver.sendCompleted() + expect(completed) == true + } + + it("works with NoError and TestError") { + let producer: SignalProducer = SignalProducer.empty + .then(SignalProducer.empty) + + _ = producer + } + + it("works with TestError and NoError") { + let producer: SignalProducer = SignalProducer.empty + .then(SignalProducer.empty) + + _ = producer + } + + it("works with NoError and NoError") { + let producer: SignalProducer = SignalProducer.empty + .then(SignalProducer.empty) + + _ = producer + } + + it("should not be ambiguous") { + let a = SignalProducer.empty.then(SignalProducer.empty) + expect(type(of: a)) == SignalProducer.self + + let b = SignalProducer.empty.then(SignalProducer.empty) + expect(type(of: b)) == SignalProducer.self + + let c = SignalProducer.empty.then(SignalProducer.empty) + expect(type(of: c)) == SignalProducer.self + + let d = SignalProducer.empty.then(SignalProducer.empty) + expect(type(of: d)) == SignalProducer.self + + let e = SignalProducer.empty.then(SignalProducer.empty) + expect(type(of: e)) == SignalProducer.self + + let f = SignalProducer.empty.then(SignalProducer.empty) + expect(type(of: f)) == SignalProducer.self + + let g = SignalProducer.empty.then(SignalProducer.empty) + expect(type(of: g)) == SignalProducer.self + + let h = SignalProducer.empty.then(SignalProducer.empty) + expect(type(of: h)) == SignalProducer.self + } + } + + describe("first") { + it("should start a signal then block on the first value") { + let (_signal, observer) = Signal.pipe() + + let forwardingScheduler: QueueScheduler + + if #available(OSX 10.10, *) { + forwardingScheduler = QueueScheduler(qos: .default, name: "\(#file):\(#line)") + } else { + forwardingScheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + + let producer = SignalProducer(_signal.delay(0.1, on: forwardingScheduler)) + + let observingScheduler: QueueScheduler + + if #available(OSX 10.10, *) { + observingScheduler = QueueScheduler(qos: .default, name: "\(#file):\(#line)") + } else { + observingScheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + + var result: Int? + + observingScheduler.schedule { + result = producer.first()?.value + } + + expect(result).to(beNil()) + + observer.send(value: 1) + expect(result).toEventually(equal(1), timeout: 5.0) + } + + it("should return a nil result if no values are sent before completion") { + let result = SignalProducer.empty.first() + expect(result).to(beNil()) + } + + it("should return the first value if more than one value is sent") { + let result = SignalProducer([ 1, 2 ]).first() + expect(result?.value) == 1 + } + + it("should return an error if one occurs before the first value") { + let result = SignalProducer(error: .default).first() + expect(result?.error) == TestError.default + } + } + + describe("single") { + it("should start a signal then block until completion") { + let (_signal, observer) = Signal.pipe() + let forwardingScheduler: QueueScheduler + + if #available(OSX 10.10, *) { + forwardingScheduler = QueueScheduler(qos: .default, name: "\(#file):\(#line)") + } else { + forwardingScheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + + let producer = SignalProducer(_signal.delay(0.1, on: forwardingScheduler)) + + let observingScheduler: QueueScheduler + + if #available(OSX 10.10, *) { + observingScheduler = QueueScheduler(qos: .default, name: "\(#file):\(#line)") + } else { + observingScheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + + var result: Int? + + observingScheduler.schedule { + result = producer.single()?.value + } + expect(result).to(beNil()) + + observer.send(value: 1) + + Thread.sleep(forTimeInterval: 3.0) + expect(result).to(beNil()) + + observer.sendCompleted() + expect(result).toEventually(equal(1)) + } + + it("should return a nil result if no values are sent before completion") { + let result = SignalProducer.empty.single() + expect(result).to(beNil()) + } + + it("should return a nil result if more than one value is sent before completion") { + let result = SignalProducer([ 1, 2 ]).single() + expect(result).to(beNil()) + } + + it("should return an error if one occurs") { + let result = SignalProducer(error: .default).single() + expect(result?.error) == TestError.default + } + } + + describe("last") { + it("should start a signal then block until completion") { + let (_signal, observer) = Signal.pipe() + let scheduler: QueueScheduler + + if #available(*, OSX 10.10) { + scheduler = QueueScheduler(name: "\(#file):\(#line)") + } else { + scheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + let producer = SignalProducer(_signal.delay(0.1, on: scheduler)) + + var result: Result? + + let group = DispatchGroup() + + let globalQueue: DispatchQueue + if #available(*, OSX 10.10) { + globalQueue = DispatchQueue.global() + } else { + globalQueue = DispatchQueue.global(priority: .default) + } + + globalQueue.async(group: group, flags: []) { + result = producer.last() + } + expect(result).to(beNil()) + + observer.send(value: 1) + observer.send(value: 2) + expect(result).to(beNil()) + + observer.sendCompleted() + group.wait() + + expect(result?.value) == 2 + } + + it("should return a nil result if no values are sent before completion") { + let result = SignalProducer.empty.last() + expect(result).to(beNil()) + } + + it("should return the last value if more than one value is sent") { + let result = SignalProducer([ 1, 2 ]).last() + expect(result?.value) == 2 + } + + it("should return an error if one occurs") { + let result = SignalProducer(error: .default).last() + expect(result?.error) == TestError.default + } + } + + describe("wait") { + it("should start a signal then block until completion") { + let (_signal, observer) = Signal.pipe() + let scheduler: QueueScheduler + if #available(*, OSX 10.10) { + scheduler = QueueScheduler(name: "\(#file):\(#line)") + } else { + scheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + let producer = SignalProducer(_signal.delay(0.1, on: scheduler)) + + var result: Result<(), NoError>? + + let group = DispatchGroup() + + let globalQueue: DispatchQueue + if #available(*, OSX 10.10) { + globalQueue = DispatchQueue.global() + } else { + globalQueue = DispatchQueue.global(priority: .default) + } + + globalQueue.async(group: group, flags: []) { + result = producer.wait() + } + + expect(result).to(beNil()) + + observer.sendCompleted() + group.wait() + + expect(result?.value).toNot(beNil()) + } + + it("should return an error if one occurs") { + let result = SignalProducer(error: .default).wait() + expect(result.error) == TestError.default + } + } + + describe("observeOn") { + it("should immediately cancel upstream producer's work when disposed") { + var upstreamLifetime: Lifetime! + let producer = SignalProducer<(), NoError>{ _, innerLifetime in + upstreamLifetime = innerLifetime + } + + var downstreamDisposable: Disposable! + producer + .observe(on: TestScheduler()) + .startWithSignal { signal, innerDisposable in + signal.observe { _ in } + downstreamDisposable = innerDisposable + } + + expect(upstreamLifetime.hasEnded) == false + + downstreamDisposable.dispose() + expect(upstreamLifetime.hasEnded) == true + } + } + + describe("take") { + it("Should not start concat'ed producer if the first one sends a value when using take(1)") { + let scheduler: QueueScheduler + if #available(OSX 10.10, *) { + scheduler = QueueScheduler(name: "\(#file):\(#line)") + } else { + scheduler = QueueScheduler(queue: DispatchQueue(label: "\(#file):\(#line)")) + } + + // Delaying producer1 from sending a value to test whether producer2 is started in the mean-time. + let producer1 = SignalProducer() { handler, _ in + handler.send(value: 1) + handler.sendCompleted() + }.start(on: scheduler) + + var started = false + let producer2 = SignalProducer() { handler, _ in + started = true + handler.send(value: 2) + handler.sendCompleted() + } + + let result = producer1.concat(producer2).take(first: 1).collect().first() + + expect(result?.value) == [1] + expect(started) == false + } + } + + describe("replayLazily") { + var producer: SignalProducer! + var observer: SignalProducer.ProducedSignal.Observer! + + var replayedProducer: SignalProducer! + + beforeEach { + let (producerTemp, observerTemp) = SignalProducer.pipe() + producer = producerTemp + observer = observerTemp + + replayedProducer = producer.replayLazily(upTo: 2) + } + + context("subscribing to underlying producer") { + it("emits new values") { + var last: Int? + + replayedProducer + .assumeNoErrors() + .startWithValues { last = $0 } + + expect(last).to(beNil()) + + observer.send(value: 1) + expect(last) == 1 + + observer.send(value: 2) + expect(last) == 2 + } + + it("emits errors") { + var error: TestError? + + replayedProducer.startWithFailed { error = $0 } + expect(error).to(beNil()) + + observer.send(error: .default) + expect(error) == TestError.default + } + } + + context("buffers past values") { + it("emits last value upon subscription") { + let disposable = replayedProducer + .start() + + observer.send(value: 1) + disposable.dispose() + + var last: Int? + + replayedProducer + .assumeNoErrors() + .startWithValues { last = $0 } + expect(last) == 1 + } + + it("emits previous failure upon subscription") { + let disposable = replayedProducer + .start() + + observer.send(error: .default) + disposable.dispose() + + var error: TestError? + + replayedProducer + .startWithFailed { error = $0 } + expect(error) == TestError.default + } + + it("emits last n values upon subscription") { + var disposable = replayedProducer + .start() + + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) + disposable.dispose() + + var values: [Int] = [] + + disposable = replayedProducer + .assumeNoErrors() + .startWithValues { values.append($0) } + expect(values) == [ 3, 4 ] + + observer.send(value: 5) + expect(values) == [ 3, 4, 5 ] + + disposable.dispose() + values = [] + + replayedProducer + .assumeNoErrors() + .startWithValues { values.append($0) } + expect(values) == [ 4, 5 ] + } + } + + context("starting underying producer") { + it("starts lazily") { + var started = false + + let producer = SignalProducer(value: 0) + .on(started: { started = true }) + expect(started) == false + + let replayedProducer = producer + .replayLazily(upTo: 1) + expect(started) == false + + replayedProducer.start() + expect(started) == true + } + + it("shares a single subscription") { + var startedTimes = 0 + + let producer = SignalProducer.never + .on(started: { startedTimes += 1 }) + expect(startedTimes) == 0 + + let replayedProducer = producer + .replayLazily(upTo: 1) + expect(startedTimes) == 0 + + replayedProducer.start() + expect(startedTimes) == 1 + + replayedProducer.start() + expect(startedTimes) == 1 + } + + it("does not start multiple times when subscribing multiple times") { + var startedTimes = 0 + + let producer = SignalProducer(value: 0) + .on(started: { startedTimes += 1 }) + + let replayedProducer = producer + .replayLazily(upTo: 1) + + expect(startedTimes) == 0 + replayedProducer.start().dispose() + expect(startedTimes) == 1 + replayedProducer.start().dispose() + expect(startedTimes) == 1 + } + + it("does not start again if it finished") { + var startedTimes = 0 + + let producer = SignalProducer.empty + .on(started: { startedTimes += 1 }) + expect(startedTimes) == 0 + + let replayedProducer = producer + .replayLazily(upTo: 1) + expect(startedTimes) == 0 + + replayedProducer.start() + expect(startedTimes) == 1 + + replayedProducer.start() + expect(startedTimes) == 1 + } + } + + context("lifetime") { + it("does not dispose underlying subscription if the replayed producer is still in memory") { + var disposed = false + + let producer = SignalProducer.never + .on(disposed: { disposed = true }) + + let replayedProducer = producer + .replayLazily(upTo: 1) + + expect(disposed) == false + let disposable = replayedProducer.start() + expect(disposed) == false + + disposable.dispose() + expect(disposed) == false + } + + it("does not dispose if it has active subscriptions") { + var disposed = false + + let producer = SignalProducer.never + .on(disposed: { disposed = true }) + + var replayedProducer = ImplicitlyUnwrappedOptional(producer.replayLazily(upTo: 1)) + + expect(disposed) == false + let disposable1 = replayedProducer?.start() + let disposable2 = replayedProducer?.start() + expect(disposed) == false + + replayedProducer = nil + expect(disposed) == false + + disposable1?.dispose() + expect(disposed) == false + + disposable2?.dispose() + expect(disposed) == true + } + + it("disposes underlying producer when the producer is deallocated") { + var disposed = false + + let producer = SignalProducer.never + .on(disposed: { disposed = true }) + + var replayedProducer = ImplicitlyUnwrappedOptional(producer.replayLazily(upTo: 1)) + + expect(disposed) == false + let disposable = replayedProducer?.start() + expect(disposed) == false + + disposable?.dispose() + expect(disposed) == false + + replayedProducer = nil + expect(disposed) == true + } + + it("does not leak buffered values") { + final class Value { + private let deinitBlock: () -> Void + + init(deinitBlock: @escaping () -> Void) { + self.deinitBlock = deinitBlock + } + + deinit { + self.deinitBlock() + } + } + + var deinitValues = 0 + + var producer: SignalProducer! = SignalProducer(value: Value { + deinitValues += 1 + }) + expect(deinitValues) == 0 + + var replayedProducer: SignalProducer! = producer + .replayLazily(upTo: 1) + + let disposable = replayedProducer + .start() + + disposable.dispose() + expect(deinitValues) == 0 + + producer = nil + expect(deinitValues) == 0 + + replayedProducer = nil + expect(deinitValues) == 1 + } + } + + describe("log events") { + it("should output the correct event") { + let expectations: [(String) -> Void] = [ + { event in expect(event) == "[] starting" }, + { event in expect(event) == "[] started" }, + { event in expect(event) == "[] value 1" }, + { event in expect(event) == "[] completed" }, + { event in expect(event) == "[] terminated" }, + { event in expect(event) == "[] disposed" } + ] + + let logger = TestLogger(expectations: expectations) + + let (producer, observer) = SignalProducer.pipe() + producer + .logEvents(logger: logger.logEvent) + .start() + + observer.send(value: 1) + observer.sendCompleted() + } + } + + describe("init(values) ambiguity") { + it("should not be a SignalProducer, NoError>") { + + let producer1: SignalProducer = SignalProducer.empty + let producer2: SignalProducer = SignalProducer.empty + + // This expression verifies at compile time that the type is as expected. + let _: SignalProducer = SignalProducer([producer1, producer2]) + .flatten(.merge) + } + } + } + + describe("take(during:)") { + it("completes a signal when the lifetime ends") { + let (signal, observer) = Signal.pipe() + let object = MutableReference(TestObject()) + + let output = signal.take(during: object.value!.lifetime) + + var results: [Int] = [] + output.observeValues { results.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + object.value = nil + observer.send(value: 3) + + expect(results) == [1, 2] + } + + it("completes a signal producer when the lifetime ends") { + let (producer, observer) = Signal.pipe() + let object = MutableReference(TestObject()) + + let output = producer.take(during: object.value!.lifetime) + + var results: [Int] = [] + output.observeValues { results.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + object.value = nil + observer.send(value: 3) + + expect(results) == [1, 2] + } + } + + describe("negated attribute") { + it("should return the negate of a value in a Boolean producer") { + let producer = SignalProducer { observer, _ in + observer.send(value: true) + observer.sendCompleted() + } + + producer.negate().startWithValues { value in + expect(value).to(beFalse()) + } + } + } + + describe("and attribute") { + it("should emit true when both producers emits the same value") { + let producer1 = SignalProducer { observer, _ in + observer.send(value: true) + observer.sendCompleted() + } + let producer2 = SignalProducer { observer, _ in + observer.send(value: true) + observer.sendCompleted() + } + + producer1.and(producer2).startWithValues { value in + expect(value).to(beTrue()) + } + } + + it("should emit false when both producers emits opposite values") { + let producer1 = SignalProducer { observer, _ in + observer.send(value: true) + observer.sendCompleted() + } + let producer2 = SignalProducer { observer, _ in + observer.send(value: false) + observer.sendCompleted() + } + + producer1.and(producer2).startWithValues { value in + expect(value).to(beFalse()) + } + } + + it("should work the same way when using signal instead of a producer") { + let producer1 = SignalProducer { observer, _ in + observer.send(value: true) + observer.sendCompleted() + } + let (signal2, observer2) = Signal.pipe() + producer1.and(signal2).startWithValues { value in + expect(value).to(beTrue()) + } + observer2.send(value: true) + + observer2.sendCompleted() + } + } + + describe("or attribute") { + it("should emit true when at least one of the producers emits true") { + let producer1 = SignalProducer { observer, _ in + observer.send(value: true) + observer.sendCompleted() + } + let producer2 = SignalProducer { observer, _ in + observer.send(value: false) + observer.sendCompleted() + } + + producer1.or(producer2).startWithValues { value in + expect(value).to(beTrue()) + } + } + + it("should emit false when both producers emits false") { + let producer1 = SignalProducer { observer, _ in + observer.send(value: false) + observer.sendCompleted() + } + let producer2 = SignalProducer { observer, _ in + observer.send(value: false) + observer.sendCompleted() + } + + producer1.or(producer2).startWithValues { value in + expect(value).to(beFalse()) + } + } + + it("should work the same way when using signal instead of a producer") { + let producer1 = SignalProducer { observer, _ in + observer.send(value: true) + observer.sendCompleted() + } + let (signal2, observer2) = Signal.pipe() + producer1.or(signal2).startWithValues { value in + expect(value).to(beTrue()) + } + observer2.send(value: true) + + observer2.sendCompleted() + } + } + + describe("promoteError") { + it("should infer the error type from the context") { + let combined: Any = SignalProducer + .combineLatest(SignalProducer.never.promoteError(), + SignalProducer.never, + SignalProducer.never.promoteError(), + SignalProducer.never.flatMapError { _ in .empty }) + + expect(combined is SignalProducer<(Int, Double, Float, UInt), TestError>) == true + } + } + } +} + +// MARK: - Helpers + +private func == (left: Expectation, right: Any.Type) { + left.to(Predicate.fromDeprecatedClosure { expression, _ in + return try expression.evaluate()! == right + }.requireNonNil) +} + +extension SignalProducer { + internal static func pipe() -> (SignalProducer, ProducedSignal.Observer) { + let (signal, observer) = ProducedSignal.pipe() + let producer = SignalProducer(signal) + return (producer, observer) + } + + /// Creates a producer that can be started as many times as elements in `results`. + /// Each signal will immediately send either a value or an error. + fileprivate static func attemptWithResults(_ results: C) -> SignalProducer where C.Iterator.Element == Result, C.IndexDistance == C.Index, C.Index == Int { + let resultCount = results.count + var operationIndex = 0 + + precondition(resultCount > 0) + + let operation: () -> Result = { + if operationIndex < resultCount { + defer { + operationIndex += 1 + } + + return results[results.index(results.startIndex, offsetBy: operationIndex)] + } else { + fail("Operation started too many times") + + return results[results.startIndex] + } + } + + return SignalProducer(operation) + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalSpec.swift new file mode 100755 index 0000000..4a68389 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/SignalSpec.swift @@ -0,0 +1,3144 @@ +// +// SignalSpec.swift +// ReactiveSwift +// +// Created by Justin Spahr-Summers on 2015-01-23. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +import Foundation +import Dispatch + +import Result +import Nimble +import Quick +@testable import ReactiveSwift + +private class StateA {} +private class StateB {} +private enum SignalState { + case alive(StateA) + case terminating(StateB) + case terminated +} + +class SignalSpec: QuickSpec { + override func spec() { + describe("thread safety") { + it("should have the same memory layout as a native pointer") { + let enumLayout = MemoryLayout>.self + let pointerLayout = MemoryLayout.self + + expect(enumLayout.alignment) == pointerLayout.alignment + expect(enumLayout.size) == pointerLayout.size + expect(enumLayout.stride) == pointerLayout.stride + } + } + + describe("init") { + var testScheduler: TestScheduler! + + beforeEach { + testScheduler = TestScheduler() + } + + it("should run the generator immediately") { + var didRunGenerator = false + _ = Signal { observer in + didRunGenerator = true + return nil + } + + expect(didRunGenerator) == true + } + + it("should forward events to observers") { + let numbers = [ 1, 2, 5 ] + + let signal: Signal = Signal { observer in + testScheduler.schedule { + for number in numbers { + observer.send(value: number) + } + observer.sendCompleted() + } + return nil + } + + var fromSignal: [Int] = [] + var completed = false + + signal.observe { event in + switch event { + case let .value(number): + fromSignal.append(number) + case .completed: + completed = true + default: + break + } + } + + expect(completed) == false + expect(fromSignal).to(beEmpty()) + + testScheduler.run() + + expect(completed) == true + expect(fromSignal) == numbers + } + + it("should dispose of returned disposable upon error") { + let disposable = AnyDisposable() + + let signal: Signal = Signal { observer in + testScheduler.schedule { + observer.send(error: TestError.default) + } + return disposable + } + + var errored = false + + signal.observeFailed { _ in errored = true } + + expect(errored) == false + expect(disposable.isDisposed) == false + + testScheduler.run() + + expect(errored) == true + expect(disposable.isDisposed) == true + } + + it("should dispose of returned disposable upon completion") { + let disposable = AnyDisposable() + + let signal: Signal = Signal { observer in + testScheduler.schedule { + observer.sendCompleted() + } + return disposable + } + + var completed = false + + signal.observeCompleted { completed = true } + + expect(completed) == false + expect(disposable.isDisposed) == false + + testScheduler.run() + + expect(completed) == true + expect(disposable.isDisposed) == true + } + + it("should dispose of returned disposable upon interrupted") { + let disposable = AnyDisposable() + + let signal: Signal = Signal { observer in + testScheduler.schedule { + observer.sendInterrupted() + } + return disposable + } + + var interrupted = false + signal.observeInterrupted { + interrupted = true + } + + expect(interrupted) == false + expect(disposable.isDisposed) == false + + testScheduler.run() + + expect(interrupted) == true + expect(disposable.isDisposed) == true + } + + it("should dispose of the returned disposable if the signal has interrupted in the generator") { + let disposable = AnyDisposable() + + let signal: Signal = Signal { observer in + observer.sendInterrupted() + expect(disposable.isDisposed) == false + return disposable + } + + expect(disposable.isDisposed) == true + } + + it("should dispose of the returned disposable if the signal has completed in the generator") { + let disposable = AnyDisposable() + + let signal: Signal = Signal { observer in + observer.sendCompleted() + expect(disposable.isDisposed) == false + return disposable + } + + expect(disposable.isDisposed) == true + } + + it("should dispose of the returned disposable if the signal has failed in the generator") { + let disposable = AnyDisposable() + + let signal: Signal = Signal { observer in + observer.send(error: .default) + expect(disposable.isDisposed) == false + return disposable + } + + expect(disposable.isDisposed) == true + } + } + + describe("Signal.empty") { + it("should interrupt its observers without emitting any value") { + let signal = Signal<(), NoError>.empty + + var hasUnexpectedEventsEmitted = false + var signalInterrupted = false + + signal.observe { event in + switch event { + case .value, .failed, .completed: + hasUnexpectedEventsEmitted = true + case .interrupted: + signalInterrupted = true + } + } + + expect(hasUnexpectedEventsEmitted) == false + expect(signalInterrupted) == true + } + } + + describe("Signal.pipe") { + it("should forward events to observers") { + let (signal, observer) = Signal.pipe() + + var fromSignal: [Int] = [] + var completed = false + + signal.observe { event in + switch event { + case let .value(number): + fromSignal.append(number) + case .completed: + completed = true + default: + break + } + } + + expect(fromSignal).to(beEmpty()) + expect(completed) == false + + observer.send(value: 1) + expect(fromSignal) == [ 1 ] + + observer.send(value: 2) + expect(fromSignal) == [ 1, 2 ] + + expect(completed) == false + observer.sendCompleted() + expect(completed) == true + } + + it("should dispose the supplied disposable when the signal terminates") { + let disposable = AnyDisposable() + let (signal, observer) = Signal<(), NoError>.pipe(disposable: disposable) + + expect(disposable.isDisposed) == false + + observer.sendCompleted() + expect(disposable.isDisposed) == true + } + + context("memory") { + it("should not crash allocating memory with a few observers") { + let (signal, _) = Signal.pipe() + + #if os(Linux) + func autoreleasepool(invoking code: () -> Void) { + code() + } + #endif + + for _ in 0..<50 { + autoreleasepool { + let disposable = signal.observe { _ in } + + disposable!.dispose() + } + } + } + } + } + + describe("interruption") { + it("should not send events after sending an interrupted event") { + let queue: DispatchQueue + let counter = Atomic(0) + + if #available(macOS 10.10, *) { + queue = DispatchQueue.global(qos: .userInitiated) + } else { + queue = DispatchQueue.global(priority: .high) + } + + let (signal, observer) = Signal.pipe() + + var hasSlept = false + var events: [Signal.Event] = [] + + // Used to synchronize the `interrupt` sender to only act after the + // chosen observer has started sending its event, but before it is done. + let semaphore = DispatchSemaphore(value: 0) + + signal.observe { event in + if !hasSlept { + semaphore.signal() + // 100000 us = 0.1 s + usleep(100000) + hasSlept = true + } + events.append(event) + } + + let group = DispatchGroup() + + DispatchQueue.concurrentPerform(iterations: 10) { index in + queue.async(group: group) { + observer.send(value: index) + } + + if index == 0 { + semaphore.wait() + observer.sendInterrupted() + } + } + + group.wait() + + expect(events.count) == 2 + expect(events.first?.value).toNot(beNil()) + expect(events.last?.isTerminating) == true + } + + it("should interrupt concurrently") { + let queue: DispatchQueue + let counter = Atomic(0) + let executionCounter = Atomic(0) + + if #available(macOS 10.10, *) { + queue = DispatchQueue.global(qos: .userInitiated) + } else { + queue = DispatchQueue.global(priority: .high) + } + + let iterations = 1000 + let group = DispatchGroup() + + queue.async(group: group) { + DispatchQueue.concurrentPerform(iterations: iterations) { _ in + let (signal, observer) = Signal<(), NoError>.pipe() + + var isInterrupted = false + signal.observeInterrupted { counter.modify { $0 += 1 } } + + // Used to synchronize the `value` sender and the `interrupt` + // sender, giving a slight priority to the former. + let semaphore = DispatchSemaphore(value: 0) + + queue.async(group: group) { + semaphore.signal() + observer.send(value: ()) + executionCounter.modify { $0 += 1 } + } + + queue.async(group: group) { + semaphore.wait() + observer.sendInterrupted() + executionCounter.modify { $0 += 1 } + } + } + } + + group.wait() + + expect(executionCounter.value) == iterations * 2 + expect(counter.value).toEventually(equal(iterations), timeout: 5) + } + } + + describe("observe") { + var testScheduler: TestScheduler! + + beforeEach { + testScheduler = TestScheduler() + } + + it("should stop forwarding events when disposed") { + let disposable = AnyDisposable() + + let signal: Signal = Signal { observer in + testScheduler.schedule { + for number in [ 1, 2 ] { + observer.send(value: number) + } + observer.sendCompleted() + observer.send(value: 4) + } + return disposable + } + + var fromSignal: [Int] = [] + signal.observeValues { number in + fromSignal.append(number) + } + + expect(disposable.isDisposed) == false + expect(fromSignal).to(beEmpty()) + + testScheduler.run() + + expect(disposable.isDisposed) == true + expect(fromSignal) == [ 1, 2 ] + } + + it("should not trigger side effects") { + var runCount = 0 + let signal: Signal<(), NoError> = Signal { observer in + runCount += 1 + return nil + } + + expect(runCount) == 1 + + signal.observe(Signal<(), NoError>.Observer()) + expect(runCount) == 1 + } + + it("should release observer after termination") { + weak var testStr: NSMutableString? + let (signal, observer) = Signal.pipe() + + let test = { + let innerStr = NSMutableString(string: "") + signal.observeValues { value in + innerStr.append("\(value)") + } + testStr = innerStr + } + test() + + observer.send(value: 1) + expect(testStr) == "1" + observer.send(value: 2) + expect(testStr) == "12" + + observer.sendCompleted() + expect(testStr).to(beNil()) + } + + it("should release observer after interruption") { + weak var testStr: NSMutableString? + let (signal, observer) = Signal.pipe() + + let test = { + let innerStr = NSMutableString(string: "") + signal.observeValues { value in + innerStr.append("\(value)") + } + + testStr = innerStr + } + + test() + + observer.send(value: 1) + expect(testStr) == "1" + + observer.send(value: 2) + expect(testStr) == "12" + + observer.sendInterrupted() + expect(testStr).to(beNil()) + } + } + + describe("trailing closure") { + it("receives next values") { + var values = [Int]() + let (signal, observer) = Signal.pipe() + + signal.observeValues { value in + values.append(value) + } + + observer.send(value: 1) + expect(values) == [1] + } + + it("receives results") { + let (signal, observer) = Signal.pipe() + + var results: [Result] = [] + signal.observeResult { results.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(error: .default) + + observer.sendCompleted() + + expect(results).to(haveCount(4)) + expect(results[0].value) == 1 + expect(results[1].value) == 2 + expect(results[2].value) == 3 + expect(results[3].error) == .default + } + } + + describe("map") { + it("should transform the values of the signal") { + let (signal, observer) = Signal.pipe() + let mappedSignal = signal.map { String($0 + 1) } + + var lastValue: String? + + mappedSignal.observeValues { + lastValue = $0 + return + } + + expect(lastValue).to(beNil()) + + observer.send(value: 0) + expect(lastValue) == "1" + + observer.send(value: 1) + expect(lastValue) == "2" + } + +#if swift(>=3.2) + it("should support key paths") { + let (signal, observer) = Signal.pipe() + let mappedSignal = signal.map(\String.count) + + var lastValue: Int? + mappedSignal.observeValues { + lastValue = $0 + } + + expect(lastValue).to(beNil()) + + observer.send(value: "foo") + expect(lastValue) == 3 + + observer.send(value: "foobar") + expect(lastValue) == 6 + } +#endif + } + + + describe("mapError") { + it("should transform the errors of the signal") { + let (signal, observer) = Signal.pipe() + let producerError = NSError(domain: "com.reactivecocoa.errordomain", code: 100, userInfo: nil) + var error: NSError? + + signal + .mapError { _ in producerError } + .observeFailed { err in error = err } + + expect(error).to(beNil()) + + observer.send(error: TestError.default) + expect(error) == producerError + } + } + + describe("lazyMap") { + describe("with a scheduled binding") { + var token: Lifetime.Token! + var lifetime: Lifetime! + var destination: [String] = [] + var tupleSignal: Signal<(character: String, other: Int), NoError>! + var tupleObserver: Signal<(character: String, other: Int), NoError>.Observer! + var theLens: Signal! + var getterCounter: Int = 0 + var lensScheduler: TestScheduler! + var targetScheduler: TestScheduler! + var target: BindingTarget! + + beforeEach { + destination = [] + token = Lifetime.Token() + lifetime = Lifetime(token) + + let (producer, observer) = Signal<(character: String, other: Int), NoError>.pipe() + tupleSignal = producer + tupleObserver = observer + + lensScheduler = TestScheduler() + targetScheduler = TestScheduler() + + getterCounter = 0 + theLens = tupleSignal.lazyMap(on: lensScheduler) { (tuple: (character: String, other: Int)) -> String in + getterCounter += 1 + return tuple.character + } + + target = BindingTarget(on: targetScheduler, lifetime: lifetime) { + destination.append($0) + } + + target <~ theLens + } + + it("should not propagate values until scheduled") { + // Send a value along + tupleObserver.send(value: (character: "🎃", other: 42)) + + // The destination should not change value, and the getter + // should not have evaluated yet, as neither has been scheduled + expect(destination) == [] + expect(getterCounter) == 0 + + // Advance both schedulers + lensScheduler.advance() + targetScheduler.advance() + + // The destination receives the previously-sent value, and the + // getter obviously evaluated + expect(destination) == ["🎃"] + expect(getterCounter) == 1 + } + + it("should evaluate the getter only when scheduled") { + // Send a value along + tupleObserver.send(value: (character: "🎃", other: 42)) + + // The destination should not change value, and the getter + // should not have evaluated yet, as neither has been scheduled + expect(destination) == [] + expect(getterCounter) == 0 + + // When the getter's scheduler advances, the getter should + // be evaluated, but the destination still shouldn't accept + // the new value + lensScheduler.advance() + expect(getterCounter) == 1 + expect(destination) == [] + + // Sending other values along shouldn't evaluate the getter + tupleObserver.send(value: (character: "😾", other: 42)) + tupleObserver.send(value: (character: "🍬", other: 13)) + tupleObserver.send(value: (character: "👻", other: 17)) + expect(getterCounter) == 1 + expect(destination) == [] + + // Push the scheduler along for the lens, and the getter + // should evaluate + lensScheduler.advance() + expect(getterCounter) == 2 + + // ...but the destination still won't receive the value + expect(destination) == [] + + // Finally, pushing the target scheduler along will + // propagate only the first and last values + targetScheduler.advance() + expect(getterCounter) == 2 + expect(destination) == ["🎃", "👻"] + } + } + } + + describe("filter") { + it("should omit values from the signal") { + let (signal, observer) = Signal.pipe() + let mappedSignal = signal.filter { $0 % 2 == 0 } + + var lastValue: Int? + + mappedSignal.observeValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: 0) + expect(lastValue) == 0 + + observer.send(value: 1) + expect(lastValue) == 0 + + observer.send(value: 2) + expect(lastValue) == 2 + } + } + + describe("filterMap") { + it("should omit values from the signal that are nil after the transformation") { + let (signal, observer) = Signal.pipe() + let mappedSignal: Signal = signal.filterMap { Int.init($0) } + + var lastValue: Int? + + mappedSignal.observeValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: "0") + expect(lastValue) == 0 + + observer.send(value: "1") + expect(lastValue) == 1 + + observer.send(value: "A") + expect(lastValue) == 1 + } + + it("should stop emiting values after an error") { + let (signal, observer) = Signal.pipe() + let mappedSignal: Signal = signal.filterMap { Int.init($0) } + + var lastValue: Int? + + mappedSignal.observeResult { result in + if let value = result.value { + lastValue = value + } + } + + expect(lastValue).to(beNil()) + + observer.send(value: "0") + expect(lastValue) == 0 + + observer.send(error: .default) + + observer.send(value: "1") + expect(lastValue) == 0 + } + + it("should stop emiting values after a complete") { + let (signal, observer) = Signal.pipe() + let mappedSignal: Signal = signal.filterMap { Int.init($0) } + + var lastValue: Int? + + mappedSignal.observeValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: "0") + expect(lastValue) == 0 + + observer.sendCompleted() + + observer.send(value: "1") + expect(lastValue) == 0 + } + + it("should send completed") { + let (signal, observer) = Signal.pipe() + let mappedSignal: Signal = signal.filterMap { Int.init($0) } + + var completed: Bool = false + + mappedSignal.observeCompleted { completed = true } + observer.sendCompleted() + + expect(completed) == true + } + + it("should send failure") { + let (signal, observer) = Signal.pipe() + let mappedSignal: Signal = signal.filterMap { Int.init($0) } + + var failure: TestError? + + mappedSignal.observeFailed { failure = $0 } + observer.send(error: .error1) + + expect(failure) == .error1 + } + } + + describe("skipNil") { + it("should forward only non-nil values") { + let (signal, observer) = Signal.pipe() + let mappedSignal = signal.skipNil() + + var lastValue: Int? + + mappedSignal.observeValues { lastValue = $0 } + expect(lastValue).to(beNil()) + + observer.send(value: nil) + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: nil) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + } + } + + describe("scan(_:_:)") { + it("should incrementally accumulate a value") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.scan("", +) + + var lastValue: String? + + signal.observeValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: "a") + expect(lastValue) == "a" + + observer.send(value: "bb") + expect(lastValue) == "abb" + } + } + + describe("scan(into:_:)") { + it("should incrementally accumulate a value") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.scan(into: "") { $0 += $1 } + + var lastValue: String? + + signal.observeValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: "a") + expect(lastValue) == "a" + + observer.send(value: "bb") + expect(lastValue) == "abb" + } + } + + describe("reduce(_:_:)") { + it("should accumulate one value") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.reduce(1, +) + + var lastValue: Int? + var completed = false + + signal.observe { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + default: + break + } + } + + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue).to(beNil()) + + expect(completed) == false + observer.sendCompleted() + expect(completed) == true + + expect(lastValue) == 4 + } + + it("should send the initial value if none are received") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.reduce(1, +) + + var lastValue: Int? + var completed = false + + signal.observe { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + default: + break + } + } + + expect(lastValue).to(beNil()) + expect(completed) == false + + observer.sendCompleted() + + expect(lastValue) == 1 + expect(completed) == true + } + } + + describe("reduce(into:_:)") { + it("should accumulate one value") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.reduce(into: 1) { $0 += $1 } + + var lastValue: Int? + var completed = false + + signal.observe { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + default: + break + } + } + + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue).to(beNil()) + + expect(completed) == false + observer.sendCompleted() + expect(completed) == true + + expect(lastValue) == 4 + } + + it("should send the initial value if none are received") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.reduce(into: 1) { $0 += $1 } + + var lastValue: Int? + var completed = false + + signal.observe { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + default: + break + } + } + + expect(lastValue).to(beNil()) + expect(completed) == false + + observer.sendCompleted() + + expect(lastValue) == 1 + expect(completed) == true + } + } + + describe("skip") { + it("should skip initial values") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.skip(first: 1) + + var lastValue: Int? + signal.observeValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue) == 2 + } + + it("should not skip any values when 0") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.skip(first: 0) + + var lastValue: Int? + signal.observeValues { lastValue = $0 } + + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + } + } + + describe("skipRepeats") { + it("should skip duplicate Equatable values") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.skipRepeats() + + var values: [Bool] = [] + signal.observeValues { values.append($0) } + + expect(values) == [] + + observer.send(value: true) + expect(values) == [ true ] + + observer.send(value: true) + expect(values) == [ true ] + + observer.send(value: false) + expect(values) == [ true, false ] + + observer.send(value: true) + expect(values) == [ true, false, true ] + } + + it("should skip values according to a predicate") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.skipRepeats { $0.characters.count == $1.characters.count } + + var values: [String] = [] + signal.observeValues { values.append($0) } + + expect(values) == [] + + observer.send(value: "a") + expect(values) == [ "a" ] + + observer.send(value: "b") + expect(values) == [ "a" ] + + observer.send(value: "cc") + expect(values) == [ "a", "cc" ] + + observer.send(value: "d") + expect(values) == [ "a", "cc", "d" ] + } + + it("should not store strong reference to previously passed items") { + var disposedItems: [Bool] = [] + + struct Item { + let payload: Bool + let disposable: ScopedDisposable + } + + func item(_ payload: Bool) -> Item { + return Item( + payload: payload, + disposable: ScopedDisposable(AnyDisposable { disposedItems.append(payload) }) + ) + } + + let (baseSignal, observer) = Signal.pipe() + baseSignal.skipRepeats { $0.payload == $1.payload }.observeValues { _ in } + + observer.send(value: item(true)) + expect(disposedItems) == [] + + observer.send(value: item(false)) + expect(disposedItems) == [ true ] + + observer.send(value: item(false)) + expect(disposedItems) == [ true, false ] + + observer.send(value: item(true)) + expect(disposedItems) == [ true, false, false ] + + observer.sendCompleted() + expect(disposedItems) == [ true, false, false, true ] + } + } + + describe("uniqueValues") { + it("should skip values that have been already seen") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.uniqueValues() + + var values: [String] = [] + signal.observeValues { values.append($0) } + + expect(values) == [] + + observer.send(value: "a") + expect(values) == [ "a" ] + + observer.send(value: "b") + expect(values) == [ "a", "b" ] + + observer.send(value: "a") + expect(values) == [ "a", "b" ] + + observer.send(value: "b") + expect(values) == [ "a", "b" ] + + observer.send(value: "c") + expect(values) == [ "a", "b", "c" ] + + observer.sendCompleted() + expect(values) == [ "a", "b", "c" ] + } + } + + describe("skipWhile") { + var signal: Signal! + var observer: Signal.Observer! + + var lastValue: Int? + + beforeEach { + let (baseSignal, incomingObserver) = Signal.pipe() + + signal = baseSignal.skip { $0 < 2 } + observer = incomingObserver + lastValue = nil + + signal.observeValues { lastValue = $0 } + } + + it("should skip while the predicate is true") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue) == 2 + + observer.send(value: 0) + expect(lastValue) == 0 + } + + it("should not skip any values when the predicate starts false") { + expect(lastValue).to(beNil()) + + observer.send(value: 3) + expect(lastValue) == 3 + + observer.send(value: 1) + expect(lastValue) == 1 + } + } + + describe("skipUntil") { + var signal: Signal! + var observer: Signal.Observer! + var triggerObserver: Signal<(), NoError>.Observer! + + var lastValue: Int? = nil + + beforeEach { + let (baseSignal, incomingObserver) = Signal.pipe() + let (triggerSignal, incomingTriggerObserver) = Signal<(), NoError>.pipe() + + signal = baseSignal.skip(until: triggerSignal) + observer = incomingObserver + triggerObserver = incomingTriggerObserver + + lastValue = nil + + signal.observe { event in + switch event { + case let .value(value): + lastValue = value + default: + break + } + } + } + + it("should skip values until the trigger fires") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue).to(beNil()) + + triggerObserver.send(value: ()) + observer.send(value: 0) + expect(lastValue) == 0 + } + + it("should skip values until the trigger completes") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue).to(beNil()) + + observer.send(value: 2) + expect(lastValue).to(beNil()) + + triggerObserver.sendCompleted() + observer.send(value: 0) + expect(lastValue) == 0 + } + } + + describe("take") { + it("should take initial values") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.take(first: 2) + + var lastValue: Int? + var completed = false + signal.observe { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + default: + break + } + } + + expect(lastValue).to(beNil()) + expect(completed) == false + + observer.send(value: 1) + expect(lastValue) == 1 + expect(completed) == false + + observer.send(value: 2) + expect(lastValue) == 2 + expect(completed) == true + } + + it("should complete immediately after taking given number of values") { + let numbers = [ 1, 2, 4, 4, 5 ] + let testScheduler = TestScheduler() + + var signal: Signal = Signal { observer in + testScheduler.schedule { + for number in numbers { + observer.send(value: number) + } + } + return nil + } + + var completed = false + + signal = signal.take(first: numbers.count) + signal.observeCompleted { completed = true } + + expect(completed) == false + testScheduler.run() + expect(completed) == true + } + + it("should interrupt when 0") { + let numbers = [ 1, 2, 4, 4, 5 ] + let testScheduler = TestScheduler() + + let signal: Signal = Signal { observer in + testScheduler.schedule { + for number in numbers { + observer.send(value: number) + } + } + return nil + } + + var result: [Int] = [] + var interrupted = false + + signal + .take(first: 0) + .observe { event in + switch event { + case let .value(number): + result.append(number) + case .interrupted: + interrupted = true + default: + break + } + } + + expect(interrupted) == true + + testScheduler.run() + expect(result).to(beEmpty()) + } + } + + describe("collect") { + it("should collect all values") { + let (original, observer) = Signal.pipe() + let signal = original.collect() + let expectedResult = [ 1, 2, 3 ] + + var result: [Int]? + + signal.observeValues { value in + expect(result).to(beNil()) + result = value + } + + for number in expectedResult { + observer.send(value: number) + } + + expect(result).to(beNil()) + observer.sendCompleted() + expect(result) == expectedResult + } + + it("should complete with an empty array if there are no values") { + let (original, observer) = Signal.pipe() + let signal = original.collect() + + var result: [Int]? + + signal.observeValues { result = $0 } + + expect(result).to(beNil()) + observer.sendCompleted() + expect(result) == [] + } + + it("should forward errors") { + let (original, observer) = Signal.pipe() + let signal = original.collect() + + var error: TestError? + + signal.observeFailed { error = $0 } + + expect(error).to(beNil()) + observer.send(error: .default) + expect(error) == TestError.default + } + + it("should collect an exact count of values") { + let (original, observer) = Signal.pipe() + + let signal = original.collect(count: 3) + + var observedValues: [[Int]] = [] + + signal.observeValues { value in + observedValues.append(value) + } + + var expectation: [[Int]] = [] + + for i in 1...7 { + observer.send(value: i) + + if i % 3 == 0 { + expectation.append([Int]((i - 2)...i)) + expect(observedValues._bridgeToObjectiveC()) == expectation._bridgeToObjectiveC() + } else { + expect(observedValues._bridgeToObjectiveC()) == expectation._bridgeToObjectiveC() + } + } + + observer.sendCompleted() + + expectation.append([7]) + expect(observedValues._bridgeToObjectiveC()) == expectation._bridgeToObjectiveC() + } + + it("should collect values until it matches a certain value") { + let (original, observer) = Signal.pipe() + + let signal = original.collect { _, value in value != 5 } + + var expectedValues = [ + [5, 5], + [42, 5] + ] + + signal.observeValues { value in + expect(value) == expectedValues.removeFirst() + } + + signal.observeCompleted { + expect(expectedValues._bridgeToObjectiveC()) == [] + } + + expectedValues + .flatMap { $0 } + .forEach(observer.send(value:)) + + observer.sendCompleted() + } + + it("should collect values until it matches a certain condition on values") { + let (original, observer) = Signal.pipe() + + let signal = original.collect { values in values.reduce(0, +) == 10 } + + var expectedValues = [ + [1, 2, 3, 4], + [5, 6, 7, 8, 9] + ] + + signal.observeValues { value in + expect(value) == expectedValues.removeFirst() + } + + signal.observeCompleted { + expect(expectedValues._bridgeToObjectiveC()) == [] + } + + expectedValues + .flatMap { $0 } + .forEach(observer.send(value:)) + + observer.sendCompleted() + } + } + + describe("takeUntil") { + var signal: Signal! + var observer: Signal.Observer! + var triggerObserver: Signal<(), NoError>.Observer! + + var lastValue: Int? = nil + var completed: Bool = false + + beforeEach { + let (baseSignal, incomingObserver) = Signal.pipe() + let (triggerSignal, incomingTriggerObserver) = Signal<(), NoError>.pipe() + + signal = baseSignal.take(until: triggerSignal) + observer = incomingObserver + triggerObserver = incomingTriggerObserver + + lastValue = nil + completed = false + + signal.observe { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + default: + break + } + } + } + + it("should take values until the trigger fires") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + + expect(completed) == false + triggerObserver.send(value: ()) + expect(completed) == true + } + + it("should take values until the trigger completes") { + expect(lastValue).to(beNil()) + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + + expect(completed) == false + triggerObserver.sendCompleted() + expect(completed) == true + } + + it("should complete if the trigger fires immediately") { + expect(lastValue).to(beNil()) + expect(completed) == false + + triggerObserver.send(value: ()) + + expect(completed) == true + expect(lastValue).to(beNil()) + } + } + + describe("takeUntilReplacement") { + var signal: Signal! + var observer: Signal.Observer! + var replacementObserver: Signal.Observer! + + var lastValue: Int? = nil + var completed: Bool = false + + beforeEach { + let (baseSignal, incomingObserver) = Signal.pipe() + let (replacementSignal, incomingReplacementObserver) = Signal.pipe() + + signal = baseSignal.take(untilReplacement: replacementSignal) + observer = incomingObserver + replacementObserver = incomingReplacementObserver + + lastValue = nil + completed = false + + signal.observe { event in + switch event { + case let .value(value): + lastValue = value + case .completed: + completed = true + default: + break + } + } + } + + it("should take values from the original then the replacement") { + expect(lastValue).to(beNil()) + expect(completed) == false + + observer.send(value: 1) + expect(lastValue) == 1 + + observer.send(value: 2) + expect(lastValue) == 2 + + replacementObserver.send(value: 3) + + expect(lastValue) == 3 + expect(completed) == false + + observer.send(value: 4) + + expect(lastValue) == 3 + expect(completed) == false + + replacementObserver.send(value: 5) + expect(lastValue) == 5 + + expect(completed) == false + replacementObserver.sendCompleted() + expect(completed) == true + } + } + + describe("takeWhile") { + var signal: Signal! + var observer: Signal.Observer! + + beforeEach { + let (baseSignal, incomingObserver) = Signal.pipe() + signal = baseSignal.take { $0 <= 4 } + observer = incomingObserver + } + + it("should take while the predicate is true") { + var latestValue: Int! + var completed = false + + signal.observe { event in + switch event { + case let .value(value): + latestValue = value + case .completed: + completed = true + default: + break + } + } + + for value in -1...4 { + observer.send(value: value) + expect(latestValue) == value + expect(completed) == false + } + + observer.send(value: 5) + expect(latestValue) == 4 + expect(completed) == true + } + + it("should complete if the predicate starts false") { + var latestValue: Int? + var completed = false + + signal.observe { event in + switch event { + case let .value(value): + latestValue = value + case .completed: + completed = true + default: + break + } + } + + observer.send(value: 5) + expect(latestValue).to(beNil()) + expect(completed) == true + } + } + + describe("observeOn") { + it("should send events on the given scheduler") { + let testScheduler = TestScheduler() + let (signal, observer) = Signal.pipe() + + var result: [Int] = [] + + signal + .observe(on: testScheduler) + .observeValues { result.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + expect(result).to(beEmpty()) + + testScheduler.run() + expect(result) == [ 1, 2 ] + } + } + + describe("delay") { + it("should send events on the given scheduler after the interval") { + let testScheduler = TestScheduler() + let signal: Signal = Signal { observer in + testScheduler.schedule { + observer.send(value: 1) + } + testScheduler.schedule(after: .seconds(5)) { + observer.send(value: 2) + observer.sendCompleted() + } + return nil + } + + var result: [Int] = [] + var completed = false + + signal + .delay(10, on: testScheduler) + .observe { event in + switch event { + case let .value(number): + result.append(number) + case .completed: + completed = true + default: + break + } + } + + testScheduler.advance(by: .seconds(4)) // send initial value + expect(result).to(beEmpty()) + + testScheduler.advance(by: .seconds(10)) // send second value and receive first + expect(result) == [ 1 ] + expect(completed) == false + + testScheduler.advance(by: .seconds(10)) // send second value and receive first + expect(result) == [ 1, 2 ] + expect(completed) == true + } + + it("should schedule errors immediately") { + let testScheduler = TestScheduler() + let signal: Signal = Signal { observer in + testScheduler.schedule { + observer.send(error: TestError.default) + } + return nil + } + + var errored = false + + signal + .delay(10, on: testScheduler) + .observeFailed { _ in errored = true } + + testScheduler.advance() + expect(errored) == true + } + } + + describe("throttle") { + var scheduler: TestScheduler! + var observer: Signal.Observer! + var signal: Signal! + + beforeEach { + scheduler = TestScheduler() + + let (baseSignal, baseObserver) = Signal.pipe() + observer = baseObserver + + signal = baseSignal.throttle(1, on: scheduler) + expect(signal).notTo(beNil()) + } + + it("should send values on the given scheduler at no less than the interval") { + var values: [Int] = [] + signal.observeValues { value in + values.append(value) + } + + expect(values) == [] + + observer.send(value: 0) + expect(values) == [] + + scheduler.advance() + expect(values) == [ 0 ] + + observer.send(value: 1) + observer.send(value: 2) + expect(values) == [ 0 ] + + scheduler.advance(by: .milliseconds(1500)) + expect(values) == [ 0, 2 ] + + scheduler.advance(by: .seconds(3)) + expect(values) == [ 0, 2 ] + + observer.send(value: 3) + expect(values) == [ 0, 2 ] + + scheduler.advance() + expect(values) == [ 0, 2, 3 ] + + observer.send(value: 4) + observer.send(value: 5) + scheduler.advance() + expect(values) == [ 0, 2, 3 ] + + scheduler.rewind(by: .seconds(2)) + expect(values) == [ 0, 2, 3 ] + + observer.send(value: 6) + scheduler.advance() + expect(values) == [ 0, 2, 3, 6 ] + + observer.send(value: 7) + observer.send(value: 8) + scheduler.advance() + expect(values) == [ 0, 2, 3, 6 ] + + scheduler.run() + expect(values) == [ 0, 2, 3, 6, 8 ] + } + + it("should schedule completion immediately") { + var values: [Int] = [] + var completed = false + + signal.observe { event in + switch event { + case let .value(value): + values.append(value) + case .completed: + completed = true + default: + break + } + } + + observer.send(value: 0) + scheduler.advance() + expect(values) == [ 0 ] + + observer.send(value: 1) + observer.sendCompleted() + expect(completed) == false + + scheduler.advance() + expect(values) == [ 0 ] + expect(completed) == true + + scheduler.run() + expect(values) == [ 0 ] + expect(completed) == true + } + } + + describe("throttle while") { + var scheduler: ImmediateScheduler! + var shouldThrottle: MutableProperty! + var observer: Signal.Observer! + var signal: Signal! + + beforeEach { + scheduler = ImmediateScheduler() + shouldThrottle = MutableProperty(false) + + let (baseSignal, baseObserver) = Signal.pipe() + observer = baseObserver + + signal = baseSignal.throttle(while: shouldThrottle, on: scheduler) + expect(signal).notTo(beNil()) + } + + it("passes through unthrottled values") { + var values: [Int] = [] + signal.observeValues { values.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + + expect(values) == [1, 2, 3] + } + + it("emits the latest throttled value when resumed") { + var values: [Int] = [] + signal.observeValues { values.append($0) } + + shouldThrottle.value = true + observer.send(value: 1) + observer.send(value: 2) + shouldThrottle.value = false + + expect(values) == [2] + } + + it("continues sending values after being resumed") { + var values: [Int] = [] + signal.observeValues { values.append($0) } + + shouldThrottle.value = true + observer.send(value: 1) + shouldThrottle.value = false + observer.send(value: 2) + observer.send(value: 3) + + expect(values) == [1, 2, 3] + } + + it("stays throttled if the property completes while throttled") { + var values: [Int] = [] + signal.observeValues { values.append($0) } + + shouldThrottle.value = false + observer.send(value: 1) + shouldThrottle.value = true + observer.send(value: 2) + shouldThrottle = nil + observer.send(value: 3) + + expect(values) == [1] + } + + it("stays resumed if the property completes while resumed") { + var values: [Int] = [] + signal.observeValues { values.append($0) } + + shouldThrottle.value = true + observer.send(value: 1) + shouldThrottle.value = false + observer.send(value: 2) + shouldThrottle = nil + observer.send(value: 3) + + expect(values) == [1, 2, 3] + } + + it("doesn't extend the lifetime of the throttle property") { + var completed = false + shouldThrottle.lifetime.observeEnded { completed = true } + + observer.send(value: 1) + shouldThrottle = nil + + expect(completed) == true + } + } + + describe("debounce") { + var scheduler: TestScheduler! + var observer: Signal.Observer! + var signal: Signal! + + beforeEach { + scheduler = TestScheduler() + + let (baseSignal, baseObserver) = Signal.pipe() + observer = baseObserver + + signal = baseSignal.debounce(1, on: scheduler) + expect(signal).notTo(beNil()) + } + + it("should send values on the given scheduler once the interval has passed since the last value was sent") { + var values: [Int] = [] + signal.observeValues { value in + values.append(value) + } + + expect(values) == [] + + observer.send(value: 0) + expect(values) == [] + + scheduler.advance() + expect(values) == [] + + observer.send(value: 1) + observer.send(value: 2) + expect(values) == [] + + scheduler.advance(by: .milliseconds(1500)) + expect(values) == [ 2 ] + + scheduler.advance(by: .seconds(3)) + expect(values) == [ 2 ] + + observer.send(value: 3) + expect(values) == [ 2 ] + + scheduler.advance() + expect(values) == [ 2 ] + + observer.send(value: 4) + observer.send(value: 5) + scheduler.advance() + expect(values) == [ 2 ] + + scheduler.run() + expect(values) == [ 2, 5 ] + } + + it("should schedule completion immediately") { + var values: [Int] = [] + var completed = false + + signal.observe { event in + switch event { + case let .value(value): + values.append(value) + case .completed: + completed = true + default: + break + } + } + + observer.send(value: 0) + scheduler.advance() + expect(values) == [] + + observer.send(value: 1) + observer.sendCompleted() + expect(completed) == false + + scheduler.advance() + expect(values) == [] + expect(completed) == true + + scheduler.run() + expect(values) == [] + expect(completed) == true + } + } + + describe("sampleWith") { + var sampledSignal: Signal<(Int, String), NoError>! + var observer: Signal.Observer! + var samplerObserver: Signal.Observer! + + beforeEach { + let (signal, incomingObserver) = Signal.pipe() + let (sampler, incomingSamplerObserver) = Signal.pipe() + sampledSignal = signal.sample(with: sampler) + observer = incomingObserver + samplerObserver = incomingSamplerObserver + } + + it("should forward the latest value when the sampler fires") { + var result: [String] = [] + sampledSignal.observeValues { result.append("\($0.0)\($0.1)") } + + observer.send(value: 1) + observer.send(value: 2) + samplerObserver.send(value: "a") + expect(result) == [ "2a" ] + } + + it("should do nothing if sampler fires before signal receives value") { + var result: [String] = [] + sampledSignal.observeValues { result.append("\($0.0)\($0.1)") } + + samplerObserver.send(value: "a") + expect(result).to(beEmpty()) + } + + it("should send lates value with sampler value multiple times when sampler fires multiple times") { + var result: [String] = [] + sampledSignal.observeValues { result.append("\($0.0)\($0.1)") } + + observer.send(value: 1) + samplerObserver.send(value: "a") + samplerObserver.send(value: "b") + expect(result) == [ "1a", "1b" ] + } + + it("should complete when both inputs have completed") { + var completed = false + sampledSignal.observeCompleted { completed = true } + + observer.sendCompleted() + expect(completed) == false + + samplerObserver.sendCompleted() + expect(completed) == true + } + } + + describe("sampleOn") { + var sampledSignal: Signal! + var observer: Signal.Observer! + var samplerObserver: Signal<(), NoError>.Observer! + + beforeEach { + let (signal, incomingObserver) = Signal.pipe() + let (sampler, incomingSamplerObserver) = Signal<(), NoError>.pipe() + sampledSignal = signal.sample(on: sampler) + observer = incomingObserver + samplerObserver = incomingSamplerObserver + } + + it("should forward the latest value when the sampler fires") { + var result: [Int] = [] + sampledSignal.observeValues { result.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + samplerObserver.send(value: ()) + expect(result) == [ 2 ] + } + + it("should do nothing if sampler fires before signal receives value") { + var result: [Int] = [] + sampledSignal.observeValues { result.append($0) } + + samplerObserver.send(value: ()) + expect(result).to(beEmpty()) + } + + it("should send lates value multiple times when sampler fires multiple times") { + var result: [Int] = [] + sampledSignal.observeValues { result.append($0) } + + observer.send(value: 1) + samplerObserver.send(value: ()) + samplerObserver.send(value: ()) + expect(result) == [ 1, 1 ] + } + + it("should complete when both inputs have completed") { + var completed = false + sampledSignal.observeCompleted { completed = true } + + observer.sendCompleted() + expect(completed) == false + + samplerObserver.sendCompleted() + expect(completed) == true + } + } + + describe("withLatest(from: signal)") { + var withLatestSignal: Signal<(Int, String), NoError>! + var observer: Signal.Observer! + var sampleeObserver: Signal.Observer! + + beforeEach { + let (signal, incomingObserver) = Signal.pipe() + let (samplee, incomingSampleeObserver) = Signal.pipe() + withLatestSignal = signal.withLatest(from: samplee) + observer = incomingObserver + sampleeObserver = incomingSampleeObserver + } + + it("should forward the latest value when the receiver fires") { + var result: [String] = [] + withLatestSignal.observeValues { result.append("\($0.0)\($0.1)") } + + sampleeObserver.send(value: "a") + sampleeObserver.send(value: "b") + observer.send(value: 1) + expect(result) == [ "1b" ] + } + + it("should do nothing if receiver fires before samplee sends value") { + var result: [String] = [] + withLatestSignal.observeValues { result.append("\($0.0)\($0.1)") } + + observer.send(value: 1) + expect(result).to(beEmpty()) + } + + it("should send latest value with samplee value multiple times when receiver fires multiple times") { + var result: [String] = [] + withLatestSignal.observeValues { result.append("\($0.0)\($0.1)") } + + sampleeObserver.send(value: "a") + observer.send(value: 1) + observer.send(value: 2) + expect(result) == [ "1a", "2a" ] + } + + it("should complete when receiver has completed") { + var completed = false + withLatestSignal.observeCompleted { completed = true } + + sampleeObserver.sendCompleted() + expect(completed) == false + + observer.sendCompleted() + expect(completed) == true + } + + it("should not affect when samplee has completed") { + var event: Signal<(Int, String), NoError>.Event? = nil + withLatestSignal.observe { event = $0 } + + sampleeObserver.sendCompleted() + expect(event).to(beNil()) + } + + it("should not affect when samplee has interrupted") { + var event: Signal<(Int, String), NoError>.Event? = nil + withLatestSignal.observe { event = $0 } + + sampleeObserver.sendInterrupted() + expect(event).to(beNil()) + } + } + + describe("withLatest(from: producer)") { + var withLatestSignal: Signal<(Int, String), NoError>! + var observer: Signal.Observer! + var sampleeObserver: Signal.Observer! + + beforeEach { + let (signal, incomingObserver) = Signal.pipe() + let (samplee, incomingSampleeObserver) = SignalProducer.pipe() + withLatestSignal = signal.withLatest(from: samplee) + observer = incomingObserver + sampleeObserver = incomingSampleeObserver + } + + it("should forward the latest value when the receiver fires") { + var result: [String] = [] + withLatestSignal.observeValues { result.append("\($0.0)\($0.1)") } + + sampleeObserver.send(value: "a") + sampleeObserver.send(value: "b") + observer.send(value: 1) + expect(result) == [ "1b" ] + } + + it("should do nothing if receiver fires before samplee sends value") { + var result: [String] = [] + withLatestSignal.observeValues { result.append("\($0.0)\($0.1)") } + + observer.send(value: 1) + expect(result).to(beEmpty()) + } + + it("should send latest value with samplee value multiple times when receiver fires multiple times") { + var result: [String] = [] + withLatestSignal.observeValues { result.append("\($0.0)\($0.1)") } + + sampleeObserver.send(value: "a") + observer.send(value: 1) + observer.send(value: 2) + expect(result) == [ "1a", "2a" ] + } + + it("should complete when receiver has completed") { + var completed = false + withLatestSignal.observeCompleted { completed = true } + + observer.sendCompleted() + expect(completed) == true + } + + it("should not affect when samplee has completed") { + var event: Signal<(Int, String), NoError>.Event? = nil + withLatestSignal.observe { event = $0 } + + sampleeObserver.sendCompleted() + expect(event).to(beNil()) + } + + it("should not affect when samplee has interrupted") { + var event: Signal<(Int, String), NoError>.Event? = nil + withLatestSignal.observe { event = $0 } + + sampleeObserver.sendInterrupted() + expect(event).to(beNil()) + } + } + + describe("combineLatestWith") { + var combinedSignal: Signal<(Int, Double), NoError>! + var observer: Signal.Observer! + var otherObserver: Signal.Observer! + + beforeEach { + let (signal, incomingObserver) = Signal.pipe() + let (otherSignal, incomingOtherObserver) = Signal.pipe() + combinedSignal = signal.combineLatest(with: otherSignal) + observer = incomingObserver + otherObserver = incomingOtherObserver + } + + it("should forward the latest values from both inputs") { + var latest: (Int, Double)? + combinedSignal.observeValues { latest = $0 } + + observer.send(value: 1) + expect(latest).to(beNil()) + + // is there a better way to test tuples? + otherObserver.send(value: 1.5) + expect(latest?.0) == 1 + expect(latest?.1) == 1.5 + + observer.send(value: 2) + expect(latest?.0) == 2 + expect(latest?.1) == 1.5 + } + + it("should complete when both inputs have completed") { + var completed = false + combinedSignal.observeCompleted { completed = true } + + observer.sendCompleted() + expect(completed) == false + + otherObserver.sendCompleted() + expect(completed) == true + } + } + + describe("zipWith") { + var leftObserver: Signal.Observer! + var rightObserver: Signal.Observer! + var zipped: Signal<(Int, String), NoError>! + + beforeEach { + let (leftSignal, incomingLeftObserver) = Signal.pipe() + let (rightSignal, incomingRightObserver) = Signal.pipe() + + leftObserver = incomingLeftObserver + rightObserver = incomingRightObserver + zipped = leftSignal.zip(with: rightSignal) + } + + it("should combine pairs") { + var result: [String] = [] + zipped.observeValues { result.append("\($0.0)\($0.1)") } + + leftObserver.send(value: 1) + leftObserver.send(value: 2) + expect(result) == [] + + rightObserver.send(value: "foo") + expect(result) == [ "1foo" ] + + leftObserver.send(value: 3) + rightObserver.send(value: "bar") + expect(result) == [ "1foo", "2bar" ] + + rightObserver.send(value: "buzz") + expect(result) == [ "1foo", "2bar", "3buzz" ] + + rightObserver.send(value: "fuzz") + expect(result) == [ "1foo", "2bar", "3buzz" ] + + leftObserver.send(value: 4) + expect(result) == [ "1foo", "2bar", "3buzz", "4fuzz" ] + } + + it("should complete when the shorter signal has completed") { + var result: [String] = [] + var completed = false + + zipped.observe { event in + switch event { + case let .value(left, right): + result.append("\(left)\(right)") + case .completed: + completed = true + default: + break + } + } + + expect(completed) == false + + leftObserver.send(value: 0) + leftObserver.sendCompleted() + expect(completed) == false + expect(result) == [] + + rightObserver.send(value: "foo") + expect(completed) == true + expect(result) == [ "0foo" ] + } + + it("should complete when both signal have completed") { + var result: [String] = [] + var completed = false + + zipped.observe { event in + switch event { + case let .value(left, right): + result.append("\(left)\(right)") + case .completed: + completed = true + default: + break + } + } + + expect(completed) == false + + leftObserver.send(value: 0) + leftObserver.sendCompleted() + expect(completed) == false + expect(result) == [] + + rightObserver.sendCompleted() + expect(result) == [ ] + } + + it("should complete and drop unpaired pending values when both signal have completed") { + var result: [String] = [] + var completed = false + + zipped.observe { event in + switch event { + case let .value(left, right): + result.append("\(left)\(right)") + case .completed: + completed = true + default: + break + } + } + + expect(completed) == false + + leftObserver.send(value: 0) + leftObserver.send(value: 1) + leftObserver.send(value: 2) + leftObserver.send(value: 3) + leftObserver.sendCompleted() + expect(completed) == false + expect(result) == [] + + rightObserver.send(value: "foo") + rightObserver.send(value: "bar") + rightObserver.sendCompleted() + expect(result) == ["0foo", "1bar"] + } + } + + describe("materialize") { + it("should reify events from the signal") { + let (signal, observer) = Signal.pipe() + var latestEvent: Signal.Event? + signal + .materialize() + .observeValues { latestEvent = $0 } + + observer.send(value: 2) + + expect(latestEvent).toNot(beNil()) + if let latestEvent = latestEvent { + switch latestEvent { + case let .value(value): + expect(value) == 2 + default: + fail() + } + } + + observer.send(error: TestError.default) + if let latestEvent = latestEvent { + switch latestEvent { + case .failed: + () + default: + fail() + } + } + } + } + + describe("dematerialize") { + typealias IntEvent = Signal.Event + var observer: Signal.Observer! + var dematerialized: Signal! + + beforeEach { + let (signal, incomingObserver) = Signal.pipe() + observer = incomingObserver + dematerialized = signal.dematerialize() + } + + it("should send values for Value events") { + var result: [Int] = [] + dematerialized + .assumeNoErrors() + .observeValues { result.append($0) } + + expect(result).to(beEmpty()) + + observer.send(value: .value(2)) + expect(result) == [ 2 ] + + observer.send(value: .value(4)) + expect(result) == [ 2, 4 ] + } + + it("should error out for Error events") { + var errored = false + dematerialized.observeFailed { _ in errored = true } + + expect(errored) == false + + observer.send(value: .failed(TestError.default)) + expect(errored) == true + } + + it("should complete early for Completed events") { + var completed = false + dematerialized.observeCompleted { completed = true } + + expect(completed) == false + observer.send(value: IntEvent.completed) + expect(completed) == true + } + } + + describe("takeLast") { + var observer: Signal.Observer! + var lastThree: Signal! + + beforeEach { + let (signal, incomingObserver) = Signal.pipe() + observer = incomingObserver + lastThree = signal.take(last: 3) + } + + it("should send the last N values upon completion") { + var result: [Int] = [] + lastThree + .assumeNoErrors() + .observeValues { result.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + observer.send(value: 4) + expect(result).to(beEmpty()) + + observer.sendCompleted() + expect(result) == [ 2, 3, 4 ] + } + + it("should send less than N values if not enough were received") { + var result: [Int] = [] + lastThree + .assumeNoErrors() + .observeValues { result.append($0) } + + observer.send(value: 1) + observer.send(value: 2) + observer.sendCompleted() + expect(result) == [ 1, 2 ] + } + + it("should send nothing when errors") { + var result: [Int] = [] + var errored = false + lastThree.observe { event in + switch event { + case let .value(value): + result.append(value) + case .failed: + errored = true + default: + break + } + } + + observer.send(value: 1) + observer.send(value: 2) + observer.send(value: 3) + expect(errored) == false + + observer.send(error: TestError.default) + expect(errored) == true + expect(result).to(beEmpty()) + } + } + + describe("timeoutWithError") { + var testScheduler: TestScheduler! + var signal: Signal! + var observer: Signal.Observer! + + beforeEach { + testScheduler = TestScheduler() + let (baseSignal, incomingObserver) = Signal.pipe() + signal = baseSignal.timeout(after: 2, raising: TestError.default, on: testScheduler) + observer = incomingObserver + } + + it("should complete if within the interval") { + var completed = false + var errored = false + signal.observe { event in + switch event { + case .completed: + completed = true + case .failed: + errored = true + default: + break + } + } + + testScheduler.schedule(after: .seconds(1)) { + observer.sendCompleted() + } + + expect(completed) == false + expect(errored) == false + + testScheduler.run() + expect(completed) == true + expect(errored) == false + } + + it("should error if not completed before the interval has elapsed") { + var completed = false + var errored = false + signal.observe { event in + switch event { + case .completed: + completed = true + case .failed: + errored = true + default: + break + } + } + + testScheduler.schedule(after: .seconds(3)) { + observer.sendCompleted() + } + + expect(completed) == false + expect(errored) == false + + testScheduler.run() + expect(completed) == false + expect(errored) == true + } + + it("should be available for NoError") { + let signal: Signal = Signal.never + .timeout(after: 2, raising: TestError.default, on: testScheduler) + + _ = signal + } + } + + describe("attempt") { + it("should forward original values upon success") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attempt { _ in + return .success(()) + } + + var current: Int? + signal + .assumeNoErrors() + .observeValues { value in + current = value + } + + for value in 1...5 { + observer.send(value: value) + expect(current) == value + } + } + + it("should error if an attempt fails") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attempt { _ in + return .failure(.default) + } + + var error: TestError? + signal.observeFailed { err in + error = err + } + + observer.send(value: 42) + expect(error) == TestError.default + } + } + + describe("attempt throws") { + it("should forward original values upon success") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attempt { _ in + _ = try operation(value: 1) + } + + var current: Int? + signal + .assumeNoErrors() + .observeValues { value in + current = value + } + + for value in 1...5 { + observer.send(value: value) + expect(current) == value + } + } + + it("should error if an attempt fails") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attempt { _ in + _ = try operation(value: nil) as Int + } + + var error: TestError? + signal.observeFailed { err in + error = err.error as? TestError + } + + observer.send(value: 42) + expect(error) == TestError.default + } + + it("should allow throwing closures with NoError") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attempt { _ in + _ = try operation(value: 1) + } + + var value: Int? + signal.observeResult { value = $0.value } + + observer.send(value: 42) + expect(value) == 42 + } + } + + describe("attemptMap") { + it("should forward mapped values upon success") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attemptMap { num -> Result in + return .success(num % 2 == 0) + } + + var even: Bool? + signal + .assumeNoErrors() + .observeValues { value in + even = value + } + + observer.send(value: 1) + expect(even) == false + + observer.send(value: 2) + expect(even) == true + } + + it("should error if a mapping fails") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attemptMap { _ -> Result in + return .failure(.default) + } + + var error: TestError? + signal.observeFailed { err in + error = err + } + + observer.send(value: 42) + expect(error) == TestError.default + } + } + + describe("attemptMap throws") { + it("should forward mapped values upon success") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attemptMap { num -> Bool in + try operation(value: num % 2 == 0) + } + + var even: Bool? + signal + .assumeNoErrors() + .observeValues { value in + even = value + } + + observer.send(value: 1) + expect(even) == false + + observer.send(value: 2) + expect(even) == true + } + + it("should error if a mapping fails") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attemptMap { _ -> Bool in + try operation(value: nil) + } + + var error: TestError? + signal.observeFailed { err in + error = err.error as? TestError + } + + observer.send(value: 42) + expect(error) == TestError.default + } + + it("should allow throwing closures with NoError") { + let (baseSignal, observer) = Signal.pipe() + let signal = baseSignal.attemptMap { num in + try operation(value: num % 2 == 0) + } + + var value: Bool? + signal.observeResult { value = $0.value } + + observer.send(value: 2) + expect(value) == true + } + } + + describe("combinePrevious") { + var observer: Signal.Observer! + let initialValue: Int = 0 + var latestValues: (Int, Int)? + + beforeEach { + latestValues = nil + + let (signal, baseObserver) = Signal.pipe() + observer = baseObserver + signal.combinePrevious(initialValue).observeValues { latestValues = $0 } + } + + it("should forward the latest value with previous value") { + expect(latestValues).to(beNil()) + + observer.send(value: 1) + expect(latestValues?.0) == initialValue + expect(latestValues?.1) == 1 + + observer.send(value: 2) + expect(latestValues?.0) == 1 + expect(latestValues?.1) == 2 + } + } + + describe("combineLatest") { + var signalA: Signal! + var signalB: Signal! + var signalC: Signal! + var observerA: Signal.Observer! + var observerB: Signal.Observer! + var observerC: Signal.Observer! + + var combinedValues: [Int]? + var completed: Bool! + + beforeEach { + combinedValues = nil + completed = false + + let (baseSignalA, baseObserverA) = Signal.pipe() + let (baseSignalB, baseObserverB) = Signal.pipe() + let (baseSignalC, baseObserverC) = Signal.pipe() + + signalA = baseSignalA + signalB = baseSignalB + signalC = baseSignalC + + observerA = baseObserverA + observerB = baseObserverB + observerC = baseObserverC + } + + let combineLatestExampleName = "combineLatest examples" + sharedExamples(combineLatestExampleName) { + it("should forward the latest values from all inputs"){ + expect(combinedValues).to(beNil()) + + observerA.send(value: 0) + observerB.send(value: 1) + observerC.send(value: 2) + expect(combinedValues) == [0, 1, 2] + + observerA.send(value: 10) + expect(combinedValues) == [10, 1, 2] + } + + it("should not forward the latest values before all inputs"){ + expect(combinedValues).to(beNil()) + + observerA.send(value: 0) + expect(combinedValues).to(beNil()) + + observerB.send(value: 1) + expect(combinedValues).to(beNil()) + + observerC.send(value: 2) + expect(combinedValues) == [0, 1, 2] + } + + it("should complete when all inputs have completed"){ + expect(completed) == false + + observerA.sendCompleted() + observerB.sendCompleted() + expect(completed) == false + + observerC.sendCompleted() + expect(completed) == true + } + } + + describe("tuple") { + beforeEach { + Signal.combineLatest(signalA, signalB, signalC) + .observe { event in + switch event { + case let .value(value): + combinedValues = [value.0, value.1, value.2] + case .completed: + completed = true + default: + break + } + } + } + + itBehavesLike(combineLatestExampleName) + } + + describe("sequence") { + beforeEach { + Signal.combineLatest([signalA, signalB, signalC]) + .observe { event in + switch event { + case let .value(values): + combinedValues = values + case .completed: + completed = true + default: + break + } + } + } + + itBehavesLike(combineLatestExampleName) + } + } + + describe("zip") { + var signalA: Signal! + var signalB: Signal! + var signalC: Signal! + var observerA: Signal.Observer! + var observerB: Signal.Observer! + var observerC: Signal.Observer! + + var zippedValues: [Int]? + var completed: Bool! + + beforeEach { + zippedValues = nil + completed = false + + let (baseSignalA, baseObserverA) = Signal.pipe() + let (baseSignalB, baseObserverB) = Signal.pipe() + let (baseSignalC, baseObserverC) = Signal.pipe() + + signalA = baseSignalA + signalB = baseSignalB + signalC = baseSignalC + + observerA = baseObserverA + observerB = baseObserverB + observerC = baseObserverC + } + + let zipExampleName = "zip examples" + sharedExamples(zipExampleName) { + it("should combine all set"){ + expect(zippedValues).to(beNil()) + + observerA.send(value: 0) + expect(zippedValues).to(beNil()) + + observerB.send(value: 1) + expect(zippedValues).to(beNil()) + + observerC.send(value: 2) + expect(zippedValues) == [0, 1, 2] + + observerA.send(value: 10) + expect(zippedValues) == [0, 1, 2] + + observerA.send(value: 20) + expect(zippedValues) == [0, 1, 2] + + observerB.send(value: 11) + expect(zippedValues) == [0, 1, 2] + + observerC.send(value: 12) + expect(zippedValues) == [10, 11, 12] + } + + it("should complete when the shorter signal has completed"){ + expect(completed) == false + + observerB.send(value: 1) + observerC.send(value: 2) + observerB.sendCompleted() + observerC.sendCompleted() + expect(completed) == false + + observerA.send(value: 0) + expect(completed) == true + } + } + + describe("tuple") { + beforeEach { + Signal.zip(signalA, signalB, signalC) + .observe { event in + switch event { + case let .value(value): + zippedValues = [value.0, value.1, value.2] + case .completed: + completed = true + default: + break + } + } + } + + itBehavesLike(zipExampleName) + } + + describe("sequence") { + beforeEach { + Signal.zip([signalA, signalB, signalC]) + .observe { event in + switch event { + case let .value(values): + zippedValues = values + case .completed: + completed = true + default: + break + } + } + } + + itBehavesLike(zipExampleName) + } + + describe("log events") { + it("should output the correct event without identifier") { + let expectations: [(String) -> Void] = [ + { event in expect(event) == "[] value 1" }, + { event in expect(event) == "[] completed" }, + { event in expect(event) == "[] terminated" }, + { event in expect(event) == "[] disposed" }, + ] + + let logger = TestLogger(expectations: expectations) + + let (signal, observer) = Signal.pipe() + signal + .logEvents(logger: logger.logEvent) + .observe { _ in } + + observer.send(value: 1) + observer.sendCompleted() + } + + it("should output the correct event with identifier") { + let expectations: [(String) -> Void] = [ + { event in expect(event) == "[test.rac] value 1" }, + { event in expect(event) == "[test.rac] failed error1" }, + { event in expect(event) == "[test.rac] terminated" }, + { event in expect(event) == "[test.rac] disposed" }, + ] + + let logger = TestLogger(expectations: expectations) + + let (signal, observer) = Signal.pipe() + signal + .logEvents(identifier: "test.rac", logger: logger.logEvent) + .observe { _ in } + + observer.send(value: 1) + observer.send(error: .error1) + } + + it("should only output the events specified in the `events` parameter") { + let expectations: [(String) -> Void] = [ + { event in expect(event) == "[test.rac] failed error1" }, + ] + + let logger = TestLogger(expectations: expectations) + + let (signal, observer) = Signal.pipe() + signal + .logEvents(identifier: "test.rac", events: [.failed], logger: logger.logEvent) + .observe { _ in } + + observer.send(value: 1) + observer.send(error: .error1) + } + } + } + + describe("negated attribute") { + it("should return the negate of a value in a Boolean signal") { + let (signal, observer) = Signal.pipe() + signal.negate().observeValues { value in + expect(value).to(beFalse()) + } + observer.send(value: true) + observer.sendCompleted() + } + } + + describe("and attribute") { + it("should emit true when both signals emits the same value") { + let (signal1, observer1) = Signal.pipe() + let (signal2, observer2) = Signal.pipe() + signal1.and(signal2).observeValues { value in + expect(value).to(beTrue()) + } + observer1.send(value: true) + observer2.send(value: true) + + observer1.sendCompleted() + observer2.sendCompleted() + } + + it("should emit false when both signals emits opposite values") { + let (signal1, observer1) = Signal.pipe() + let (signal2, observer2) = Signal.pipe() + signal1.and(signal2).observeValues { value in + expect(value).to(beFalse()) + } + observer1.send(value: false) + observer2.send(value: true) + + observer1.sendCompleted() + observer2.sendCompleted() + } + } + + describe("or attribute") { + it("should emit true when at least one of the signals emits true") { + let (signal1, observer1) = Signal.pipe() + let (signal2, observer2) = Signal.pipe() + signal1.or(signal2).observeValues { value in + expect(value).to(beTrue()) + } + observer1.send(value: true) + observer2.send(value: false) + + observer1.sendCompleted() + observer2.sendCompleted() + } + + it("should emit false when both signals emits false") { + let (signal1, observer1) = Signal.pipe() + let (signal2, observer2) = Signal.pipe() + signal1.or(signal2).observeValues { value in + expect(value).to(beFalse()) + } + observer1.send(value: false) + observer2.send(value: false) + + observer1.sendCompleted() + observer2.sendCompleted() + } + } + + describe("promoteError") { + it("should infer the error type from the context") { + let combined: Any = Signal + .combineLatest(Signal.never.promoteError(), + Signal.never, + Signal.never.promoteError(), + Signal.never.flatMapError { _ in .empty }) + + expect(combined is Signal<(Int, Double, Float, UInt), TestError>) == true + } + } + + describe("promoteValue") { + it("should infer the value type from the context") { + let completable = Signal.never + let producer: Signal = Signal.never + .flatMap(.latest) { _ in completable.promoteValue() } + + expect((producer as Any) is Signal) == true + } + } + } +} + +private func operation(value: T?) throws -> T { + guard let value = value else { throw TestError.default } + return value +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/TestError.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/TestError.swift new file mode 100644 index 0000000..cdfba37 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/TestError.swift @@ -0,0 +1,43 @@ +// +// TestError.swift +// ReactiveSwift +// +// Created by Almas Sapargali on 1/26/15. +// Copyright (c) 2015 GitHub. All rights reserved. +// + +import ReactiveSwift +import Result + +internal enum TestError: Int { + case `default` = 0 + case error1 = 1 + case error2 = 2 +} + +extension TestError: Error { +} + + +internal extension SignalProducer { + /// Halts if an error is emitted in the receiver signal. + /// This is useful in tests to be able to just use `startWithNext` + /// in cases where we know that an error won't be emitted. + func assumeNoErrors() -> SignalProducer { + return self.lift { $0.assumeNoErrors() } + } +} + +internal extension Signal { + /// Halts if an error is emitted in the receiver signal. + /// This is useful in tests to be able to just use `startWithNext` + /// in cases where we know that an error won't be emitted. + func assumeNoErrors() -> Signal { + return self.mapError { error in + fatalError("Unexpected error: \(error)") + + () + } + } +} + diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/TestLogger.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/TestLogger.swift new file mode 100644 index 0000000..bc66927 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/TestLogger.swift @@ -0,0 +1,24 @@ +// +// TestLogger.swift +// ReactiveSwift +// +// Created by Rui Peres on 29/04/2016. +// Copyright © 2016 GitHub. All rights reserved. +// + +import Foundation +@testable import ReactiveSwift + +final class TestLogger { + fileprivate var expectations: [(String) -> Void] + + init(expectations: [(String) -> Void]) { + self.expectations = expectations + } +} + +extension TestLogger { + func logEvent(_ identifier: String, event: String, fileName: String, functionName: String, lineNumber: Int) { + expectations.removeFirst()("[\(identifier)] \(event)") + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/UnidirectionalBindingSpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/UnidirectionalBindingSpec.swift new file mode 100644 index 0000000..7153068 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/UnidirectionalBindingSpec.swift @@ -0,0 +1,135 @@ +import Dispatch + +import Result +import Nimble +import Quick +@testable import ReactiveSwift + +class UnidirectionalBindingSpec: QuickSpec { + override func spec() { + describe("BindingTarget") { + var token: Lifetime.Token! + var lifetime: Lifetime! + var target: BindingTarget! + var optionalTarget: BindingTarget! + var value: Int? + + beforeEach { + token = Lifetime.Token() + lifetime = Lifetime(token) + target = BindingTarget(lifetime: lifetime, action: { value = $0 }) + optionalTarget = BindingTarget(lifetime: lifetime, action: { value = $0 }) + value = nil + } + + describe("non-optional target") { + it("should pass through the lifetime") { + expect(target.lifetime).to(beIdenticalTo(lifetime)) + } + + it("should trigger the supplied setter") { + expect(value).to(beNil()) + + target.action(1) + expect(value) == 1 + } + + it("should accept bindings from properties") { + expect(value).to(beNil()) + + let property = MutableProperty(1) + target <~ property + expect(value) == 1 + + property.value = 2 + expect(value) == 2 + } + } + + describe("optional target") { + it("should pass through the lifetime") { + expect(optionalTarget.lifetime).to(beIdenticalTo(lifetime)) + } + + it("should trigger the supplied setter") { + expect(value).to(beNil()) + + optionalTarget.action(1) + expect(value) == 1 + } + + it("should accept bindings from properties") { + expect(value).to(beNil()) + + let property = MutableProperty(1) + optionalTarget <~ property + expect(value) == 1 + + property.value = 2 + expect(value) == 2 + } + } + + it("should not deadlock on the same queue") { + target = BindingTarget(on: UIScheduler(), + lifetime: lifetime, + action: { value = $0 }) + + let property = MutableProperty(1) + target <~ property + expect(value) == 1 + } + + it("should not deadlock on the main thread even if the context was switched to a different queue") { + let queue = DispatchQueue(label: #file) + + target = BindingTarget(on: UIScheduler(), + lifetime: lifetime, + action: { value = $0 }) + + let property = MutableProperty(1) + + queue.sync { + _ = target <~ property + } + + expect(value).toEventually(equal(1)) + } + + it("should not deadlock even if the value is originated from the same queue indirectly") { + let key = DispatchSpecificKey() + DispatchQueue.main.setSpecific(key: key, value: ()) + + let mainQueueCounter = Atomic(0) + + let setter: (Int) -> Void = { + value = $0 + mainQueueCounter.modify { $0 += DispatchQueue.getSpecific(key: key) != nil ? 1 : 0 } + } + + target = BindingTarget(on: UIScheduler(), + lifetime: lifetime, + action: setter) + + let scheduler: QueueScheduler + if #available(OSX 10.10, *) { + scheduler = QueueScheduler() + } else { + scheduler = QueueScheduler(queue: DispatchQueue(label: "com.reactivecocoa.ReactiveSwift.UnidirectionalBindingSpec")) + } + + let property = MutableProperty(1) + target <~ property.producer + .start(on: scheduler) + .observe(on: scheduler) + + expect(value).toEventually(equal(1)) + expect(mainQueueCounter.value).toEventually(equal(1)) + + property.value = 2 + expect(value).toEventually(equal(2)) + expect(mainQueueCounter.value).toEventually(equal(2)) + } + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ValidatingPropertySpec.swift b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ValidatingPropertySpec.swift new file mode 100644 index 0000000..6c76f60 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/Tests/ReactiveSwiftTests/ValidatingPropertySpec.swift @@ -0,0 +1,304 @@ +import Quick +import Nimble +import ReactiveSwift +import Result + +class ValidatingPropertySpec: QuickSpec { + override func spec() { + describe("ValidatingProperty") { + describe("no dependency") { + var root: MutableProperty! + var validated: ValidatingProperty! + var validationResult: FlattenedResult? + + beforeEach { + root = MutableProperty(0) + validated = ValidatingProperty(root) { $0 >= 0 ? ($0 == 100 ? .coerced(Int.max, .default) : .valid) : .invalid(.default) } + + validated.result.signal.observeValues { validationResult = FlattenedResult($0) } + + expect(validated.value) == 0 + expect(FlattenedResult(validated.result.value)) == FlattenedResult.valid(0) + expect(validationResult).to(beNil()) + } + + afterEach { + validationResult = nil + + weak var weakRoot = root + expect(weakRoot).notTo(beNil()) + + root = nil + expect(weakRoot).notTo(beNil()) + + validated = nil + expect(weakRoot).to(beNil()) + + } + + it("should let valid values get through") { + validated.value = 10 + + expect(validated.value) == 10 + expect(validationResult) == .valid(10) + } + + it("should denote the substitution") { + validated.value = 100 + + expect(validated.value) == Int.max + expect(validationResult) == .coerced(Int.max, 100, .default) + } + + it("should block invalid values") { + validated.value = -10 + + expect(validated.value) == 0 + expect(validationResult) == .errorDefault(-10) + } + + it("should validate changes originated from the root property") { + root.value = 10 + + expect(validated.value) == 10 + expect(validationResult) == .valid(10) + + root.value = -10 + + expect(validated.value) == -10 + expect(validationResult) == .errorDefault(-10) + } + } + + describe("a MutablePropertyProtocol dependency") { + var other: MutableProperty! + var validated: ValidatingProperty! + var validationResult: FlattenedResult? + + beforeEach { + other = MutableProperty("") + validated = ValidatingProperty(0, with: other) { $0 >= 0 && $1 == "🎃" ? ($0 == 100 ? .coerced(Int.max, .default) : .valid) : .invalid(.default) } + + validated.result.signal.observeValues { validationResult = FlattenedResult($0) } + + expect(validated.value) == 0 + expect(FlattenedResult(validated.result.value)) == FlattenedResult.errorDefault(0) + expect(validationResult).to(beNil()) + } + + afterEach { + weak var weakOther = other + expect(weakOther).toNot(beNil()) + + other = nil + expect(weakOther).to(beNil()) + + validationResult = nil + } + + it("should let valid values get through") { + other.value = "🎃" + + validated.value = 10 + + expect(validated.value) == 10 + expect(validationResult) == .valid(10) + } + + it("should block invalid values") { + validated.value = -10 + + expect(validated.value) == 0 + expect(validationResult) == .errorDefault(-10) + } + + it("should denote the substitution") { + other.value = "🎃" + validated.value = 100 + + expect(validated.value) == Int.max + expect(validationResult) == .coerced(Int.max, 100, .default) + } + + it("should automatically revalidate the latest failed value if the dependency changes") { + validated.value = 10 + + expect(validated.value) == 0 + expect(validationResult) == .errorDefault(10) + + other.value = "🎃" + + expect(validated.value) == 10 + expect(validationResult) == .valid(10) + } + + it("should automatically revalidate the latest substituted value if the dependency changes") { + validated.value = 100 + + expect(validated.value) == 0 + expect(validationResult) == .errorDefault(100) + + other.value = "🎃" + + expect(validated.value) == Int.max + expect(validationResult) == .coerced(Int.max, 100, .default) + + validated.value = -1 + + expect(validated.value) == Int.max + expect(validationResult) == .errorDefault(-1) + } + } + + describe("a ValidatingProperty dependency") { + var other: ValidatingProperty! + var validated: ValidatingProperty! + var validationResult: FlattenedResult? + + beforeEach { + other = ValidatingProperty("") { $0.hasSuffix("🎃") && $0 != "🎃" ? .valid : .invalid(.error2) } + + validated = ValidatingProperty(0, with: other) { $0 >= 0 && $1.hasSuffix("🎃") ? ($0 == 100 ? .coerced(Int.max, .default) : .valid) : .invalid(.default) } + + validated.result.signal.observeValues { validationResult = FlattenedResult($0) } + + expect(validated.value) == 0 + expect(FlattenedResult(validated.result.value)) == FlattenedResult.errorDefault(0) + expect(validationResult).to(beNil()) + } + + afterEach { + weak var weakOther = other + expect(weakOther).toNot(beNil()) + + other = nil + expect(weakOther).to(beNil()) + + validationResult = nil + } + + it("should let valid values get through even if the dependency fails its validation") { + other.value = "🎃" + + validated.value = 10 + + expect(validated.value) == 10 + expect(validationResult) == .valid(10) + } + + it("should block invalid values") { + validated.value = -10 + + expect(validated.value) == 0 + expect(validationResult) == .errorDefault(-10) + } + + it("should denote the substitution") { + other.value = "🎃" + validated.value = 100 + + expect(validated.value) == Int.max + expect(validationResult) == .coerced(Int.max, 100, .default) + } + + it("should automatically revalidate the latest failed value if the dependency changes") { + validated.value = 10 + + expect(validated.value) == 0 + expect(validationResult) == .errorDefault(10) + + other.value = "🎃" + + expect(validated.value) == 10 + expect(validationResult) == .valid(10) + } + + it("should automatically revalidate the latest substituted value if the dependency changes") { + validated.value = 100 + + expect(validated.value) == 0 + expect(validationResult) == .errorDefault(100) + + other.value = "🎃" + + expect(validated.value) == Int.max + expect(validationResult) == .coerced(Int.max, 100, .default) + + validated.value = -1 + + expect(validated.value) == Int.max + expect(validationResult) == .errorDefault(-1) + } + + it("should automatically revalidate the latest failed value whenever the dependency has been proposed a new input") { + validated.value = 10 + + expect(validated.value) == 0 + expect(validationResult) == .errorDefault(10) + + other.value = "🎃" + + expect(other.value) == "" + expect(FlattenedResult(other.result.value)) == FlattenedResult.error2("🎃") + + expect(validated.value) == 10 + expect(validationResult) == .valid(10) + + other.value = "👻🎃" + + expect(other.value) == "👻🎃" + expect(FlattenedResult(other.result.value)) == FlattenedResult.valid("👻🎃") + + expect(validated.value) == 10 + expect(validationResult) == .valid(10) + } + } + } + } +} + +private enum FlattenedResult: Equatable { + case errorDefault(Value) + case error1(Value) + case error2(Value) + + case valid(Value) + case coerced(Value, Value, TestError?) + + init(_ result: ValidationResult) { + switch result { + case let .valid(value): + self = .valid(value) + + case let .coerced(substitutedValue, proposedValue, error): + self = .coerced(substitutedValue, proposedValue, error) + + case let .invalid(value, error): + switch error { + case .default: + self = .errorDefault(value) + case .error1: + self = .error1(value) + case .error2: + self = .error2(value) + } + } + } + + static func ==(left: FlattenedResult, right: FlattenedResult) -> Bool { + switch (left, right) { + case (let .errorDefault(lhsValue), let .errorDefault(rhsValue)): + return lhsValue == rhsValue + case (let .error1(lhsValue), let .error1(rhsValue)): + return lhsValue == rhsValue + case (let .error2(lhsValue), let .error2(rhsValue)): + return lhsValue == rhsValue + case (let .valid(lhsValue), let .valid(rhsValue)): + return lhsValue == rhsValue + case (let .coerced(lhsSubstitution, lhsProposed, lhsError), let .coerced(rhsSubstitution, rhsProposed, rhsError)): + return lhsSubstitution == rhsSubstitution && lhsProposed == rhsProposed && lhsError == rhsError + default: + return false + } + } +} diff --git a/Carthage/Checkouts/ReactiveSwift/script/build b/Carthage/Checkouts/ReactiveSwift/script/build new file mode 100755 index 0000000..e36726e --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/script/build @@ -0,0 +1,52 @@ +#!/bin/bash + +BUILD_DIRECTORY="build" +CONFIGURATION=Release + +if [[ -z $TRAVIS_XCODE_WORKSPACE ]]; then + echo "Error: \$TRAVIS_XCODE_WORKSPACE is not set." + exit 1 +fi + +if [[ -z $TRAVIS_XCODE_SCHEME ]]; then + echo "Error: \$TRAVIS_XCODE_SCHEME is not set!" + exit 1 +fi + +if [[ -z $XCODE_ACTION ]]; then + echo "Error: \$XCODE_ACTION is not set!" + exit 1 +fi + +if [[ -z $XCODE_SDK ]]; then + echo "Error: \$XCODE_SDK is not set!" + exit 1 +fi + +if [[ -z $XCODE_DESTINATION ]]; then + echo "Error: \$XCODE_DESTINATION is not set!" + exit 1 +fi + +set -o pipefail +xcodebuild $XCODE_ACTION \ + -workspace "$TRAVIS_XCODE_WORKSPACE" \ + -scheme "$TRAVIS_XCODE_SCHEME" \ + -sdk "$XCODE_SDK" \ + -destination "$XCODE_DESTINATION" \ + -derivedDataPath "${BUILD_DIRECTORY}" \ + -configuration $CONFIGURATION \ + ENABLE_TESTABILITY=YES \ + GCC_GENERATE_DEBUGGING_SYMBOLS=NO \ + RUN_CLANG_STATIC_ANALYZER=NO | xcpretty +result=$? + +if [ "$result" -ne 0 ]; then + exit $result +fi + +# Compile code in playgrounds +if [[ $XCODE_SDK = "macosx" ]]; then + echo "SDK is $XCODE_SDK, validating playground..." + . script/validate-playground.sh +fi diff --git a/Carthage/Checkouts/ReactiveSwift/script/feed.xml.template b/Carthage/Checkouts/ReactiveSwift/script/feed.xml.template new file mode 100644 index 0000000..9125d8b --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/script/feed.xml.template @@ -0,0 +1,4 @@ + + FRAMEWORK_VERSION + http://reactivecocoa.io/reactiveswift/docs/latest/docsets/ReactiveSwift.tgz + diff --git a/Carthage/Checkouts/ReactiveSwift/script/gen-docs b/Carthage/Checkouts/ReactiveSwift/script/gen-docs new file mode 100755 index 0000000..8ea5fa0 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/script/gen-docs @@ -0,0 +1,93 @@ +#!/bin/bash + +if [[ -z "$TRAVIS_TAG" ]]; then + echo "Not a tag build. Abort." + exit 0 +fi + +if [[ -z "$RAC_CIBOT_TOKEN" ]]; then + echo "CI bot token is undefined. Abort." + exit 0 +fi + +if [[ -z "$RAC_CIBOT_USERNAME" ]]; then + echo "CI bot username is undefined. Abort." + exit 0 +fi + +echo "Documentation builder. The tag is \`${TRAVIS_TAG}\`." + +rvm use 2.3 +gem install jazzy +jazzy + +if [[ $? -ne 0 ]]; then + echo "Jazzy has failed. Aborting the push." + exit 1 +fi + +brew install hub +export GITHUB_TOKEN=${RAC_CIBOT_TOKEN} + +# Clone the master branch of the website. +git clone -b master --single-branch https://${RAC_CIBOT_TOKEN}@github.com/ReactiveCocoa/ReactiveCocoa.github.io.git RACSite +cd ./RACSite + +# Fork the repo without fetching it. +hub fork --no-remote +git remote add cibot https://${RAC_CIBOT_TOKEN}@github.com/${RAC_CIBOT_USERNAME}/ReactiveCocoa.github.io.git +git checkout master + +# Create a new branch for the release. +git checkout -b ras-${TRAVIS_TAG} + +DOC_PATH=./reactiveswift/docs/${TRAVIS_TAG} + +# Copy the generated docs. +mkdir -p ${DOC_PATH} +cp -r ../docs/. ${DOC_PATH} + +# Copy the icons, and archive the docset. +rm ${DOC_PATH}/docsets/ReactiveSwift.tgz + +DOCSET_IMG_PATH=${DOC_PATH}/docsets/ReactiveSwift.docset/Contents/Resources/Documents/Logo/PNG +mkdir -p ${DOCSET_IMG_PATH} +cp ../Logo/PNG/logo-Swift.png ${DOCSET_IMG_PATH}/logo-Swift.png +cp ../Logo/PNG/JoinSlack.png ${DOCSET_IMG_PATH}/JoinSlack.png +cp ../Logo/PNG/Docs.png ${DOCSET_IMG_PATH}/Docs.png +cp ../Logo/Icons/docset-icon.png ${DOC_PATH}/docsets/ReactiveSwift.docset/icon.png +cp ../Logo/Icons/docset-icon@2x.png ${DOC_PATH}/docsets/ReactiveSwift.docset/icon@2x.png +tar --exclude='.DS_Store' -cvzf ${DOC_PATH}/docsets/ReactiveSwift.tgz -C ${DOC_PATH}/docsets/ . +rm -rf ${DOC_PATH}/docsets/ReactiveSwift.docset/ + +# Copy image assets used by README.md. +mkdir -p ${DOC_PATH}/Logo/PNG/ +cp ../Logo/PNG/logo-Swift.png ${DOC_PATH}/Logo/PNG/logo-Swift.png +cp ../Logo/PNG/JoinSlack.png ${DOC_PATH}/Logo/PNG/JoinSlack.png +cp ../Logo/PNG/Docs.png ${DOC_PATH}/Logo/PNG/Docs.png + +git add ${DOC_PATH} + +# Ensure Jekyll is not running in `docs`. +touch ./reactiveswift/docs/.nojekyll +git add ./reactiveswift/docs/.nojekyll + +# Update the `latest` symlink. +ln -sfn ${TRAVIS_TAG}/ reactiveswift/docs/latest +git add ./reactiveswift/docs/latest + +# Update the docset feed. +rm ./reactiveswift/docs/ReactiveSwift.xml +cp ../script/feed.xml.template ./reactiveswift/docs/ReactiveSwift.xml +sed -i -- "s/FRAMEWORK_VERSION/${TRAVIS_TAG}/g" ./reactiveswift/docs/ReactiveSwift.xml +git add ./reactiveswift/docs/ReactiveSwift.xml + +# Commit and push to the fork. +git commit -m "Documentation: ReactiveSwift ${TRAVIS_TAG}" +git push -u cibot ras-${TRAVIS_TAG} + +# Open a pull request in the main repo. +hub pull-request -m "Documentation: ReactiveSwift ${TRAVIS_TAG}" -h "${RAC_CIBOT_USERNAME}:ras-${TRAVIS_TAG}" + +cd .. +rm -rf ./RACSite diff --git a/Carthage/Checkouts/ReactiveSwift/script/update-version b/Carthage/Checkouts/ReactiveSwift/script/update-version new file mode 100755 index 0000000..34dbb05 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/script/update-version @@ -0,0 +1,24 @@ +#!/bin/bash + +if [[ -z "$1" ]]; then + echo "Please specify a version tag." + exit +fi + +PRERELEASE_STRIPPED=$(echo "$1" | perl -0777 -ne '/([0-9]+)\.([0-9]+)\.([0-9]+)(-.*)?/ and print "$1.$2.$3"') + +if [[ -z "$PRERELEASE_STRIPPED" ]]; then + echo "The version tag is not semver compliant." + exit +fi + +CURRENT_TAG=$(perl -0777 -ne '/s.version([\s]+)=([\s]+)"(.+)"/ and print $3' *.podspec) +echo "Current tag: $CURRENT_TAG" + +perl -0777 -i -pe 's/s.version([\s]+)=([\s]+)"'${CURRENT_TAG}'"/s.version$1=$2"'${1}'"/' *.podspec +perl -0777 -i -pe 's/g>'${CURRENT_TAG}'<\/str/g>'${PRERELEASE_STRIPPED}'<\/str/' */Info.plist +perl -0777 -i -pe 's/g>'${CURRENT_TAG}'<\/str/g>'${PRERELEASE_STRIPPED}'<\/str/' */*/Info.plist +sed -i '' '3i\ +\ +# '${1} CHANGELOG.md + diff --git a/Carthage/Checkouts/ReactiveSwift/script/validate-playground.sh b/Carthage/Checkouts/ReactiveSwift/script/validate-playground.sh new file mode 100755 index 0000000..b262332 --- /dev/null +++ b/Carthage/Checkouts/ReactiveSwift/script/validate-playground.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Bash script to lint the content of playgrounds +# Heavily based on RxSwift's +# https://github.com/ReactiveX/RxSwift/blob/master/scripts/validate-playgrounds.sh + +if [ -z "$BUILD_DIRECTORY" ]; then + echo "\$BUILD_DIRECTORY is not set. Are you trying to run \`validate-playgrounds.sh\` without building RAC first?\n" + echo "To validate the playground, run \`script/build\`." + exit 1 +fi + +if [ -z "$XCODE_PLAYGROUND_TARGET" ]; then + echo "\$XCODE_PLAYGROUND_TARGET is not set." + exit 1 +fi + +PAGES_PATH=${BUILD_DIRECTORY}/Build/Products/${CONFIGURATION}/all-playground-pages.swift + +cat ReactiveSwift.playground/Sources/*.swift ReactiveSwift.playground/Pages/**/*.swift > ${PAGES_PATH} + +swift -v -target ${XCODE_PLAYGROUND_TARGET} -D NOT_IN_PLAYGROUND -F ${BUILD_DIRECTORY}/Build/Products/${CONFIGURATION} ${PAGES_PATH} > /dev/null +result=$? + +# Cleanup +rm -Rf $BUILD_DIRECTORY + +exit $result 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..9f55b2c --- /dev/null +++ b/Carthage/Checkouts/Result/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/Carthage/Checkouts/Result/.travis.yml b/Carthage/Checkouts/Result/.travis.yml new file mode 100644 index 0000000..17ee849 --- /dev/null +++ b/Carthage/Checkouts/Result/.travis.yml @@ -0,0 +1,44 @@ +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 1080p" | xcpretty + - xcodebuild build -scheme Result-watchOS -sdk watchsimulator | xcpretty + # - pod lib lint + env: + - JOB=Xcode + - XCODE_ACTION="build-for-testing test-without-building" + os: osx + osx_image: xcode8 + language: objective-c + - script: + - swift build + - swift test + env: JOB=SPM + os: osx + osx_image: xcode8 + language: objective-c + - script: + - 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)" + - script: + - swift build + - swift test + env: + - JOB=Linux + - SWIFT_VERSION=3.1-DEVELOPMENT-SNAPSHOT-2017-03-01-a + 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..3004377 --- /dev/null +++ b/Carthage/Checkouts/Result/Package.swift @@ -0,0 +1,10 @@ +import PackageDescription + +let package = Package( + name: "Result", + targets: [ + Target( + name: "Result" + ) + ] +) diff --git a/Carthage/Checkouts/Result/README.md b/Carthage/Checkouts/Result/README.md new file mode 100644 index 0000000..7343ade --- /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 in 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..06a136f --- /dev/null +++ b/Carthage/Checkouts/Result/Result.podspec @@ -0,0 +1,16 @@ +Pod::Spec.new do |s| + s.name = 'Result' + s.version = '3.2.3' + 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' +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..8700324 --- /dev/null +++ b/Carthage/Checkouts/Result/Result.xcodeproj/project.pbxproj @@ -0,0 +1,1024 @@ +// !$*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 */; }; + 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 = ""; }; + 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 = ( + 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 = ( + 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 = 0820; + ORGANIZATIONNAME = "Rob Rix"; + TargetAttributes = { + 57FCDE3C1BA280DC00130C48 = { + LastSwiftMigration = 0800; + }; + 57FCDE491BA280E000130C48 = { + LastSwiftMigration = 0800; + }; + D03579991B2B788F005D26AE = { + LastSwiftMigration = 0800; + }; + D45480561A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0800; + }; + D45480661A9572F5009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0800; + }; + D454807C1A957361009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0800; + }; + D45480861A957362009D7229 = { + CreatedOnToolsVersion = 6.3; + LastSwiftMigration = 0800; + }; + }; + }; + 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 = ( + 57FCDE3E1BA280DC00130C48 /* ResultProtocol.swift in Sources */, + 57FCDE3F1BA280DC00130C48 /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 57FCDE4C1BA280E000130C48 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 57FCDE4D1BA280E000130C48 /* ResultTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D035799A1B2B788F005D26AE /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 45AE89E61B3A6564007B99D7 /* ResultProtocol.swift in Sources */, + D035799B1B2B788F005D26AE /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480521A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E93621461B35596200948F2A /* ResultProtocol.swift in Sources */, + D45480971A957465009D7229 /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480631A9572F5009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D454806F1A9572F5009D7229 /* ResultTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480781A957361009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E93621471B35596200948F2A /* ResultProtocol.swift in Sources */, + D45480981A957465009D7229 /* Result.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D45480831A957362009D7229 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D45480991A9574B8009D7229 /* ResultTests.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; + SWIFT_VERSION = 3.0; + 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; + SWIFT_VERSION = 3.0; + 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; + SWIFT_VERSION = 3.0; + }; + 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; + SWIFT_VERSION = 3.0; + 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; + SWIFT_VERSION = 3.0; + }; + 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; + SWIFT_VERSION = 3.0; + }; + 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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + 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"; + 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_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = 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_OBJC_ROOT_CLASS = YES_ERROR; + 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"; + 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; + SWIFT_VERSION = 3.0; + 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; + SWIFT_VERSION = 3.0; + 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)"; + SWIFT_VERSION = 3.0; + }; + 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)"; + SWIFT_VERSION = 3.0; + }; + 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; + SWIFT_VERSION = 3.0; + 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; + SWIFT_VERSION = 3.0; + 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; + SWIFT_VERSION = 3.0; + }; + 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; + SWIFT_VERSION = 3.0; + 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/Info.plist b/Carthage/Checkouts/Result/Result/Info.plist new file mode 100644 index 0000000..c39d0d3 --- /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 + 3.2.3 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2015 Rob Rix. All rights reserved. + NSPrincipalClass + + + 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..158e11e --- /dev/null +++ b/Carthage/Checkouts/Result/Result/Result.swift @@ -0,0 +1,274 @@ +// 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(T) + case failure(Error) + + // MARK: Constructors + + /// Constructs a success wrapping a `value`. + public init(value: T) { + 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: T?, 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 -> T) { + self.init(attempt: f) + } + + /// Constructs a result from a function that uses `throw`, failing with `Error` if throws. + public init(attempt f: () throws -> T) { + 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 -> T { + 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: (T) -> 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 { + return analysis( + ifSuccess: { ".success(\($0))" }, + ifFailure: { ".failure(\($0))" }) + } + + + // MARK: CustomDebugStringConvertible + + public var debugDescription: String { + return description + } +} + +// MARK: - Derive result from failable closure + +public func materialize(_ f: () throws -> T) -> Result { + return materialize(try f()) +} + +public func materialize(_ f: @autoclosure () throws -> T) -> Result { + do { + return .success(try f()) + } catch { + return .failure(AnyError(error)) + } +} + +@available(*, deprecated, message: "Use the overload which returns `Result` instead") +public func materialize(_ f: () throws -> T) -> Result { + return materialize(try f()) +} + +@available(*, deprecated, message: "Use the overload which returns `Result` instead") +public func materialize(_ f: @autoclosure () throws -> T) -> Result { + do { + return .success(try f()) + } catch { +// This isn't great, but it lets us maintain compatibility until this deprecated +// method can be removed. +#if _runtime(_ObjC) + return .failure(error as NSError) +#else + // https://github.com/apple/swift-corelibs-foundation/blob/swift-3.0.2-RELEASE/Foundation/NSError.swift#L314 + let userInfo = _swift_Foundation_getErrorDefaultUserInfo(error) as? [String: Any] + let nsError = NSError(domain: error._domain, code: error._code, userInfo: userInfo) + return .failure(nsError) +#endif + } +} + +// MARK: - Cocoa API conveniences + +#if !os(Linux) + +/// 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) } +public func `try`(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> T?) -> Result { + var error: NSError? + return `try`(&error).map(Result.success) ?? .failure(error ?? Result.error(function: function, file: file, line: line)) +} + +/// 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) } +public func `try`(_ function: String = #function, file: String = #file, line: Int = #line, `try`: (NSErrorPointer) -> Bool) -> Result<(), NSError> { + var error: NSError? + return `try`(&error) ? + .success(()) + : .failure(error ?? Result<(), NSError>.error(function: function, file: file, line: line)) +} + +#endif + +// 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: - Errors + +/// 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 + } +} + +/// 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) + } +} + +// There appears to be a bug in Foundation on Linux which prevents this from working: +// https://bugs.swift.org/browse/SR-3565 +// Don't forget to comment the tests back in when removing this check when it's fixed! +#if !os(Linux) + +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 + } +} + +#endif + +// MARK: - migration support +extension Result { + @available(*, unavailable, renamed: "success") + public static func Success(_: T) -> Result { + fatalError() + } + + @available(*, unavailable, renamed: "failure") + public static func Failure(_: Error) -> Result { + fatalError() + } +} + +extension NSError { + @available(*, unavailable, renamed: "error(from:)") + public static func errorFromErrorType(_ error: Swift.Error) -> Self { + fatalError() + } +} + +import Foundation diff --git a/Carthage/Checkouts/Result/Result/ResultProtocol.swift b/Carthage/Checkouts/Result/Result/ResultProtocol.swift new file mode 100644 index 0000000..678f294 --- /dev/null +++ b/Carthage/Checkouts/Result/Result/ResultProtocol.swift @@ -0,0 +1,203 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +/// A type that can represent either failure with an error or success with a result value. +public protocol ResultProtocol { + associatedtype Value + associatedtype Error: Swift.Error + + /// Constructs a successful result wrapping a `value`. + init(value: Value) + + /// Constructs a failed result wrapping an `error`. + init(error: Error) + + /// Case analysis for ResultProtocol. + /// + /// Returns the value produced by appliying `ifFailure` to the error if self represents a failure, or `ifSuccess` to the result value if self represents a success. + func analysis(ifSuccess: (Value) -> U, ifFailure: (Error) -> U) -> U + + /// Returns the value if self represents a success, `nil` otherwise. + /// + /// A default implementation is provided by a protocol extension. Conforming types may specialize it. + var value: Value? { get } + + /// Returns the error if self represents a failure, `nil` otherwise. + /// + /// A default implementation is provided by a protocol extension. Conforming types may specialize it. + var error: Error? { get } +} + +public extension ResultProtocol { + + /// Returns the value if self represents a success, `nil` otherwise. + public var value: Value? { + return analysis(ifSuccess: { $0 }, ifFailure: { _ in nil }) + } + + /// Returns the error if self represents a failure, `nil` otherwise. + public var error: Error? { + return analysis(ifSuccess: { _ in nil }, ifFailure: { $0 }) + } + + /// 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 { + return analysis( + ifSuccess: transform, + ifFailure: Result.failure) + } + + /// 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 () -> R) -> Result<(Value, R.Value), Error> + where Error == R.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 { + return analysis( + ifSuccess: Result.success, + ifFailure: transform) + } + + /// 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 { + return analysis( + ifSuccess: { .success(success($0)) }, + ifFailure: { .failure(failure($0)) } + ) + } +} + +public extension ResultProtocol { + + // 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 () -> Self) -> Self { + return analysis( + ifSuccess: { _ in self }, + ifFailure: { _ in 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 ResultProtocol 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 + +infix operator &&& : LogicalConjunctionPrecedence + +/// Returns a Result with a tuple of `left` and `right` values if both are `Success`es, or re-wrapping the error of the earlier `Failure`. +@available(*, deprecated, renamed: "ResultProtocol.fanout(self:_:)") +public func &&& (left: L, right: @autoclosure () -> R) -> Result<(L.Value, R.Value), L.Error> + where L.Error == R.Error +{ + return left.fanout(right) +} + +precedencegroup ChainingPrecedence { + associativity: left + higherThan: TernaryPrecedence +} + +infix operator >>- : ChainingPrecedence + +/// Returns the result of applying `transform` to `Success`es’ values, or re-wrapping `Failure`’s errors. +/// +/// This is a synonym for `flatMap`. +@available(*, deprecated, renamed: "ResultProtocol.flatMap(self:_:)") +public func >>- (result: T, transform: (T.Value) -> Result) -> Result { + return result.flatMap(transform) +} + +/// 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 func == (left: T, right: T) -> Bool + where T.Value: Equatable, T.Error: Equatable +{ + 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 +} + +/// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values. +public func != (left: T, right: T) -> Bool + where T.Value: Equatable, T.Error: Equatable +{ + return !(left == right) +} + +/// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits. +public func ?? (left: T, right: @autoclosure () -> T.Value) -> T.Value { + return left.recover(right()) +} + +/// Returns `left` if it is a `Success`es, or `right` otherwise. Short-circuits. +public func ?? (left: T, right: @autoclosure () -> T) -> T { + return left.recover(with: right()) +} + +// MARK: - migration support +@available(*, unavailable, renamed: "ResultProtocol") +public typealias ResultType = ResultProtocol + +@available(*, unavailable, renamed: "Error") +public typealias ResultErrorType = Swift.Error + +@available(*, unavailable, renamed: "ErrorConvertible") +public typealias ErrorTypeConvertible = ErrorConvertible + +@available(*, deprecated, renamed: "ErrorConvertible") +public protocol ErrorProtocolConvertible: ErrorConvertible {} + +extension ResultProtocol { + @available(*, unavailable, renamed: "recover(with:)") + public func recoverWith(_ result: @autoclosure () -> Self) -> Self { + fatalError() + } +} + +extension ErrorConvertible { + @available(*, unavailable, renamed: "error(from:)") + public static func errorFromErrorType(_ error: Swift.Error) -> Self { + fatalError() + } +} diff --git a/Carthage/Checkouts/Result/Tests/LinuxMain.swift b/Carthage/Checkouts/Result/Tests/LinuxMain.swift new file mode 100644 index 0000000..b23e8fc --- /dev/null +++ b/Carthage/Checkouts/Result/Tests/LinuxMain.swift @@ -0,0 +1,8 @@ +import XCTest + +@testable import ResultTests + +XCTMain([ + testCase(ResultTests.allTests), + testCase(NoErrorTests.allTests), +]) diff --git a/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist b/Carthage/Checkouts/Result/Tests/ResultTests/Info.plist new file mode 100644 index 0000000..93e68d7 --- /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 + 3.2.3 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift b/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift new file mode 100644 index 0000000..04229ee --- /dev/null +++ b/Carthage/Checkouts/Result/Tests/ResultTests/ResultTests.swift @@ -0,0 +1,370 @@ +// Copyright (c) 2015 Rob Rix. All rights reserved. + +final class ResultTests: XCTestCase { + func testMapTransformsSuccesses() { + XCTAssertEqual(success.map { $0.characters.count } ?? 0, 7) + } + + func testMapRewrapsFailures() { + XCTAssertEqual(failure.map { $0.characters.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.characters.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) + } + +// These tests fail on linux, root cause possibly https://bugs.swift.org/browse/SR-3565 +// Try again when it's fixed + #if !os(Linux) + + 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") + } + + #endif + + // 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 = materialize(try tryIsSuccess("success")) + XCTAssert(result1 == success) + + let result2: Result = materialize { try tryIsSuccess("success") } + XCTAssert(result2 == success) + } + + func testMaterializeProducesFailures() { + let result1: Result = materialize(try tryIsSuccess(nil)) + XCTAssert(result1.error == error) + + let result2: Result = materialize { try tryIsSuccess(nil) } + XCTAssert(result2.error == error) + } + + // 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) + } + + // MARK: Cocoa API idioms + + #if !os(Linux) + + func testTryProducesFailuresForBooleanAPIWithErrorReturnedByReference() { + let result = `try` { attempt(true, succeed: false, error: $0) } + XCTAssertFalse(result ?? false) + XCTAssertNotNil(result.error) + } + + func testTryProducesFailuresForOptionalWithErrorReturnedByReference() { + let result = `try` { attempt(1, succeed: false, error: $0) } + XCTAssertEqual(result ?? 0, 0) + XCTAssertNotNil(result.error) + } + + func testTryProducesSuccessesForBooleanAPI() { + let result = `try` { attempt(true, succeed: true, error: $0) } + XCTAssertTrue(result ?? false) + XCTAssertNil(result.error) + } + + func testTryProducesSuccessesForOptionalAPI() { + let result = `try` { attempt(1, succeed: true, error: $0) } + XCTAssertEqual(result ?? 0, 1) + XCTAssertNil(result.error) + } + + #endif + + func testTryMapProducesSuccess() { + let result = success.tryMap(tryIsSuccess) + XCTAssert(result == success) + } + + func testTryMapProducesFailure() { + let result = Result.success("fail").tryMap(tryIsSuccess) + XCTAssert(result == failure) + } +} + +final class NoErrorTests: XCTestCase { + static var allTests: [(String, (NoErrorTests) -> () throws -> Void)] { + return [ ("testEquatable", testEquatable) ] + } + + func testEquatable() { + let foo = Result(1) + let bar = Result(1) + XCTAssertTrue(foo == bar) + } +} + +final class AnyErrorTests: XCTestCase { + static var allTests: [(String, (AnyErrorTests) -> () throws -> Void)] { + return [ ("testAnyError", testAnyError) ] + } + + func testAnyError() { + let error = Error.a + let anyErrorFromError = AnyError(error) + let anyErrorFromAnyError = AnyError(anyErrorFromError) + XCTAssertTrue(anyErrorFromError == anyErrorFromAnyError) + } +} + + +// MARK: - Fixtures + +private 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 + } +} + +#if !os(Linux) + +func attempt(_ value: T, succeed: Bool, error: NSErrorPointer) -> T? { + if succeed { + return value + } else { + error?.pointee = Result<(), NSError>.error() + return nil + } +} + +#endif + +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 + } +} + +#if os(Linux) + +extension ResultTests { + static var allTests: [(String, (ResultTests) -> () throws -> Void)] { + return [ + ("testMapTransformsSuccesses", testMapTransformsSuccesses), + ("testMapRewrapsFailures", testMapRewrapsFailures), + ("testInitOptionalSuccess", testInitOptionalSuccess), + ("testInitOptionalFailure", testInitOptionalFailure), + ("testFanout", testFanout), + ("testBimapTransformsSuccesses", testBimapTransformsSuccesses), + ("testBimapTransformsFailures", testBimapTransformsFailures), + ("testErrorsIncludeTheSourceFile", testErrorsIncludeTheSourceFile), + ("testErrorsIncludeTheSourceLine", testErrorsIncludeTheSourceLine), + ("testErrorsIncludeTheCallingFunction", testErrorsIncludeTheCallingFunction), + ("testTryCatchProducesSuccesses", testTryCatchProducesSuccesses), + ("testTryCatchProducesFailures", testTryCatchProducesFailures), + ("testTryCatchWithFunctionProducesSuccesses", testTryCatchWithFunctionProducesSuccesses), + ("testTryCatchWithFunctionCatchProducesFailures", testTryCatchWithFunctionCatchProducesFailures), + ("testMaterializeProducesSuccesses", testMaterializeProducesSuccesses), + ("testMaterializeProducesFailures", testMaterializeProducesFailures), + ("testRecoverProducesLeftForLeftSuccess", testRecoverProducesLeftForLeftSuccess), + ("testRecoverProducesRightForLeftFailure", testRecoverProducesRightForLeftFailure), + ("testRecoverWithProducesLeftForLeftSuccess", testRecoverWithProducesLeftForLeftSuccess), + ("testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess", testRecoverWithProducesRightSuccessForLeftFailureAndRightSuccess), + ("testRecoverWithProducesRightFailureForLeftFailureAndRightFailure", testRecoverWithProducesRightFailureForLeftFailureAndRightFailure), +// ("testTryProducesFailuresForBooleanAPIWithErrorReturnedByReference", testTryProducesFailuresForBooleanAPIWithErrorReturnedByReference), +// ("testTryProducesFailuresForOptionalWithErrorReturnedByReference", testTryProducesFailuresForOptionalWithErrorReturnedByReference), +// ("testTryProducesSuccessesForBooleanAPI", testTryProducesSuccessesForBooleanAPI), +// ("testTryProducesSuccessesForOptionalAPI", testTryProducesSuccessesForOptionalAPI), + ("testTryMapProducesSuccess", testTryMapProducesSuccess), + ("testTryMapProducesFailure", testTryMapProducesFailure), + +// These tests fail on linux, root cause possibly https://bugs.swift.org/browse/SR-3565 +// Try again when it's fixed +// ("testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError", testAnyErrorDelegatesLocalizedDescriptionToUnderlyingError), +// ("testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError", testAnyErrorDelegatesLocalizedFailureReasonToUnderlyingError), +// ("testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError", testAnyErrorDelegatesLocalizedRecoverySuggestionToUnderlyingError), +// ("testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError", testAnyErrorDelegatesLocalizedHelpAnchorToUnderlyingError), + ] + } +} + +#endif + +import Foundation +import Result +import XCTest diff --git a/Carthage/Checkouts/xcconfigs b/Carthage/Checkouts/xcconfigs index 2e77204..cc451b0 160000 --- a/Carthage/Checkouts/xcconfigs +++ b/Carthage/Checkouts/xcconfigs @@ -1 +1 @@ -Subproject commit 2e77204b59c3d97c24e5dd34966fb32c231194f0 +Subproject commit cc451b08e052b6146f5caf66bc1120420c529c7b diff --git a/ReactiveAnimation.xcodeproj/project.pbxproj b/ReactiveAnimation.xcodeproj/project.pbxproj index c475d76..8dc2e94 100644 --- a/ReactiveAnimation.xcodeproj/project.pbxproj +++ b/ReactiveAnimation.xcodeproj/project.pbxproj @@ -7,31 +7,177 @@ objects = { /* Begin PBXBuildFile section */ + 215BF00C1EF42857006A9B71 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 215BEFCF1EF4282A006A9B71 /* Result.framework */; }; + 215BF00D1EF4285E006A9B71 /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 215BEFFF1EF42837006A9B71 /* ReactiveSwift.framework */; }; + 215BF00E1EF42865006A9B71 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 215BEFD31EF4282A006A9B71 /* Result.framework */; }; + 215BF00F1EF4286B006A9B71 /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 215BF0031EF42837006A9B71 /* ReactiveSwift.framework */; }; + 215BF0291EF42956006A9B71 /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 215BF01B1EF4293E006A9B71 /* ReactiveCocoa.framework */; }; + 215BF02A1EF4295B006A9B71 /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 215BF01F1EF4293E006A9B71 /* ReactiveCocoa.framework */; }; + 215BF0431EF42FA9006A9B71 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04EE2661ABFC79200AC8E65 /* View.swift */; }; + 215BF0441EF42FAA006A9B71 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04EE2661ABFC79200AC8E65 /* View.swift */; }; D04EE1F01ABFB9AD00AC8E65 /* ReactiveAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = D04EE1EF1ABFB9AD00AC8E65 /* ReactiveAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; D04EE1F61ABFB9AD00AC8E65 /* ReactiveAnimation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE1EA1ABFB9AD00AC8E65 /* ReactiveAnimation.framework */; }; D04EE1FD1ABFB9AD00AC8E65 /* ReactiveAnimationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D04EE1FC1ABFB9AD00AC8E65 /* ReactiveAnimationTests.m */; }; D04EE22E1ABFBA1E00AC8E65 /* ReactiveAnimation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE2231ABFBA1E00AC8E65 /* ReactiveAnimation.framework */; }; D04EE2461ABFBB0200AC8E65 /* ReactiveAnimationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D04EE1FC1ABFB9AD00AC8E65 /* ReactiveAnimationTests.m */; }; D04EE2471ABFBB0400AC8E65 /* ReactiveAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = D04EE1EF1ABFB9AD00AC8E65 /* ReactiveAnimation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D04EE24E1ABFBB6900AC8E65 /* LlamaKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24C1ABFBB6900AC8E65 /* LlamaKit.framework */; }; - D04EE24F1ABFBB6900AC8E65 /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24D1ABFBB6900AC8E65 /* ReactiveCocoa.framework */; }; - D04EE2501ABFBB8500AC8E65 /* LlamaKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24C1ABFBB6900AC8E65 /* LlamaKit.framework */; }; D04EE2511ABFBB8500AC8E65 /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24D1ABFBB6900AC8E65 /* ReactiveCocoa.framework */; }; - D04EE2521ABFBB8900AC8E65 /* LlamaKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24C1ABFBB6900AC8E65 /* LlamaKit.framework */; }; - D04EE2531ABFBB8900AC8E65 /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24D1ABFBB6900AC8E65 /* ReactiveCocoa.framework */; }; - D04EE2541ABFBB9100AC8E65 /* LlamaKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24C1ABFBB6900AC8E65 /* LlamaKit.framework */; }; D04EE2551ABFBB9100AC8E65 /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24D1ABFBB6900AC8E65 /* ReactiveCocoa.framework */; }; - D04EE2571ABFBBB100AC8E65 /* LlamaKit.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24C1ABFBB6900AC8E65 /* LlamaKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; D04EE2581ABFBBB100AC8E65 /* ReactiveCocoa.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = D04EE24D1ABFBB6900AC8E65 /* ReactiveCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; D04EE25C1ABFBBDF00AC8E65 /* SwiftJunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04EE25B1ABFBBDF00AC8E65 /* SwiftJunk.swift */; }; D04EE25D1ABFBBDF00AC8E65 /* SwiftJunk.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04EE25B1ABFBBDF00AC8E65 /* SwiftJunk.swift */; }; D04EE2601ABFBD9100AC8E65 /* Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04EE25F1ABFBD9100AC8E65 /* Animation.swift */; }; D04EE2611ABFBD9100AC8E65 /* Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04EE25F1ABFBD9100AC8E65 /* Animation.swift */; }; - D04EE2671ABFC79200AC8E65 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04EE2661ABFC79200AC8E65 /* View.swift */; }; - D04EE2681ABFC79200AC8E65 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04EE2661ABFC79200AC8E65 /* View.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 215BEFCE1EF4282A006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D45480571A9572F5009D7229; + remoteInfo = "Result-Mac"; + }; + 215BEFD01EF4282A006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D45480671A9572F5009D7229; + remoteInfo = "Result-MacTests"; + }; + 215BEFD21EF4282A006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D454807D1A957361009D7229; + remoteInfo = "Result-iOS"; + }; + 215BEFD41EF4282A006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D45480871A957362009D7229; + remoteInfo = "Result-iOSTests"; + }; + 215BEFD61EF4282A006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 57FCDE471BA280DC00130C48; + remoteInfo = "Result-tvOS"; + }; + 215BEFD81EF4282A006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 57FCDE541BA280E000130C48; + remoteInfo = "Result-tvOSTests"; + }; + 215BEFDA1EF4282A006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D03579A31B2B788F005D26AE; + remoteInfo = "Result-watchOS"; + }; + 215BEFFE1EF42837006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D04725EA19E49ED7006002AA; + remoteInfo = "ReactiveSwift-macOS"; + }; + 215BF0001EF42837006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D04725F519E49ED7006002AA; + remoteInfo = "ReactiveSwift-macOSTests"; + }; + 215BF0021EF42837006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D047260C19E49F82006002AA; + remoteInfo = "ReactiveSwift-iOS"; + }; + 215BF0041EF42837006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D047261619E49F82006002AA; + remoteInfo = "ReactiveSwift-iOSTests"; + }; + 215BF0061EF42837006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A9B315541B3940610001CB9C; + remoteInfo = "ReactiveSwift-watchOS"; + }; + 215BF0081EF42837006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 57A4D2411BA13D7A00F7D4B1; + remoteInfo = "ReactiveSwift-tvOS"; + }; + 215BF00A1EF42837006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 7DFBED031CDB8C9500EE435B; + remoteInfo = "ReactiveSwift-tvOSTests"; + }; + 215BF01A1EF4293E006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D04725EA19E49ED7006002AA; + remoteInfo = "ReactiveCocoa-macOS"; + }; + 215BF01C1EF4293E006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D04725F519E49ED7006002AA; + remoteInfo = "ReactiveCocoa-macOSTests"; + }; + 215BF01E1EF4293E006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D047260C19E49F82006002AA; + remoteInfo = "ReactiveCocoa-iOS"; + }; + 215BF0201EF4293E006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D047261619E49F82006002AA; + remoteInfo = "ReactiveCocoa-iOSTests"; + }; + 215BF0221EF4293E006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A9B315541B3940610001CB9C; + remoteInfo = "ReactiveCocoa-watchOS"; + }; + 215BF0241EF4293E006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 57A4D2411BA13D7A00F7D4B1; + remoteInfo = "ReactiveCocoa-tvOS"; + }; + 215BF0261EF4293E006A9B71 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 7DFBED031CDB8C9500EE435B; + remoteInfo = "ReactiveCocoa-tvOSTests"; + }; D04EE1F71ABFB9AD00AC8E65 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D04EE1E11ABFB9AD00AC8E65 /* Project object */; @@ -55,7 +201,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - D04EE2571ABFBBB100AC8E65 /* LlamaKit.framework in Copy Frameworks */, D04EE2581ABFBBB100AC8E65 /* ReactiveCocoa.framework in Copy Frameworks */, ); name = "Copy Frameworks"; @@ -64,6 +209,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Result.xcodeproj; path = Carthage/Checkouts/Result/Result.xcodeproj; sourceTree = ""; }; + 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactiveSwift.xcodeproj; path = Carthage/Checkouts/ReactiveSwift/ReactiveSwift.xcodeproj; sourceTree = ""; }; + 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactiveCocoa.xcodeproj; path = Carthage/Checkouts/ReactiveCocoa/ReactiveCocoa.xcodeproj; sourceTree = ""; }; D04EE1EA1ABFB9AD00AC8E65 /* ReactiveAnimation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveAnimation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D04EE1EE1ABFB9AD00AC8E65 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D04EE1EF1ABFB9AD00AC8E65 /* ReactiveAnimation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactiveAnimation.h; sourceTree = ""; }; @@ -90,7 +238,6 @@ D04EE21D1ABFB9E100AC8E65 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; D04EE2231ABFBA1E00AC8E65 /* ReactiveAnimation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveAnimation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D04EE22D1ABFBA1E00AC8E65 /* ReactiveAnimation-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "ReactiveAnimation-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - D04EE24C1ABFBB6900AC8E65 /* LlamaKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = LlamaKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D04EE24D1ABFBB6900AC8E65 /* ReactiveCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = ReactiveCocoa.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D04EE2591ABFBBDE00AC8E65 /* ReactiveAnimationTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ReactiveAnimationTests-Bridging-Header.h"; sourceTree = ""; }; D04EE25B1ABFBBDF00AC8E65 /* SwiftJunk.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftJunk.swift; sourceTree = ""; }; @@ -103,8 +250,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D04EE24E1ABFBB6900AC8E65 /* LlamaKit.framework in Frameworks */, - D04EE24F1ABFBB6900AC8E65 /* ReactiveCocoa.framework in Frameworks */, + 215BF0291EF42956006A9B71 /* ReactiveCocoa.framework in Frameworks */, + 215BF00D1EF4285E006A9B71 /* ReactiveSwift.framework in Frameworks */, + 215BF00C1EF42857006A9B71 /* Result.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -113,7 +261,6 @@ buildActionMask = 2147483647; files = ( D04EE1F61ABFB9AD00AC8E65 /* ReactiveAnimation.framework in Frameworks */, - D04EE2501ABFBB8500AC8E65 /* LlamaKit.framework in Frameworks */, D04EE2511ABFBB8500AC8E65 /* ReactiveCocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -122,8 +269,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D04EE2521ABFBB8900AC8E65 /* LlamaKit.framework in Frameworks */, - D04EE2531ABFBB8900AC8E65 /* ReactiveCocoa.framework in Frameworks */, + 215BF02A1EF4295B006A9B71 /* ReactiveCocoa.framework in Frameworks */, + 215BF00F1EF4286B006A9B71 /* ReactiveSwift.framework in Frameworks */, + 215BF00E1EF42865006A9B71 /* Result.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -132,7 +280,6 @@ buildActionMask = 2147483647; files = ( D04EE22E1ABFBA1E00AC8E65 /* ReactiveAnimation.framework in Frameworks */, - D04EE2541ABFBB9100AC8E65 /* LlamaKit.framework in Frameworks */, D04EE2551ABFBB9100AC8E65 /* ReactiveCocoa.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -140,6 +287,48 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 215BEFC51EF4282A006A9B71 /* Products */ = { + isa = PBXGroup; + children = ( + 215BEFCF1EF4282A006A9B71 /* Result.framework */, + 215BEFD11EF4282A006A9B71 /* Result-MacTests.xctest */, + 215BEFD31EF4282A006A9B71 /* Result.framework */, + 215BEFD51EF4282A006A9B71 /* Result-iOSTests.xctest */, + 215BEFD71EF4282A006A9B71 /* Result.framework */, + 215BEFD91EF4282A006A9B71 /* Result-tvOSTests.xctest */, + 215BEFDB1EF4282A006A9B71 /* Result.framework */, + ); + name = Products; + sourceTree = ""; + }; + 215BEFF51EF42836006A9B71 /* Products */ = { + isa = PBXGroup; + children = ( + 215BEFFF1EF42837006A9B71 /* ReactiveSwift.framework */, + 215BF0011EF42837006A9B71 /* ReactiveSwiftTests.xctest */, + 215BF0031EF42837006A9B71 /* ReactiveSwift.framework */, + 215BF0051EF42837006A9B71 /* ReactiveSwiftTests.xctest */, + 215BF0071EF42837006A9B71 /* ReactiveSwift.framework */, + 215BF0091EF42837006A9B71 /* ReactiveSwift.framework */, + 215BF00B1EF42837006A9B71 /* ReactiveSwiftTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 215BF0111EF4293E006A9B71 /* Products */ = { + isa = PBXGroup; + children = ( + 215BF01B1EF4293E006A9B71 /* ReactiveCocoa.framework */, + 215BF01D1EF4293E006A9B71 /* ReactiveCocoaTests.xctest */, + 215BF01F1EF4293E006A9B71 /* ReactiveCocoa.framework */, + 215BF0211EF4293E006A9B71 /* ReactiveCocoaTests.xctest */, + 215BF0231EF4293E006A9B71 /* ReactiveCocoa.framework */, + 215BF0251EF4293E006A9B71 /* ReactiveCocoa.framework */, + 215BF0271EF4293E006A9B71 /* ReactiveCocoaTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; D04EE1E01ABFB9AD00AC8E65 = { isa = PBXGroup; children = ( @@ -147,6 +336,9 @@ D04EE1F91ABFB9AD00AC8E65 /* ReactiveAnimationTests */, D04EE2061ABFB9E100AC8E65 /* Configuration */, D04EE1EB1ABFB9AD00AC8E65 /* Products */, + 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */, + 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */, + 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */, ); sourceTree = ""; }; @@ -174,7 +366,6 @@ D04EE1ED1ABFB9AD00AC8E65 /* Supporting Files */ = { isa = PBXGroup; children = ( - D04EE24C1ABFBB6900AC8E65 /* LlamaKit.framework */, D04EE24D1ABFBB6900AC8E65 /* ReactiveCocoa.framework */, D04EE1EE1ABFB9AD00AC8E65 /* Info.plist */, ); @@ -404,6 +595,20 @@ mainGroup = D04EE1E01ABFB9AD00AC8E65; productRefGroup = D04EE1EB1ABFB9AD00AC8E65 /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 215BF0111EF4293E006A9B71 /* Products */; + ProjectRef = 215BF0101EF4293E006A9B71 /* ReactiveCocoa.xcodeproj */; + }, + { + ProductGroup = 215BEFF51EF42836006A9B71 /* Products */; + ProjectRef = 215BEFF41EF42836006A9B71 /* ReactiveSwift.xcodeproj */; + }, + { + ProductGroup = 215BEFC51EF4282A006A9B71 /* Products */; + ProjectRef = 215BEFC41EF4282A006A9B71 /* Result.xcodeproj */; + }, + ); projectRoot = ""; targets = ( D04EE1E91ABFB9AD00AC8E65 /* ReactiveAnimation-Mac */, @@ -414,6 +619,156 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 215BEFCF1EF4282A006A9B71 /* Result.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Result.framework; + remoteRef = 215BEFCE1EF4282A006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BEFD11EF4282A006A9B71 /* Result-MacTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "Result-MacTests.xctest"; + remoteRef = 215BEFD01EF4282A006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BEFD31EF4282A006A9B71 /* Result.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Result.framework; + remoteRef = 215BEFD21EF4282A006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BEFD51EF4282A006A9B71 /* Result-iOSTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "Result-iOSTests.xctest"; + remoteRef = 215BEFD41EF4282A006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BEFD71EF4282A006A9B71 /* Result.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Result.framework; + remoteRef = 215BEFD61EF4282A006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BEFD91EF4282A006A9B71 /* Result-tvOSTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "Result-tvOSTests.xctest"; + remoteRef = 215BEFD81EF4282A006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BEFDB1EF4282A006A9B71 /* Result.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Result.framework; + remoteRef = 215BEFDA1EF4282A006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BEFFF1EF42837006A9B71 /* ReactiveSwift.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveSwift.framework; + remoteRef = 215BEFFE1EF42837006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF0011EF42837006A9B71 /* ReactiveSwiftTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = ReactiveSwiftTests.xctest; + remoteRef = 215BF0001EF42837006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF0031EF42837006A9B71 /* ReactiveSwift.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveSwift.framework; + remoteRef = 215BF0021EF42837006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF0051EF42837006A9B71 /* ReactiveSwiftTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = ReactiveSwiftTests.xctest; + remoteRef = 215BF0041EF42837006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF0071EF42837006A9B71 /* ReactiveSwift.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveSwift.framework; + remoteRef = 215BF0061EF42837006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF0091EF42837006A9B71 /* ReactiveSwift.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveSwift.framework; + remoteRef = 215BF0081EF42837006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF00B1EF42837006A9B71 /* ReactiveSwiftTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = ReactiveSwiftTests.xctest; + remoteRef = 215BF00A1EF42837006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF01B1EF4293E006A9B71 /* ReactiveCocoa.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveCocoa.framework; + remoteRef = 215BF01A1EF4293E006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF01D1EF4293E006A9B71 /* ReactiveCocoaTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = ReactiveCocoaTests.xctest; + remoteRef = 215BF01C1EF4293E006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF01F1EF4293E006A9B71 /* ReactiveCocoa.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveCocoa.framework; + remoteRef = 215BF01E1EF4293E006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF0211EF4293E006A9B71 /* ReactiveCocoaTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = ReactiveCocoaTests.xctest; + remoteRef = 215BF0201EF4293E006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF0231EF4293E006A9B71 /* ReactiveCocoa.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveCocoa.framework; + remoteRef = 215BF0221EF4293E006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF0251EF4293E006A9B71 /* ReactiveCocoa.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveCocoa.framework; + remoteRef = 215BF0241EF4293E006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 215BF0271EF4293E006A9B71 /* ReactiveCocoaTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = ReactiveCocoaTests.xctest; + remoteRef = 215BF0261EF4293E006A9B71 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ D04EE1E81ABFB9AD00AC8E65 /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -450,7 +805,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D04EE2671ABFC79200AC8E65 /* View.swift in Sources */, + 215BF0431EF42FA9006A9B71 /* View.swift in Sources */, D04EE2601ABFBD9100AC8E65 /* Animation.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -468,7 +823,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D04EE2681ABFC79200AC8E65 /* View.swift in Sources */, + 215BF0441EF42FAA006A9B71 /* View.swift in Sources */, D04EE2611ABFBD9100AC8E65 /* Animation.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -536,6 +891,7 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; INFOPLIST_FILE = ReactiveAnimation/Info.plist; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -547,6 +903,7 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; INFOPLIST_FILE = ReactiveAnimation/Info.plist; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -586,6 +943,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; INFOPLIST_FILE = ReactiveAnimation/Info.plist; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -597,6 +955,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; INFOPLIST_FILE = ReactiveAnimation/Info.plist; + SWIFT_VERSION = 3.0; }; name = Release; }; @@ -653,6 +1012,7 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; INFOPLIST_FILE = ReactiveAnimation/Info.plist; + SWIFT_VERSION = 3.0; }; name = Profile; }; @@ -678,6 +1038,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; INFOPLIST_FILE = ReactiveAnimation/Info.plist; + SWIFT_VERSION = 3.0; }; name = Profile; }; @@ -719,6 +1080,7 @@ DYLIB_CURRENT_VERSION = 1; FRAMEWORK_VERSION = A; INFOPLIST_FILE = ReactiveAnimation/Info.plist; + SWIFT_VERSION = 3.0; }; name = Test; }; @@ -744,6 +1106,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; INFOPLIST_FILE = ReactiveAnimation/Info.plist; + SWIFT_VERSION = 3.0; }; name = Test; }; @@ -807,6 +1170,7 @@ D04EE23F1ABFBA8800AC8E65 /* Profile */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; D04EE2391ABFBA1E00AC8E65 /* Build configuration list for PBXNativeTarget "ReactiveAnimation-iOSTests" */ = { isa = XCConfigurationList; @@ -817,6 +1181,7 @@ D04EE2401ABFBA8800AC8E65 /* Profile */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/ReactiveAnimation.xcodeproj/xcshareddata/xcschemes/ReactiveAnimation Mac.xcscheme b/ReactiveAnimation.xcodeproj/xcshareddata/xcschemes/ReactiveAnimation Mac.xcscheme index 8193af4..3951598 100644 --- a/ReactiveAnimation.xcodeproj/xcshareddata/xcschemes/ReactiveAnimation Mac.xcscheme +++ b/ReactiveAnimation.xcodeproj/xcshareddata/xcschemes/ReactiveAnimation Mac.xcscheme @@ -15,7 +15,7 @@ @@ -37,10 +37,10 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -57,26 +57,29 @@ + + @@ -85,16 +88,16 @@ diff --git a/ReactiveAnimation.xcodeproj/xcshareddata/xcschemes/ReactiveAnimation iOS.xcscheme b/ReactiveAnimation.xcodeproj/xcshareddata/xcschemes/ReactiveAnimation iOS.xcscheme index 9ddecc4..dd747a0 100644 --- a/ReactiveAnimation.xcodeproj/xcshareddata/xcschemes/ReactiveAnimation iOS.xcscheme +++ b/ReactiveAnimation.xcodeproj/xcshareddata/xcschemes/ReactiveAnimation iOS.xcscheme @@ -15,7 +15,7 @@ @@ -37,10 +37,10 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -57,26 +57,29 @@ + + @@ -85,16 +88,16 @@ diff --git a/ReactiveAnimation.xcworkspace/contents.xcworkspacedata b/ReactiveAnimation.xcworkspace/contents.xcworkspacedata index c23943d..c37415f 100644 --- a/ReactiveAnimation.xcworkspace/contents.xcworkspacedata +++ b/ReactiveAnimation.xcworkspace/contents.xcworkspacedata @@ -4,10 +4,4 @@ - - - - diff --git a/ReactiveAnimation.xcworkspace/xcshareddata/ReactiveAnimation.xcscmblueprint b/ReactiveAnimation.xcworkspace/xcshareddata/ReactiveAnimation.xcscmblueprint new file mode 100644 index 0000000..c861e73 --- /dev/null +++ b/ReactiveAnimation.xcworkspace/xcshareddata/ReactiveAnimation.xcscmblueprint @@ -0,0 +1,42 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "AF9DA363DF5A12C6971A2F6E535983CE54A9D927", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "51B210D0D41486D3ADD6940D57E4480BBD4DE4C5" : 9223372036854775807, + "AF9DA363DF5A12C6971A2F6E535983CE54A9D927" : 9223372036854775807, + "E084C86B03F81D63323C9E7510697EA528A758C7" : 9223372036854775807 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "6F8DC9BA-2864-4A6F-8998-AF07DF0FCEEC", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "51B210D0D41486D3ADD6940D57E4480BBD4DE4C5" : "ReactiveAnimation\/Carthage\/Checkouts\/ReactiveCocoa\/", + "AF9DA363DF5A12C6971A2F6E535983CE54A9D927" : "ReactiveAnimation\/", + "E084C86B03F81D63323C9E7510697EA528A758C7" : "ReactiveAnimation\/Carthage\/Checkouts\/ReactiveCocoa\/Carthage\/Checkouts\/xcconfigs\/" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "ReactiveAnimation", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "ReactiveAnimation.xcworkspace", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/ReactiveCocoa\/ReactiveCocoa.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "51B210D0D41486D3ADD6940D57E4480BBD4DE4C5" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/ReactiveCocoa\/ReactiveAnimation", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "AF9DA363DF5A12C6971A2F6E535983CE54A9D927" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/jspahrsummers\/xcconfigs.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "E084C86B03F81D63323C9E7510697EA528A758C7" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/jspahrsummers\/xcconfigs.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "E084C86B03F81D63323C9E7510697EA528A758C7" + } + ] +} \ No newline at end of file diff --git a/ReactiveAnimation/Animation.swift b/ReactiveAnimation/Animation.swift index 8dfd711..11bf192 100644 --- a/ReactiveAnimation/Animation.swift +++ b/ReactiveAnimation/Animation.swift @@ -16,7 +16,9 @@ public typealias AnimationCurveRawValue = UIViewAnimationCurve.RawValue #endif +import ReactiveSwift import ReactiveCocoa +import enum Result.NoError /// Creates an animated SignalProducer for each value that arrives on /// `producer`. @@ -60,54 +62,68 @@ import ReactiveCocoa /// animation corresponding to that value has finished. Deferring the events of /// the returned producer or having them delivered on another thread is considered /// undefined behavior. -public func animateEach(duration: NSTimeInterval? = nil, curve: AnimationCurve = .Default)(producer: SignalProducer) -> SignalProducer, Error> { - return producer |> map { value in - return SignalProducer { observer, disposable in - OSAtomicIncrement32(&runningInAnimationCount) - disposable.addDisposable { - OSAtomicDecrement32(&runningInAnimationCount) - } - - #if os(OSX) - NSAnimationContext.runAnimationGroup({ context in - if let duration = duration { - context.duration = duration - } - - if curve != .Default { - context.timingFunction = CAMediaTimingFunction(name: curve.mediaTimingFunction) - } - - sendNext(observer, value) - }, completionHandler: { - // Avoids weird AppKit deadlocks when interrupting an - // existing animation. - UIScheduler().schedule { - sendCompleted(observer) - } - }) - #elseif os(iOS) - var options = UIViewAnimationOptions(UInt(curve.rawValue)) - options |= UIViewAnimationOptions.LayoutSubviews - options |= UIViewAnimationOptions.BeginFromCurrentState - if curve != .Default { - options |= UIViewAnimationOptions.OverrideInheritedCurve - } - - UIView.animateWithDuration(duration ?? 0.2, delay: 0, options: options, animations: { - sendNext(observer, value) - }, completion: { finished in - if finished { - sendCompleted(observer) - } else { - sendInterrupted(observer) - } - }) - #endif - } - } + + +extension Signal { + public func animateEach(duration: TimeInterval? = nil, curve: AnimationCurve = .Default) -> Signal, Error> { + return self.map { value in + return SignalProducer { observer, lifetime in + OSAtomicIncrement32(&runningInAnimationCount) + lifetime.observeEnded { + OSAtomicDecrement32(&runningInAnimationCount) + } + + #if os(OSX) + NSAnimationContext.runAnimationGroup({ context in + if let duration = duration { + context.duration = duration + } + + if curve != .Default { + context.timingFunction = CAMediaTimingFunction(name: curve.mediaTimingFunction) + } + + observer.send(value: value as! Value) // TODO: Why is the downcast necessary? + }, completionHandler: { + // Avoids weird AppKit deadlocks when interrupting an + // existing animation. + UIScheduler().schedule { + observer.sendCompleted() + } + }) + #elseif os(iOS) + var options: UIViewAnimationOptions = [ + UIViewAnimationOptions(rawValue: UInt(curve.rawValue)), + .layoutSubviews, + .beginFromCurrentState] + + if curve != .Default { + options.formUnion(.overrideInheritedCurve) + } + + UIView.animate(withDuration: duration ?? 0.2, delay: 0, options: options, animations: { + observer.send(value: value as! Value) // TODO: Why is the downcast necessary? + }, completion: { finished in + if(finished) { + observer.sendCompleted() + } else { + observer.sendInterrupted() + } + }) + #endif + } + } + } +} + + +extension SignalProducer { + public func animateEach(duration: TimeInterval? = nil, curve: AnimationCurve = .Default) -> SignalProducer, Error> { + return self.lift { $0.animateEach(duration: duration, curve: curve) } + } } + /// The number of animated signals in the call stack. /// /// This variable should be manipulated with OSAtomic functions. @@ -131,31 +147,37 @@ public enum AnimationCurve: AnimationCurveRawValue, Equatable { /// Begins the animation slowly, speeds up in the middle, then slows to /// a stop. - case EaseInOut - #if os(iOS) - = UIViewAnimationCurve.EaseInOut - #endif - - /// Begins the animation slowly and speeds up to a stop. - case EaseIn - #if os(iOS) - = UIViewAnimationCurve.EaseIn - #endif - - /// Begins the animation quickly and slows down to a stop. - case EaseOut - #if os(iOS) - = UIViewAnimationCurve.EaseOut - #endif - - /// Animates with the same pace over the duration of the animation. - case Linear - #if os(iOS) - = UIViewAnimationCurve.Linear - #endif - + case EaseInOut + case EaseIn + case EaseOut + case Linear +// #if os(iOS) +// case EaseInOut = UIViewAnimationCurve.EaseInOut.rawValue +// #else +// case EaseInOut +// #endif +// +// /// Begins the animation slowly and speeds up to a stop. +// case EaseIn +// #if os(iOS) +// = UIViewAnimationCurve.EaseIn +// #endif +// +// /// Begins the animation quickly and slows down to a stop. +// case EaseOut +// #if os(iOS) +// = UIViewAnimationCurve.EaseOut +// #endif +// +// /// Animates with the same pace over the duration of the animation. +// case Linear +// #if os(iOS) +// = UIViewAnimationCurve.Linear +// #endif + /// The name of the CAMediaTimingFunction corresponding to this curve. public var mediaTimingFunction: String { + switch self { case .Default: return kCAMediaTimingFunctionDefault @@ -185,7 +207,7 @@ public func == (lhs: AnimationCurve, rhs: AnimationCurve) -> Bool { } } -extension AnimationCurve: Printable { +extension AnimationCurve: CustomStringConvertible { public var description: String { switch self { case .Default: diff --git a/ReactiveAnimation/View.swift b/ReactiveAnimation/View.swift index 5f5c682..451b7f9 100644 --- a/ReactiveAnimation/View.swift +++ b/ReactiveAnimation/View.swift @@ -7,145 +7,67 @@ // #if os(OSX) - import AppKit + import AppKit - public typealias View = NSView + public typealias View = NSView #elseif os(iOS) - import UIKit + import UIKit - public typealias View = UIView + public typealias View = UIView #endif +import ReactiveSwift import ReactiveCocoa - -/// Wraps an NSView or UIView with bindable properties for animations. -public struct RAN { - private weak var view: View? - private let willDealloc: SignalProducer<(), NoError> - - private var animator: View? { - #if os(OSX) - if runningInAnimation { - return view.map { $0.animator() } - } - #endif - - return view - } - - /// Creates a wrapper for the given view's properties. - public init(_ view: View) { - self.view = view - self.willDealloc = view.rac_willDeallocSignal().toSignalProducer() - |> map { _ in () } - |> catch { error in - assert(false, "rac_willDeallocSignal failed with error: \(error)") - return .empty - } - } - - private func viewProperty(setter: T -> ()) -> ViewProperty { - return ViewProperty(willDealloc: self.willDealloc, setter: setter) - } - - public var frame: ViewProperty { - return viewProperty { self.animator?.frame = $0 } - } - - public var bounds: ViewProperty { - return viewProperty { self.animator?.bounds = $0 } - } - - #if os(iOS) - public var center: ViewProperty { - return viewProperty { self.animator?.center = $0 } +import enum Result.NoError + +extension Reactive where Base: View { + public var frame: BindingTarget { + return makeBindingTarget { $0.frame = $1 } + } + + public var bounds: BindingTarget { + return makeBindingTarget { $0.bounds = $1 } + } + + #if os(iOS) + public var center: BindingTarget { + return makeBindingTarget { $0.center = $1 } + } + + public var backgroundColor: BindingTarget { + return makeBindingTarget { $0.backgroundColor = $1 } + } + + public var transform: BindingTarget { + return makeBindingTarget { $0.transform = $1 } + } + #endif + + public var alpha: BindingTarget { + return makeBindingTarget { + #if os(OSX) + $0.alphaValue = $1 + #elseif os(iOS) + $0.alpha = $1 + #endif } - - public var backgroundColor: ViewProperty { - return viewProperty { self.animator?.backgroundColor = $0 } - } - - public var transform: ViewProperty { - return viewProperty { self.animator?.transform = $0 } - } - #endif - - public var alpha: ViewProperty { - return viewProperty { value in - #if os(OSX) - self.animator?.alphaValue = value - #elseif os(iOS) - self.animator?.alpha = value - #endif - } - } - - #if os(OSX) - public var frameOrigin: ViewProperty { - return viewProperty { self.animator?.setFrameOrigin($0) } - } - - public var frameSize: ViewProperty { - return viewProperty { self.animator?.setFrameSize($0) } - } - - public var boundsOrigin: ViewProperty { - return viewProperty { self.animator?.setBoundsOrigin($0) } - } - - public var boundsSize: ViewProperty { - return viewProperty { self.animator?.setBoundsSize($0) } - } - #endif - -} - -/// A property on a view that can be animated. -public struct ViewProperty { - private let willDealloc: SignalProducer<(), NoError> - private let setter: T -> () -} - -extension ViewProperty: SinkType { - public func put(value: T) { - setter(value) - } -} - -/// Binds a (potentially animated) signal to a view property. -public func <~ (property: ViewProperty, signal: Signal) -> Disposable { - let disposable = CompositeDisposable() - let propertyDisposable = property.willDealloc.start(completed: { - disposable.dispose() - }) - - disposable.addDisposable(propertyDisposable) - - let signalDisposable = signal.observe(next: property.setter, completed: { - disposable.dispose() - }) - - disposable.addDisposable(signalDisposable) - return disposable -} - -/// Binds a (potentially animated) signal producer to a view property. -public func <~ (property: ViewProperty, producer: SignalProducer) -> Disposable { - var disposable: Disposable! - - producer.startWithSignal { signal, signalDisposable in - property <~ signal - disposable = signalDisposable - - property.willDealloc.start(completed: { - signalDisposable.dispose() - }) - } - - return disposable -} - -/// Binds the view property to the latest values of `sourceProperty`. -public func <~ (destinationProperty: ViewProperty, sourceProperty: P) -> Disposable { - return destinationProperty <~ sourceProperty.producer + } + + #if os(OSX) + public var frameOrigin: BindingTarget { + return viewProperty { $0.setFrameOrigin($1) } + } + + public var frameSize: BindingTarget { + return viewProperty { $0.setFrameSize($1) } + } + + public var boundsOrigin: BindingTarget { + return viewProperty { $0.setBoundsOrigin($1) } + } + + public var boundsSize: BindingTarget { + return viewProperty { $0.setBoundsSize($1) } + } + #endif } diff --git a/ReactiveAnimationDemo b/ReactiveAnimationDemo new file mode 160000 index 0000000..7f226ea --- /dev/null +++ b/ReactiveAnimationDemo @@ -0,0 +1 @@ +Subproject commit 7f226eaefc6236d7ac0e389fc32cdf01568dbf94 From eeee3b19dff603d230f185ad5fd97d556e6c9dfd Mon Sep 17 00:00:00 2001 From: Markus Chmelar Date: Tue, 20 Jun 2017 10:16:38 +0200 Subject: [PATCH 2/2] Actually add the demo --- ReactiveAnimationDemo | 1 - .../project.pbxproj | 469 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + ReactiveAnimationDemo_iOS/AppDelegate.swift | 46 ++ .../AppIcon.appiconset/Contents.json | 93 ++++ .../Base.lproj/LaunchScreen.storyboard | 27 + .../Base.lproj/Main.storyboard | 42 ++ ReactiveAnimationDemo_iOS/Info.plist | 45 ++ .../ViewController.swift | 46 ++ 9 files changed, 775 insertions(+), 1 deletion(-) delete mode 160000 ReactiveAnimationDemo create mode 100644 ReactiveAnimationDemo_iOS.xcodeproj/project.pbxproj create mode 100644 ReactiveAnimationDemo_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ReactiveAnimationDemo_iOS/AppDelegate.swift create mode 100644 ReactiveAnimationDemo_iOS/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ReactiveAnimationDemo_iOS/Base.lproj/LaunchScreen.storyboard create mode 100644 ReactiveAnimationDemo_iOS/Base.lproj/Main.storyboard create mode 100644 ReactiveAnimationDemo_iOS/Info.plist create mode 100644 ReactiveAnimationDemo_iOS/ViewController.swift diff --git a/ReactiveAnimationDemo b/ReactiveAnimationDemo deleted file mode 160000 index 7f226ea..0000000 --- a/ReactiveAnimationDemo +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7f226eaefc6236d7ac0e389fc32cdf01568dbf94 diff --git a/ReactiveAnimationDemo_iOS.xcodeproj/project.pbxproj b/ReactiveAnimationDemo_iOS.xcodeproj/project.pbxproj new file mode 100644 index 0000000..3b7124f --- /dev/null +++ b/ReactiveAnimationDemo_iOS.xcodeproj/project.pbxproj @@ -0,0 +1,469 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 2157F5521EF444DB0057F2B2 /* ReactiveAnimation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2157F54F1EF444CC0057F2B2 /* ReactiveAnimation.framework */; }; + 2157F5531EF444DB0057F2B2 /* ReactiveAnimation.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2157F54F1EF444CC0057F2B2 /* ReactiveAnimation.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 2157F5571EF444DE0057F2B2 /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2157F5561EF444DE0057F2B2 /* ReactiveCocoa.framework */; }; + 2157F5581EF444DE0057F2B2 /* ReactiveCocoa.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2157F5561EF444DE0057F2B2 /* ReactiveCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 2157F55A1EF444E40057F2B2 /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2157F5591EF444E40057F2B2 /* ReactiveSwift.framework */; }; + 2157F55B1EF444E40057F2B2 /* ReactiveSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2157F5591EF444E40057F2B2 /* ReactiveSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 2157F55D1EF444ED0057F2B2 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2157F55C1EF444ED0057F2B2 /* Result.framework */; }; + 2157F55E1EF444ED0057F2B2 /* Result.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 2157F55C1EF444ED0057F2B2 /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 215BF0521EF43CB4006A9B71 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215BF0511EF43CB4006A9B71 /* AppDelegate.swift */; }; + 215BF0541EF43CB4006A9B71 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215BF0531EF43CB4006A9B71 /* ViewController.swift */; }; + 215BF0571EF43CB4006A9B71 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 215BF0551EF43CB4006A9B71 /* Main.storyboard */; }; + 215BF0591EF43CB4006A9B71 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 215BF0581EF43CB4006A9B71 /* Assets.xcassets */; }; + 215BF05C1EF43CB4006A9B71 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 215BF05A1EF43CB4006A9B71 /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 2157F54A1EF444CC0057F2B2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2157F5401EF444CC0057F2B2 /* ReactiveAnimation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D04EE1EA1ABFB9AD00AC8E65; + remoteInfo = "ReactiveAnimation-Mac"; + }; + 2157F54C1EF444CC0057F2B2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2157F5401EF444CC0057F2B2 /* ReactiveAnimation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D04EE1F51ABFB9AD00AC8E65; + remoteInfo = "ReactiveAnimation-MacTests"; + }; + 2157F54E1EF444CC0057F2B2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2157F5401EF444CC0057F2B2 /* ReactiveAnimation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D04EE2231ABFBA1E00AC8E65; + remoteInfo = "ReactiveAnimation-iOS"; + }; + 2157F5501EF444CC0057F2B2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2157F5401EF444CC0057F2B2 /* ReactiveAnimation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D04EE22D1ABFBA1E00AC8E65; + remoteInfo = "ReactiveAnimation-iOSTests"; + }; + 2157F5541EF444DB0057F2B2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2157F5401EF444CC0057F2B2 /* ReactiveAnimation.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = D04EE2221ABFBA1E00AC8E65; + remoteInfo = "ReactiveAnimation-iOS"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 215BF08A1EF441CB006A9B71 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 2157F5531EF444DB0057F2B2 /* ReactiveAnimation.framework in Embed Frameworks */, + 2157F5581EF444DE0057F2B2 /* ReactiveCocoa.framework in Embed Frameworks */, + 2157F55B1EF444E40057F2B2 /* ReactiveSwift.framework in Embed Frameworks */, + 2157F55E1EF444ED0057F2B2 /* Result.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2157F5401EF444CC0057F2B2 /* ReactiveAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactiveAnimation.xcodeproj; path = ../ReactiveAnimation.xcodeproj; sourceTree = ""; }; + 2157F5561EF444DE0057F2B2 /* ReactiveCocoa.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ReactiveCocoa.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2157F5591EF444E40057F2B2 /* ReactiveSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ReactiveSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 2157F55C1EF444ED0057F2B2 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 215BF04E1EF43CB4006A9B71 /* ReactiveAnimationDemo_iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReactiveAnimationDemo_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 215BF0511EF43CB4006A9B71 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 215BF0531EF43CB4006A9B71 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 215BF0561EF43CB4006A9B71 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 215BF0581EF43CB4006A9B71 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 215BF05B1EF43CB4006A9B71 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 215BF05D1EF43CB4006A9B71 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 215BF0771EF43D04006A9B71 /* ReactiveSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReactiveSwift.framework; path = "../../Carthage/Checkouts/ReactiveSwift/build/Debug-iphoneos/ReactiveSwift.framework"; sourceTree = ""; }; + 215BF0781EF43D04006A9B71 /* ReactiveCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReactiveCocoa.framework; path = "../../Carthage/Checkouts/ReactiveCocoa/build/Debug-iphoneos/ReactiveCocoa.framework"; sourceTree = ""; }; + 215BF0791EF43D04006A9B71 /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = "../../Carthage/Checkouts/Result/build/Debug-iphoneos/Result.framework"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 215BF04B1EF43CB4006A9B71 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2157F5521EF444DB0057F2B2 /* ReactiveAnimation.framework in Frameworks */, + 2157F5571EF444DE0057F2B2 /* ReactiveCocoa.framework in Frameworks */, + 2157F55A1EF444E40057F2B2 /* ReactiveSwift.framework in Frameworks */, + 2157F55D1EF444ED0057F2B2 /* Result.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2157F5411EF444CC0057F2B2 /* Products */ = { + isa = PBXGroup; + children = ( + 2157F54B1EF444CC0057F2B2 /* ReactiveAnimation.framework */, + 2157F54D1EF444CC0057F2B2 /* ReactiveAnimation-MacTests.xctest */, + 2157F54F1EF444CC0057F2B2 /* ReactiveAnimation.framework */, + 2157F5511EF444CC0057F2B2 /* ReactiveAnimation-iOSTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 215BF0451EF43CB4006A9B71 = { + isa = PBXGroup; + children = ( + 2157F5401EF444CC0057F2B2 /* ReactiveAnimation.xcodeproj */, + 215BF0501EF43CB4006A9B71 /* ReactiveAnimationDemo_iOS */, + 215BF04F1EF43CB4006A9B71 /* Products */, + 215BF0761EF43D00006A9B71 /* Frameworks */, + ); + sourceTree = ""; + }; + 215BF04F1EF43CB4006A9B71 /* Products */ = { + isa = PBXGroup; + children = ( + 215BF04E1EF43CB4006A9B71 /* ReactiveAnimationDemo_iOS.app */, + ); + name = Products; + sourceTree = ""; + }; + 215BF0501EF43CB4006A9B71 /* ReactiveAnimationDemo_iOS */ = { + isa = PBXGroup; + children = ( + 215BF0511EF43CB4006A9B71 /* AppDelegate.swift */, + 215BF0531EF43CB4006A9B71 /* ViewController.swift */, + 215BF0551EF43CB4006A9B71 /* Main.storyboard */, + 215BF0581EF43CB4006A9B71 /* Assets.xcassets */, + 215BF05A1EF43CB4006A9B71 /* LaunchScreen.storyboard */, + 215BF05D1EF43CB4006A9B71 /* Info.plist */, + ); + path = ReactiveAnimationDemo_iOS; + sourceTree = ""; + }; + 215BF0761EF43D00006A9B71 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2157F55C1EF444ED0057F2B2 /* Result.framework */, + 2157F5591EF444E40057F2B2 /* ReactiveSwift.framework */, + 215BF0781EF43D04006A9B71 /* ReactiveCocoa.framework */, + 215BF0771EF43D04006A9B71 /* ReactiveSwift.framework */, + 2157F5561EF444DE0057F2B2 /* ReactiveCocoa.framework */, + 215BF0791EF43D04006A9B71 /* Result.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 215BF04D1EF43CB4006A9B71 /* ReactiveAnimationDemo_iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 215BF0601EF43CB4006A9B71 /* Build configuration list for PBXNativeTarget "ReactiveAnimationDemo_iOS" */; + buildPhases = ( + 215BF04A1EF43CB4006A9B71 /* Sources */, + 215BF04B1EF43CB4006A9B71 /* Frameworks */, + 215BF04C1EF43CB4006A9B71 /* Resources */, + 215BF08A1EF441CB006A9B71 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 2157F5551EF444DB0057F2B2 /* PBXTargetDependency */, + ); + name = ReactiveAnimationDemo_iOS; + productName = ReactiveAnimationDemo_iOS; + productReference = 215BF04E1EF43CB4006A9B71 /* ReactiveAnimationDemo_iOS.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 215BF0461EF43CB4006A9B71 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0900; + LastUpgradeCheck = 0900; + ORGANIZATIONNAME = "Innovaptor OG"; + TargetAttributes = { + 215BF04D1EF43CB4006A9B71 = { + CreatedOnToolsVersion = 9.0; + }; + }; + }; + buildConfigurationList = 215BF0491EF43CB4006A9B71 /* Build configuration list for PBXProject "ReactiveAnimationDemo_iOS" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 215BF0451EF43CB4006A9B71; + productRefGroup = 215BF04F1EF43CB4006A9B71 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 2157F5411EF444CC0057F2B2 /* Products */; + ProjectRef = 2157F5401EF444CC0057F2B2 /* ReactiveAnimation.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 215BF04D1EF43CB4006A9B71 /* ReactiveAnimationDemo_iOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 2157F54B1EF444CC0057F2B2 /* ReactiveAnimation.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveAnimation.framework; + remoteRef = 2157F54A1EF444CC0057F2B2 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2157F54D1EF444CC0057F2B2 /* ReactiveAnimation-MacTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "ReactiveAnimation-MacTests.xctest"; + remoteRef = 2157F54C1EF444CC0057F2B2 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2157F54F1EF444CC0057F2B2 /* ReactiveAnimation.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ReactiveAnimation.framework; + remoteRef = 2157F54E1EF444CC0057F2B2 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 2157F5511EF444CC0057F2B2 /* ReactiveAnimation-iOSTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "ReactiveAnimation-iOSTests.xctest"; + remoteRef = 2157F5501EF444CC0057F2B2 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 215BF04C1EF43CB4006A9B71 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 215BF05C1EF43CB4006A9B71 /* LaunchScreen.storyboard in Resources */, + 215BF0591EF43CB4006A9B71 /* Assets.xcassets in Resources */, + 215BF0571EF43CB4006A9B71 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 215BF04A1EF43CB4006A9B71 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 215BF0541EF43CB4006A9B71 /* ViewController.swift in Sources */, + 215BF0521EF43CB4006A9B71 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 2157F5551EF444DB0057F2B2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "ReactiveAnimation-iOS"; + targetProxy = 2157F5541EF444DB0057F2B2 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 215BF0551EF43CB4006A9B71 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 215BF0561EF43CB4006A9B71 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 215BF05A1EF43CB4006A9B71 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 215BF05B1EF43CB4006A9B71 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 215BF05E1EF43CB4006A9B71 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + 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_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + 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 = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 215BF05F1EF43CB4006A9B71 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + 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_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + 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 = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 215BF0611EF43CB4006A9B71 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = F6SD5MVY6N; + INFOPLIST_FILE = ReactiveAnimationDemo_iOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.innovaptor.ReactiveAnimationDemo-iOS"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 215BF0621EF43CB4006A9B71 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = F6SD5MVY6N; + INFOPLIST_FILE = ReactiveAnimationDemo_iOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.innovaptor.ReactiveAnimationDemo-iOS"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 215BF0491EF43CB4006A9B71 /* Build configuration list for PBXProject "ReactiveAnimationDemo_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 215BF05E1EF43CB4006A9B71 /* Debug */, + 215BF05F1EF43CB4006A9B71 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 215BF0601EF43CB4006A9B71 /* Build configuration list for PBXNativeTarget "ReactiveAnimationDemo_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 215BF0611EF43CB4006A9B71 /* Debug */, + 215BF0621EF43CB4006A9B71 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 215BF0461EF43CB4006A9B71 /* Project object */; +} diff --git a/ReactiveAnimationDemo_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ReactiveAnimationDemo_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..fb7cd31 --- /dev/null +++ b/ReactiveAnimationDemo_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ReactiveAnimationDemo_iOS/AppDelegate.swift b/ReactiveAnimationDemo_iOS/AppDelegate.swift new file mode 100644 index 0000000..17fdda8 --- /dev/null +++ b/ReactiveAnimationDemo_iOS/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// ReactiveAnimationDemo_iOS +// +// Created by Markus Chmelar on 16/06/2017. +// Copyright © 2017 Innovaptor OG. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/ReactiveAnimationDemo_iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/ReactiveAnimationDemo_iOS/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..1d060ed --- /dev/null +++ b/ReactiveAnimationDemo_iOS/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,93 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ReactiveAnimationDemo_iOS/Base.lproj/LaunchScreen.storyboard b/ReactiveAnimationDemo_iOS/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..fdf3f97 --- /dev/null +++ b/ReactiveAnimationDemo_iOS/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ReactiveAnimationDemo_iOS/Base.lproj/Main.storyboard b/ReactiveAnimationDemo_iOS/Base.lproj/Main.storyboard new file mode 100644 index 0000000..d351722 --- /dev/null +++ b/ReactiveAnimationDemo_iOS/Base.lproj/Main.storyboard @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ReactiveAnimationDemo_iOS/Info.plist b/ReactiveAnimationDemo_iOS/Info.plist new file mode 100644 index 0000000..16be3b6 --- /dev/null +++ b/ReactiveAnimationDemo_iOS/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/ReactiveAnimationDemo_iOS/ViewController.swift b/ReactiveAnimationDemo_iOS/ViewController.swift new file mode 100644 index 0000000..e7f4b1b --- /dev/null +++ b/ReactiveAnimationDemo_iOS/ViewController.swift @@ -0,0 +1,46 @@ +// +// ViewController.swift +// ReactiveAnimationDemo_iOS +// +// Created by Markus Chmelar on 16/06/2017. +// Copyright © 2017 Innovaptor OG. All rights reserved. +// + +import UIKit + +import ReactiveSwift +import ReactiveCocoa +import ReactiveAnimation + +class ViewController: UIViewController { + @IBOutlet weak var label: UILabel! + + private func randomPoint() -> CGPoint { + let random: (CGFloat) -> CGFloat = { max in + return CGFloat(arc4random_uniform(UInt32(max))) + } + + let x = random(view.frame.size.width) + let y = random(view.frame.size.height) + + return CGPoint(x: x, y: y) + } + + override func viewDidLoad() { + super.viewDidLoad() + label.reactive.center <~ SignalProducer.timer(interval: .seconds(1), on: QueueScheduler.main) + .map { _ in return self.randomPoint() } + // In order to demonstrate different flatten strategies, + // the animation duration is larger than the animation interval, + // thus a new animation begins before the running animation is finished + .animateEach(duration: 1.5, curve: .EaseInOut) + // With the .concat flatten strategy, each animations are concatenated. + // Each animation finisheds, before the next one starts. + // This also means, that animations are queued + .flatten(.concat) + // With the .merge flatten strategy, each animation is performed immediately + // If an animation is currently running, it is cancelled and the next animation starts from the current animation state +// .flatten(.merge) + } +} +