diff --git a/.swift-version b/.swift-version index 5186d07..7d5c902 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.0 +4.1 diff --git a/.travis.yml b/.travis.yml index a3c04dc..845282e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ matrix: include: - os: osx language: objective-c - osx_image: xcode9 + osx_image: xcode9.3 before_install: - git submodule update --init --recursive - pushd Utilities @@ -16,7 +16,7 @@ matrix: - carthage build --no-skip-current - os: osx language: objective-c - osx_image: xcode9 + osx_image: xcode9.3 before_install: - git submodule update --init --recursive - pushd Utilities @@ -25,19 +25,10 @@ matrix: script: - set -o pipefail - xcodebuild test -scheme SwiftCheck | xcpretty -c - # -- Start iOS -- - # !!!: Make sure desired device name & OS version are suitable for the Xcode version installed on osx_image - - iOS_DEVICE_NAME="iPad Pro (12.9-inch) (2nd generation)" - - iOS_RUNTIME_VERSION="11.0" - # Get simulator identifier for desired device/runtime pair - - SIMULATOR_ID=$(xcrun instruments -s | grep -o "${iOS_DEVICE_NAME} (${iOS_RUNTIME_VERSION}) \[.*\]" | grep -o "\[.*\]" | sed "s/^\[\(.*\)\]$/\1/") - - echo $SIMULATOR_ID - - echo $iOS_DEVICE_NAME - - echo $iOS_RUNTIME_VERSION - - xcodebuild build-for-testing -scheme SwiftCheck-iOS -destination "platform=iOS Simulator,name=${iOS_DEVICE_NAME},OS=${iOS_RUNTIME_VERSION}" | xcpretty -c - - xcodebuild test -scheme SwiftCheck-iOS -destination "platform=iOS Simulator,name=${iOS_DEVICE_NAME},OS=${iOS_RUNTIME_VERSION}" | xcpretty -c - - xcodebuild build-for-testing -scheme SwiftCheck-tvOS -destination 'platform=tvOS Simulator,name=Apple TV 1080p' | xcpretty -c - - xcodebuild test -scheme SwiftCheck-tvOS -destination 'platform=tvOS Simulator,name=Apple TV 1080p' | xcpretty -c + - xcodebuild build-for-testing -scheme SwiftCheck-iOS -destination "platform=iOS Simulator,name=iPad Pro (12.9-inch) (2nd generation)" | xcpretty -c + - xcodebuild test -scheme SwiftCheck-iOS -destination "platform=iOS Simulator,name=iPad Pro (12.9-inch) (2nd generation)" | xcpretty -c + - xcodebuild build-for-testing -scheme SwiftCheck-tvOS -destination 'platform=tvOS Simulator,name=Apple TV 4K (at 1080p)' | xcpretty -c + - xcodebuild test -scheme SwiftCheck-tvOS -destination 'platform=tvOS Simulator,name=Apple TV 4K (at 1080p)' | xcpretty -c - os: linux language: generic sudo: required @@ -45,9 +36,9 @@ matrix: before_install: - git submodule update --init --recursive - wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import - - - wget https://swift.org/builds/swift-4.0-release/ubuntu1404/swift-4.0-RELEASE/swift-4.0-RELEASE-ubuntu14.04.tar.gz - - tar xzf swift-4.0-RELEASE-ubuntu14.04.tar.gz - - export PATH=${PWD}/swift-4.0-RELEASE-ubuntu14.04/usr/bin:"${PATH}" + - wget https://swift.org/builds/swift-4.1-release/ubuntu1404/swift-4.1-RELEASE/swift-4.1-RELEASE-ubuntu14.04.tar.gz + - tar xzf swift-4.1-RELEASE-ubuntu14.04.tar.gz + - export PATH=${PWD}/swift-4.1-RELEASE-ubuntu14.04/usr/bin:"${PATH}" - pushd Utilities - ./compile.sh - popd diff --git a/Package.swift b/Package.swift index f114597..2afb8c5 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.0 +// swift-tools-version:4.1 import PackageDescription diff --git a/README.md b/README.md index a958420..d84c128 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,7 @@ For a less contrived example, here is a program property that tests whether Array identity holds under double reversal: ```swift -// Because Swift doesn't allow us to implement `Arbitrary` for certain types, -// SwiftCheck instead implements 'modifier' types that wrap them. Here, -// `ArrayOf` generates random arrays of values of type `T`. -property("The reverse of the reverse of an array is that array") <- forAll { (xs : ArrayOf) in +property("The reverse of the reverse of an array is that array") <- forAll { (xs : [Int]) in // This property is using a number of SwiftCheck's more interesting // features. `^&&^` is the conjunction operator for properties that turns // both properties into a larger property that only holds when both sub-properties @@ -56,9 +53,9 @@ property("The reverse of the reverse of an array is that array") <- forAll { (xs // *** Passed 100 tests // (100% , Right identity, Left identity) return - (xs.getArray.reverse().reverse() == xs.getArray) "Left identity" + (xs.reverse().reverse() == xs) "Left identity" ^&&^ - (xs.getArray == xs.getArray.reverse().reverse()) "Right identity" + (xs == xs.reverse().reverse()) "Right identity" } ``` @@ -66,12 +63,12 @@ Because SwiftCheck doesn't require tests to return `Bool`, just `Testable`, we can produce tests for complex properties with ease: ```swift -property("Shrunken lists of integers always contain [] or [0]") <- forAll { (l : ArrayOf) in +property("Shrunken lists of integers always contain [] or [0]") <- forAll { (l : [Int]) in // Here we use the Implication Operator `==>` to define a precondition for // this test. If the precondition fails the test is discarded. If it holds // the test proceeds. - return (!l.getArray.isEmpty && l.getArray != [0]) ==> { - let ls = self.shrinkArbitrary(l).map { $0.getArray } + return (!l.isEmpty && l != [0]) ==> { + let ls = self.shrinkArbitrary(l) return (ls.filter({ $0 == [] || $0 == [0] }).count >= 1) } } diff --git a/Sources/SwiftCheck/Arbitrary.swift b/Sources/SwiftCheck/Arbitrary.swift index ba885e1..17106e7 100644 --- a/Sources/SwiftCheck/Arbitrary.swift +++ b/Sources/SwiftCheck/Arbitrary.swift @@ -23,9 +23,9 @@ /// implementation of `shrink` is provided, SwiftCheck will default to an empty /// one - that is, no shrinking will occur. /// -/// As an example, take the `ArrayOf` implementation of shrink: +/// As an example, take `Array`'s implementation of shrink: /// -/// Arbitrary.shrink(ArrayOf([1, 2, 3])) +/// Arbitrary.shrink([1, 2, 3]) /// > [[], [2,3], [1,3], [1,2], [0,2,3], [1,0,3], [1,1,3], [1,2,0], [1,2,2]] /// /// SwiftCheck will search each case forward, one-by-one, and continue shrinking diff --git a/Sources/SwiftCheck/Modifiers.swift b/Sources/SwiftCheck/Modifiers.swift index 806829d..b37c829 100644 --- a/Sources/SwiftCheck/Modifiers.swift +++ b/Sources/SwiftCheck/Modifiers.swift @@ -37,16 +37,6 @@ /// return xs.map(f.getArrow) == xs.map(f.getArrow) /// } /// } -/// -/// Finally, modifiers nest to allow the generation of intricate structures that -/// would not otherwise be possible due to the limitations above. For example, -/// to generate an Array of Arrays of Dictionaries of Integers and Strings (a -/// type that normally looks like `Array>>`), -/// would look like this: -/// -/// property("Generating monstrous data types is possible") <- forAll { (xs : ArrayOf>>) in -/// /// We're gonna need a bigger boat. -/// } /// For types that either do not have a `CustomStringConvertible` instance or /// that wish to have no description to print, Blind will create a default @@ -115,48 +105,6 @@ extension Static : CoArbitrary { } } -/// Generates an array of arbitrary values of type A. -public struct ArrayOf : Arbitrary, CustomStringConvertible { - /// Retrieves the underlying array of values. - public let getArray : [A] - - /// Retrieves the underlying array of values as a contiguous array. - public var getContiguousArray : ContiguousArray { - return ContiguousArray(self.getArray) - } - - /// Creates a new `ArrayOf` modifier from an underlying array of values. - public init(_ array : [A]) { - self.getArray = array - } - - /// A textual representation of `self`. - public var description : String { - return "\(self.getArray)" - } - - /// Returns a generator of `ArrayOf` values. - public static var arbitrary : Gen> { - return Array.arbitrary.map(ArrayOf.init) - } - - /// The default shrinking function for an `ArrayOf` values. - public static func shrink(_ bl : ArrayOf) -> [ArrayOf] { - return Array.shrink(bl.getArray).map(ArrayOf.init) - } -} - -extension ArrayOf : CoArbitrary { - /// Uses the underlying array of values to perturb a generator. - public static func coarbitrary(_ x : ArrayOf) -> ((Gen) -> Gen) { - let a = x.getArray - if a.isEmpty { - return { $0.variant(0) } - } - return comp({ $0.variant(1) }, ArrayOf.coarbitrary(ArrayOf([A](a[1.. : Arbitrary, CustomStringConvertible { /// Retrieves the underlying sorted array of values. @@ -193,121 +141,6 @@ public struct OrderedArrayOf : Arbitrary, CustomStri } } - -/// Generates an dictionary of arbitrary keys and values. -public struct DictionaryOf : Arbitrary, CustomStringConvertible { - /// Retrieves the underlying dictionary of values. - public let getDictionary : Dictionary - - /// Creates a new `DictionaryOf` modifier from an underlying dictionary of - /// key-value pairs. - public init(_ dict : Dictionary) { - self.getDictionary = dict - } - - /// A textual representation of `self`. - public var description : String { - return "\(self.getDictionary)" - } - - /// Returns a generator for a `DictionaryOf` values. - public static var arbitrary : Gen> { - return Dictionary.arbitrary.map(DictionaryOf.init) - } - - /// The default shrinking function for a `DictionaryOf` values. - public static func shrink(_ d : DictionaryOf) -> [DictionaryOf] { - return Dictionary.shrink(d.getDictionary).map(DictionaryOf.init) - } -} - -extension DictionaryOf : CoArbitrary { - /// Uses the underlying array of values to perturb a generator. - public static func coarbitrary(_ x : DictionaryOf) -> ((Gen) -> Gen) { - return Dictionary.coarbitrary(x.getDictionary) - } -} - -/// Generates an Optional of arbitrary values of type A. -public struct OptionalOf : Arbitrary, CustomStringConvertible { - /// Retrieves the underlying optional value. - public let getOptional : A? - - /// Creates a new `OptionalOf` modifier from an underlying `Optional` value. - public init(_ opt : A?) { - self.getOptional = opt - } - - /// A textual representation of `self`. - public var description : String { - return "\(String(describing: self.getOptional))" - } - - /// Returns a generator for `OptionalOf` values. - public static var arbitrary : Gen> { - return Optional.arbitrary.map(OptionalOf.init) - } - - /// The default shrinking function for `OptionalOf` values. - public static func shrink(_ bl : OptionalOf) -> [OptionalOf] { - return Optional.shrink(bl.getOptional).map(OptionalOf.init) - } -} - -extension OptionalOf : CoArbitrary { - /// Uses the underlying presence or lack of a value to perturb a generator. - public static func coarbitrary(_ x : OptionalOf) -> ((Gen) -> Gen) { - if let _ = x.getOptional { - return { $0.variant(0) } - } - return { $0.variant(1) } - } -} - -/// Generates a set of arbitrary values of type A. -public struct SetOf : Arbitrary, CustomStringConvertible { - /// Retrieves the underlying set of values. - public let getSet : Set - - /// Creates a new `SetOf` modifier from an underlying set of values. - public init(_ set : Set) { - self.getSet = set - } - - /// A textual representation of `self`. - public var description : String { - return "\(self.getSet)" - } - - /// Returns a generator for a `SetOf` values. - public static var arbitrary : Gen> { - return Gen.sized { n in - return Gen.choose((0, n)).flatMap { k in - if k == 0 { - return Gen.pure(SetOf(Set([]))) - } - - return sequence(Array((0...k)).map { _ in A.arbitrary }).map(comp(SetOf.init, Set.init)) - } - } - } - - /// The default shrinking function for a `SetOf` values. - public static func shrink(_ s : SetOf) -> [SetOf] { - return ArrayOf.shrink(ArrayOf([A](s.getSet))).map({ SetOf(Set($0.getArray)) }) - } -} - -extension SetOf : CoArbitrary { - /// Uses the underlying set of values to perturb a generator. - public static func coarbitrary(_ x : SetOf) -> ((Gen) -> Gen) { - if x.getSet.isEmpty { - return { $0.variant(0) } - } - return { $0.variant(1) } - } -} - /// Generates pointers of varying size of random values of type T. public struct PointerOf : Arbitrary, CustomStringConvertible { fileprivate let _impl : PointerOfImpl @@ -663,10 +496,8 @@ private final class PointerOfImpl : Arbitrary { } deinit { - if self.size > 0 && self.ptr != nil { - self.ptr?.deallocate(capacity: self.size) - self.ptr = nil - } + self.ptr?.deallocate() + self.ptr = nil } static var arbitrary : Gen> { diff --git a/Sources/SwiftCheck/Testable.swift b/Sources/SwiftCheck/Testable.swift index c3bd744..c1f4fd9 100644 --- a/Sources/SwiftCheck/Testable.swift +++ b/Sources/SwiftCheck/Testable.swift @@ -79,7 +79,7 @@ extension Bool : Testable { } } -extension Gen /*: Testable*/ where A : Testable { +extension Gen : Testable where A : Testable { public var property : Property { return Property(self.flatMap { $0.property.unProperty }) } diff --git a/Sources/SwiftCheck/Witness.swift b/Sources/SwiftCheck/Witness.swift deleted file mode 100644 index a654e0e..0000000 --- a/Sources/SwiftCheck/Witness.swift +++ /dev/null @@ -1,161 +0,0 @@ -// -// Witness.swift -// SwiftCheck -// -// Created by Robert Widmann on 7/26/15. -// Copyright © 2015 TypeLift. All rights reserved. -// - -/// Provides a way for higher-order types to implement the `Arbitrary` protocol. -/// -/// The `WitnessedArbitrary` protocol is a *HACK*, but a very necessary one. -/// Because Swift does not have Higher Kinded Types, but we need to know that, -/// say, the `Element`s underlying an `Array` are all `Arbitrary`, we -/// instead ask the conformee to hand over information about the type parameter -/// it wishes to guarantee is `Arbitrary` then SwiftCheck will synthesize a -/// function to act as a Witness that the parameter is in fact `Arbitrary`. -/// SwiftCheck presents a stronger but less general version of `forAll` that -/// must be implemented by the conformee to guarantee a type-safe interface with -/// the rest of the framework. -/// -/// Implementating the `WitnessedArbitrary` protocol functions much like -/// implementing the `Arbitrary` protocol, but with a little extra baggage. For -/// example, to implement the protocol for `Array`, we declare the usual -/// `arbitrary` and `shrink`: -/// -/// extension Array where Element : Arbitrary { -/// public static var arbitrary : Gen> { -/// return Gen.sized { n in -/// return Gen.choose((0, n)).flatMap { k in -/// if k == 0 { -/// return Gen.pure([]) -/// } -/// -/// return sequence((0...k).map { _ in Element.arbitrary }) -/// } -/// } -/// } -/// -/// public static func shrink(bl : Array) -> [[Element]] { -/// let rec : [[Element]] = shrinkOne(bl) -/// return Int.shrink(bl.count).reverse().flatMap({ k in removes(k.successor(), n: bl.count, xs: bl) }) + rec -/// } -/// } -/// -/// In addition, we declare a witnessed version of `forAll` that simply invokes -/// `forAllShrink` and `map`s the witness function to make sure all generated -/// `Array`s are made of `Arbitrary ` elements: -/// -/// extension Array : WitnessedArbitrary { -/// public typealias Param = Element -/// -/// public static func forAllWitnessed(wit : A -> Element, pf : ([Element] -> Testable)) -> Property { -/// return forAllShrink([A].arbitrary, shrinker: [A].shrink, f: { bl in -/// return pf(bl.map(wit)) -/// }) -/// } -/// } -public protocol WitnessedArbitrary { - /// The witnessing type parameter. - associatedtype Param - - /// A property test that relies on a witness that the given type parameter - /// is actually `Arbitrary`. - static func forAllWitnessed(_ wit : @escaping (A) -> Param, pf : @escaping (Self) -> Testable) -> Property -} - -/// Converts a function into a universally quantified property using the default -/// shrinker and generator for that type. -/// -/// - parameter pf: A block that carries the property or invariant to be tested. -/// -/// - returns: A `Property` that executes the given testing block. -public func forAll(_ pf : @escaping (A) -> Testable) -> Property - where A.Param : Arbitrary -{ - return A.forAllWitnessed({ $0 }, pf: pf) -} - -/// Converts a function into a universally quantified property using the default -/// shrinker and generator for 2 types. -/// -/// - parameter pf: A block that carries the property or invariant to be tested. -/// -/// - returns: A `Property` that executes the given testing block. -public func forAll(_ pf : @escaping (A, B) -> Testable) -> Property - where A.Param : Arbitrary, B.Param : Arbitrary -{ - return forAll { t in forAll { b in pf(t, b) } } -} - -/// Converts a function into a universally quantified property using the default -/// shrinker and generator for 3 types. -/// -/// - parameter pf: A block that carries the property or invariant to be tested. -/// -/// - returns: A `Property` that executes the given testing block. -public func forAll(_ pf : @escaping (A, B, C) -> Testable) -> Property - where A.Param : Arbitrary, B.Param : Arbitrary, C.Param : Arbitrary -{ - return forAll { t in forAll { b, c in pf(t, b, c) } } -} - -/// Converts a function into a universally quantified property using the default -/// shrinker and generator for 4 types. -/// -/// - parameter pf: A block that carries the property or invariant to be tested. -/// -/// - returns: A `Property` that executes the given testing block. -public func forAll(_ pf : @escaping (A, B, C, D) -> Testable) -> Property - where A.Param : Arbitrary, B.Param : Arbitrary, C.Param : Arbitrary, D.Param : Arbitrary -{ - return forAll { t in forAll { b, c, d in pf(t, b, c, d) } } -} - -/// Converts a function into a universally quantified property using the default -/// shrinker and generator for 5 types. -/// -/// - parameter pf: A block that carries the property or invariant to be tested. -/// -/// - returns: A `Property` that executes the given testing block. -public func forAll(_ pf : @escaping (A, B, C, D, E) -> Testable) -> Property - where A.Param : Arbitrary, B.Param : Arbitrary, C.Param : Arbitrary, D.Param : Arbitrary, E.Param : Arbitrary -{ - return forAll { t in forAll { b, c, d, e in pf(t, b, c, d, e) } } -} - -/// Converts a function into a universally quantified property using the default -/// shrinker and generator for 6 types. -/// -/// - parameter pf: A block that carries the property or invariant to be tested. -/// -/// - returns: A `Property` that executes the given testing block. -public func forAll(_ pf : @escaping (A, B, C, D, E, F) -> Testable) -> Property - where A.Param : Arbitrary, B.Param : Arbitrary, C.Param : Arbitrary, D.Param : Arbitrary, E.Param : Arbitrary, F.Param : Arbitrary -{ - return forAll { t in forAll { b, c, d, e, f in pf(t, b, c, d, e, f) } } -} - -/// Converts a function into a universally quantified property using the default -/// shrinker and generator for 7 types. -/// -/// - parameter pf: A block that carries the property or invariant to be tested. -/// -/// - returns: A `Property` that executes the given testing block. -public func forAll(_ pf : @escaping (A, B, C, D, E, F, G) -> Testable) -> Property - where A.Param : Arbitrary, B.Param : Arbitrary, C.Param : Arbitrary, D.Param : Arbitrary, E.Param : Arbitrary, F.Param : Arbitrary, G.Param : Arbitrary -{ - return forAll { t in forAll { b, c, d, e, f, g in pf(t, b, c, d, e, f, g) } } -} - -/// Converts a function into a universally quantified property using the default -/// shrinker and generator for 8 types. -/// -/// - parameter pf: A block that carries the property or invariant to be tested. -/// -/// - returns: A `Property` that executes the given testing block. -public func forAll(_ pf : @escaping (A, B, C, D, E, F, G, H) -> Testable) -> Property - where A.Param : Arbitrary, B.Param : Arbitrary, C.Param : Arbitrary, D.Param : Arbitrary, E.Param : Arbitrary, F.Param : Arbitrary, G.Param : Arbitrary, H.Param : Arbitrary -{ - return forAll { t in forAll { b, c, d, e, f, g, h in pf(t, b, c, d, e, f, g, h) } } -} diff --git a/Sources/SwiftCheck/WitnessedArbitrary.swift b/Sources/SwiftCheck/WitnessedArbitrary.swift index 5dea544..bc7f9a9 100644 --- a/Sources/SwiftCheck/WitnessedArbitrary.swift +++ b/Sources/SwiftCheck/WitnessedArbitrary.swift @@ -6,7 +6,7 @@ // Copyright © 2016 Typelift. All rights reserved. // -extension Array where Element : Arbitrary { +extension Array : Arbitrary where Element : Arbitrary { /// Returns a generator of `Array`s of arbitrary `Element`s. public static var arbitrary : Gen> { return Element.arbitrary.proliferate @@ -19,19 +19,7 @@ extension Array where Element : Arbitrary { } } -extension Array : WitnessedArbitrary { - public typealias Param = Element - - /// Given a witness and a function to test, converts them into a universally - /// quantified property over `Array`s. - public static func forAllWitnessed(_ wit : @escaping (A) -> Element, pf : @escaping ([Element]) -> Testable) -> Property { - return forAllShrink([A].arbitrary, shrinker: [A].shrink, f: { bl in - return pf(bl.map(wit)) - }) - } -} - -extension AnyBidirectionalCollection where Element : Arbitrary { +extension AnyBidirectionalCollection : Arbitrary where Element : Arbitrary { /// Returns a generator of `AnyBidirectionalCollection`s of arbitrary `Element`s. public static var arbitrary : Gen> { return [Element].arbitrary.map(AnyBidirectionalCollection.init) @@ -43,23 +31,7 @@ extension AnyBidirectionalCollection where Element : Arbitrary { } } -extension AnyBidirectionalCollection : WitnessedArbitrary { - public typealias Param = Element - - /// Given a witness and a function to test, converts them into a universally - /// quantified property over `AnyBidirectionalCollection`s. - public static func forAllWitnessed(_ wit : @escaping (A) -> Element, pf : @escaping (AnyBidirectionalCollection) -> Testable) -> Property { - return forAllShrink( - AnyBidirectionalCollection.arbitrary, - shrinker: AnyBidirectionalCollection.shrink, - f: { bl in - return pf(AnyBidirectionalCollection(bl.map(wit))) - } - ) - } -} - -extension AnySequence where Element : Arbitrary { +extension AnySequence : Arbitrary where Element : Arbitrary { /// Returns a generator of `AnySequence`s of arbitrary `Element`s. public static var arbitrary : Gen> { return [Element].arbitrary.map(AnySequence.init) @@ -71,19 +43,7 @@ extension AnySequence where Element : Arbitrary { } } -extension AnySequence : WitnessedArbitrary { - public typealias Param = Element - - /// Given a witness and a function to test, converts them into a universally - /// quantified property over `AnySequence`s. - public static func forAllWitnessed(_ wit : @escaping (A) -> Element, pf : @escaping (AnySequence) -> Testable) -> Property { - return forAllShrink(AnySequence.arbitrary, shrinker: AnySequence.shrink, f: { bl in - return pf(AnySequence(bl.map(wit))) - }) - } -} - -extension ArraySlice where Element : Arbitrary { +extension ArraySlice : Arbitrary where Element : Arbitrary { /// Returns a generator of `ArraySlice`s of arbitrary `Element`s. public static var arbitrary : Gen> { return [Element].arbitrary.map(ArraySlice.init) @@ -95,39 +55,15 @@ extension ArraySlice where Element : Arbitrary { } } -extension ArraySlice : WitnessedArbitrary { - public typealias Param = Element - - /// Given a witness and a function to test, converts them into a universally - /// quantified property over `ArraySlice`s. - public static func forAllWitnessed(_ wit : @escaping (A) -> Element, pf : @escaping (ArraySlice) -> Testable) -> Property { - return forAllShrink(ArraySlice.arbitrary, shrinker: ArraySlice.shrink, f: { bl in - return pf(ArraySlice(bl.map(wit))) - }) - } -} - -extension CollectionOfOne where Element : Arbitrary { +extension CollectionOfOne : Arbitrary where Element : Arbitrary { /// Returns a generator of `CollectionOfOne`s of arbitrary `Element`s. public static var arbitrary : Gen> { return Element.arbitrary.map(CollectionOfOne.init) } } -extension CollectionOfOne : WitnessedArbitrary { - public typealias Param = Element - - /// Given a witness and a function to test, converts them into a universally - /// quantified property over `CollectionOfOne`s. - public static func forAllWitnessed(_ wit : @escaping (A) -> Element, pf : @escaping (CollectionOfOne) -> Testable) -> Property { - return forAllShrink(CollectionOfOne.arbitrary, shrinker: { _ in [] }, f: { (bl : CollectionOfOne) -> Testable in - return pf(CollectionOfOne(wit(bl[bl.startIndex]))) - }) - } -} - /// Generates an Optional of arbitrary values of type A. -extension Optional where Wrapped : Arbitrary { +extension Optional : Arbitrary where Wrapped : Arbitrary { /// Returns a generator of `Optional`s of arbitrary `Wrapped` values. public static var arbitrary : Gen> { return Gen>.frequency([ @@ -146,19 +82,7 @@ extension Optional where Wrapped : Arbitrary { } } -extension Optional : WitnessedArbitrary { - public typealias Param = Wrapped - - /// Given a witness and a function to test, converts them into a universally - /// quantified property over `Optional`s. - public static func forAllWitnessed(_ wit : @escaping (A) -> Wrapped, pf : @escaping (Optional) -> Testable) -> Property { - return forAllShrink(Optional.arbitrary, shrinker: Optional.shrink, f: { bl in - return pf(bl.map(wit)) - }) - } -} - -extension ContiguousArray where Element : Arbitrary { +extension ContiguousArray : Arbitrary where Element : Arbitrary { /// Returns a generator of `ContiguousArray`s of arbitrary `Element`s. public static var arbitrary : Gen> { return [Element].arbitrary.map(ContiguousArray.init) @@ -170,20 +94,8 @@ extension ContiguousArray where Element : Arbitrary { } } -extension ContiguousArray : WitnessedArbitrary { - public typealias Param = Element - - /// Given a witness and a function to test, converts them into a universally - /// quantified property over `ContiguousArray`s. - public static func forAllWitnessed(_ wit : @escaping (A) -> Element, pf : @escaping (ContiguousArray) -> Testable) -> Property { - return forAllShrink(ContiguousArray.arbitrary, shrinker: ContiguousArray.shrink, f: { bl in - return pf(ContiguousArray(bl.map(wit))) - }) - } -} - /// Generates an dictionary of arbitrary keys and values. -extension Dictionary where Key : Arbitrary, Value : Arbitrary { +extension Dictionary : Arbitrary where Key : Arbitrary, Value : Arbitrary { /// Returns a generator of `Dictionary`s of arbitrary `Key`s and `Value`s. public static var arbitrary : Gen> { return [Key].arbitrary.flatMap { (k : [Key]) in @@ -207,7 +119,7 @@ extension EmptyCollection : Arbitrary { } } -extension Range where Bound : Arbitrary { +extension Range : Arbitrary where Bound : Arbitrary { /// Returns a generator of `HalfOpenInterval`s of arbitrary `Bound`s. public static var arbitrary : Gen> { return Bound.arbitrary.flatMap { l in @@ -223,21 +135,21 @@ extension Range where Bound : Arbitrary { } } -extension LazyCollection where Base : Arbitrary { +extension LazyCollection : Arbitrary where Base : Arbitrary { /// Returns a generator of `LazyCollection`s of arbitrary `Base`s. public static var arbitrary : Gen> { return LazyCollection.arbitrary } } -extension LazySequence where Base : Arbitrary { +extension LazySequence : Arbitrary where Base : Arbitrary { /// Returns a generator of `LazySequence`s of arbitrary `Base`s. public static var arbitrary : Gen> { return LazySequence.arbitrary } } -extension Repeated where Element : Arbitrary { +extension Repeated : Arbitrary where Element : Arbitrary { /// Returns a generator of `Repeat`s of arbitrary `Element`s. public static var arbitrary : Gen> { let constructor: (Element, Int) -> Repeated = { (element, count) in @@ -248,20 +160,7 @@ extension Repeated where Element : Arbitrary { } } -extension Repeated : WitnessedArbitrary { - public typealias Param = Element - - /// Given a witness and a function to test, converts them into a universally - /// quantified property over `Repeat`s. - public static func forAllWitnessed(_ wit : @escaping (A) -> Element, pf : @escaping (Repeated) -> Testable) -> Property { - return forAllShrink(Repeated.arbitrary, shrinker: { _ in [] }, f: { bl in - let xs = bl.map(wit) - return pf(repeatElement(xs.first!, count: xs.count)) - }) - } -} - -extension Set where Element : Arbitrary { +extension Set : Arbitrary where Element : Arbitrary { /// Returns a generator of `Set`s of arbitrary `Element`s. public static var arbitrary : Gen> { return Gen.sized { n in @@ -281,18 +180,6 @@ extension Set where Element : Arbitrary { } } -extension Set : WitnessedArbitrary { - public typealias Param = Element - - /// Given a witness and a function to test, converts them into a universally - /// quantified property over `Set`s. - public static func forAllWitnessed(_ wit : @escaping (A) -> Element, pf : @escaping (Set) -> Testable) -> Property { - return forAll { (xs : [A]) in - return pf(Set(xs.map(wit))) - } - } -} - // MARK: - Implementation Details Follow private func removes(_ k : Int, n : Int, xs : [A]) -> [[A]] { diff --git a/SwiftCheck.xcodeproj/project.pbxproj b/SwiftCheck.xcodeproj/project.pbxproj index d575527..a0fe41b 100644 --- a/SwiftCheck.xcodeproj/project.pbxproj +++ b/SwiftCheck.xcodeproj/project.pbxproj @@ -22,7 +22,6 @@ 6A761BAA1F14E92100A7D74F /* SwiftCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A761B831F14E91500A7D74F /* SwiftCheck.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6A761BAB1F14E92100A7D74F /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B841F14E91500A7D74F /* Test.swift */; }; 6A761BAC1F14E92100A7D74F /* Testable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B851F14E91500A7D74F /* Testable.swift */; }; - 6A761BAD1F14E92100A7D74F /* Witness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B861F14E91500A7D74F /* Witness.swift */; }; 6A761BAE1F14E92100A7D74F /* WitnessedArbitrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B871F14E91500A7D74F /* WitnessedArbitrary.swift */; }; 6A761BAF1F14E92100A7D74F /* Arbitrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B771F14E91400A7D74F /* Arbitrary.swift */; }; 6A761BB01F14E92200A7D74F /* Cartesian.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B781F14E91400A7D74F /* Cartesian.swift */; }; @@ -39,7 +38,6 @@ 6A761BBB1F14E92200A7D74F /* SwiftCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A761B831F14E91500A7D74F /* SwiftCheck.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6A761BBC1F14E92200A7D74F /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B841F14E91500A7D74F /* Test.swift */; }; 6A761BBD1F14E92200A7D74F /* Testable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B851F14E91500A7D74F /* Testable.swift */; }; - 6A761BBE1F14E92200A7D74F /* Witness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B861F14E91500A7D74F /* Witness.swift */; }; 6A761BBF1F14E92200A7D74F /* WitnessedArbitrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B871F14E91500A7D74F /* WitnessedArbitrary.swift */; }; 6A761BC01F14E92200A7D74F /* Arbitrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B771F14E91400A7D74F /* Arbitrary.swift */; }; 6A761BC11F14E92200A7D74F /* Cartesian.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B781F14E91400A7D74F /* Cartesian.swift */; }; @@ -56,7 +54,6 @@ 6A761BCC1F14E92200A7D74F /* SwiftCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A761B831F14E91500A7D74F /* SwiftCheck.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6A761BCD1F14E92200A7D74F /* Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B841F14E91500A7D74F /* Test.swift */; }; 6A761BCE1F14E92200A7D74F /* Testable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B851F14E91500A7D74F /* Testable.swift */; }; - 6A761BCF1F14E92200A7D74F /* Witness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B861F14E91500A7D74F /* Witness.swift */; }; 6A761BD01F14E92200A7D74F /* WitnessedArbitrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B871F14E91500A7D74F /* WitnessedArbitrary.swift */; }; 6A761BD11F14E93900A7D74F /* BooleanIdentitySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B8D1F14E91500A7D74F /* BooleanIdentitySpec.swift */; }; 6A761BD21F14E93900A7D74F /* CartesianSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B8E1F14E91500A7D74F /* CartesianSpec.swift */; }; @@ -195,7 +192,6 @@ 6A761B831F14E91500A7D74F /* SwiftCheck.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftCheck.h; sourceTree = ""; }; 6A761B841F14E91500A7D74F /* Test.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Test.swift; sourceTree = ""; }; 6A761B851F14E91500A7D74F /* Testable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Testable.swift; sourceTree = ""; }; - 6A761B861F14E91500A7D74F /* Witness.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Witness.swift; sourceTree = ""; }; 6A761B871F14E91500A7D74F /* WitnessedArbitrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WitnessedArbitrary.swift; sourceTree = ""; }; 6A761B881F14E91500A7D74F /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 6A761B8A1F14E91500A7D74F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -308,7 +304,6 @@ 6A761B821F14E91500A7D74F /* State.swift */, 6A761B841F14E91500A7D74F /* Test.swift */, 6A761B851F14E91500A7D74F /* Testable.swift */, - 6A761B861F14E91500A7D74F /* Witness.swift */, 6A761B871F14E91500A7D74F /* WitnessedArbitrary.swift */, ); path = SwiftCheck; @@ -537,7 +532,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 0930; ORGANIZATIONNAME = Typelift; TargetAttributes = { 8240CCB01C3A123600EF4D29 = { @@ -669,7 +664,6 @@ 6A761BC31F14E92200A7D74F /* CoArbitrary.swift in Sources */, 6A761BC21F14E92200A7D74F /* Check.swift in Sources */, 6A761BC41F14E92200A7D74F /* Compose.swift in Sources */, - 6A761BCF1F14E92200A7D74F /* Witness.swift in Sources */, 6A761BCB1F14E92200A7D74F /* State.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -721,7 +715,6 @@ 6A761BA11F14E92100A7D74F /* CoArbitrary.swift in Sources */, 6A761BA01F14E92100A7D74F /* Check.swift in Sources */, 6A761BA21F14E92100A7D74F /* Compose.swift in Sources */, - 6A761BAD1F14E92100A7D74F /* Witness.swift in Sources */, 6A761BA91F14E92100A7D74F /* State.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -773,7 +766,6 @@ 6A761BB21F14E92200A7D74F /* CoArbitrary.swift in Sources */, 6A761BB11F14E92200A7D74F /* Check.swift in Sources */, 6A761BB31F14E92200A7D74F /* Compose.swift in Sources */, - 6A761BBE1F14E92200A7D74F /* Witness.swift in Sources */, 6A761BBA1F14E92200A7D74F /* State.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -949,12 +941,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -1003,12 +997,14 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; diff --git a/SwiftCheck.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SwiftCheck.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/SwiftCheck.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SwiftCheck.xcodeproj/xcshareddata/xcschemes/SwiftCheck-iOS.xcscheme b/SwiftCheck.xcodeproj/xcshareddata/xcschemes/SwiftCheck-iOS.xcscheme index e1d02b1..4a0ec67 100644 --- a/SwiftCheck.xcodeproj/xcshareddata/xcschemes/SwiftCheck-iOS.xcscheme +++ b/SwiftCheck.xcodeproj/xcshareddata/xcschemes/SwiftCheck-iOS.xcscheme @@ -1,6 +1,6 @@ { func format(_ value : Value) -> String { let formatted = makeString(value) - let maxIndex = formatted.index(formatted.startIndex, offsetBy: String.IndexDistance(lengthLimit)) + let maxIndex = formatted.index(formatted.startIndex, offsetBy: Int(lengthLimit)) if maxIndex >= formatted.endIndex { return formatted } else { @@ -76,7 +76,7 @@ class FormatterSpec : XCTestCase { let formatter = af.get let string = formatter.format(x) _ = formatter.unFormat(string) - return string.distance(from: string.startIndex, to: string.endIndex) <= String.IndexDistance(formatter.lengthLimit) + return string.distance(from: string.startIndex, to: string.endIndex) <= Int(formatter.lengthLimit) } }) diff --git a/Tests/SwiftCheckTests/GenSpec.swift b/Tests/SwiftCheckTests/GenSpec.swift index 567af82..93d0fca 100644 --- a/Tests/SwiftCheckTests/GenSpec.swift +++ b/Tests/SwiftCheckTests/GenSpec.swift @@ -147,12 +147,12 @@ class GenSpec : XCTestCase { // CHECK-NEXT: *** Passed 100 tests // CHECK-NEXT: . - property("oneOf n") <- forAll { (xss : ArrayOf) in - if xss.getArray.isEmpty { + property("oneOf n") <- forAll { (xss : [Int]) in + if xss.isEmpty { return Discard() } - let l = Set(xss.getArray) - return forAll(Gen.one(of: xss.getArray.map(Gen.pure))) { l.contains($0) } + let l = Set(xss) + return forAll(Gen.one(of: xss.map(Gen.pure))) { l.contains($0) } } // CHECK-NEXT: *** Passed 100 tests @@ -166,14 +166,14 @@ class GenSpec : XCTestCase { // CHECK-NEXT: *** Passed 100 tests // CHECK-NEXT: . property("Gen.proliferateSized n generates arrays of length n") <- forAll(Gen.choose((0, 100))) { n in - let g = Int.arbitrary.proliferate(withSize: n).map(ArrayOf.init) - return forAll(g) { $0.getArray.count == n } + let g = Int.arbitrary.proliferate(withSize: n) + return forAll(g) { $0.count == n } } // CHECK-NEXT: *** Passed 100 tests // CHECK-NEXT: . - property("Gen.proliferateSized 0 generates only empty arrays") <- forAll(Int.arbitrary.proliferate(withSize: 0).map(ArrayOf.init)) { - return $0.getArray.isEmpty + property("Gen.proliferateSized 0 generates only empty arrays") <- forAll(Int.arbitrary.proliferate(withSize: 0)) { + return $0.isEmpty } // CHECK-NEXT: *** Passed 100 tests diff --git a/Tests/SwiftCheckTests/LambdaSpec.swift b/Tests/SwiftCheckTests/LambdaSpec.swift index 618ca55..cac0381 100644 --- a/Tests/SwiftCheckTests/LambdaSpec.swift +++ b/Tests/SwiftCheckTests/LambdaSpec.swift @@ -82,7 +82,7 @@ extension Exp : Arbitrary { return [a] + Exp.shrink(a).map { .lam(x, $0) } case let .app(a, b): let part1 : [Exp] = [a, b] - + [a].flatMap({ (expr : Exp) -> Exp? in + + [a].compactMap({ (expr : Exp) -> Exp? in if case let .lam(x, a) = expr { return a.subst(x, b) } diff --git a/Tests/SwiftCheckTests/ModifierSpec.swift b/Tests/SwiftCheckTests/ModifierSpec.swift index 3363791..a5827b6 100644 --- a/Tests/SwiftCheckTests/ModifierSpec.swift +++ b/Tests/SwiftCheckTests/ModifierSpec.swift @@ -53,22 +53,22 @@ class ModifierSpec : XCTestCase { // CHECK-NEXT: *** Passed 100 tests // CHECK-NEXT: . - property("ArrayOf modifiers nest") <- forAll { (xxxs : ArrayOf>) in + property("ArrayOf modifiers nest") <- forAll { (xxs : [[Int8]]) in return true } // CHECK-NEXT: *** Passed 100 tests // CHECK-NEXT: (100%, {{Left|Right}} identity, {{Left|Right}} identity) - property("The reverse of the reverse of an array is that array") <- forAll { (xs : ArrayOf) in - return (xs.getArray.reversed().reversed() == xs.getArray) "Left identity" + property("The reverse of the reverse of an array is that array") <- forAll { (xs : [Int]) in + return (xs.reversed().reversed() == xs) "Left identity" ^&&^ - (xs.getArray == xs.getArray.reversed().reversed()) "Right identity" + (xs == xs.reversed().reversed()) "Right identity" } // CHECK-NEXT: *** Passed 100 tests // CHECK-NEXT: . - property("map behaves") <- forAll { (xs : ArrayOf, f : ArrowOf) in - return xs.getArray.map(f.getArrow) == xs.getArray.map(f.getArrow) + property("map behaves") <- forAll { (xs : [Int], f : ArrowOf) in + return xs.map(f.getArrow) == xs.map(f.getArrow) } // CHECK-NEXT: *** Passed 100 tests @@ -81,9 +81,9 @@ class ModifierSpec : XCTestCase { // CHECK-NEXT: *** Passed 100 tests // CHECK-NEXT: . - property("filter behaves") <- forAll { (xs : ArrayOf, pred : ArrowOf) in + property("filter behaves") <- forAll { (xs : [Int], pred : ArrowOf) in let f = pred.getArrow - return (xs.getArray.filter(f).reduce(true, { (acc, val) in acc && f(val) }) as Bool) + return (xs.filter(f).reduce(true, { (acc, val) in acc && f(val) }) as Bool) } }) } diff --git a/Tests/SwiftCheckTests/PropertySpec.swift b/Tests/SwiftCheckTests/PropertySpec.swift index 909941f..344fe89 100644 --- a/Tests/SwiftCheckTests/PropertySpec.swift +++ b/Tests/SwiftCheckTests/PropertySpec.swift @@ -62,7 +62,7 @@ class PropertySpec : XCTestCase { // CHECK-NEXT: . property("Again undoes once") <- forAll { (n : Int) in var counter : Int = 0 - quickCheck(forAll { (_ : Int) in + quickCheck(asserting: "", property: forAll { (_ : Int) in counter += 1 return true }.once.again) diff --git a/Tests/SwiftCheckTests/ShrinkSpec.swift b/Tests/SwiftCheckTests/ShrinkSpec.swift index eb26b7d..182f9d3 100644 --- a/Tests/SwiftCheckTests/ShrinkSpec.swift +++ b/Tests/SwiftCheckTests/ShrinkSpec.swift @@ -49,9 +49,9 @@ class ShrinkSpec : XCTestCase { // CHECK-NEXT: *** Passed 100 tests // CHECK-NEXT: . - property("Shrunken arrays of integers always contain [] or [0]") <- forAll { (l : ArrayOf) in - return (!l.getArray.isEmpty && l.getArray != [0]) ==> { - let ls = self.shrinkArbitrary(l).map { $0.getArray } + property("Shrunken arrays of integers always contain [] or [0]") <- forAll { (l : [Int]) in + return (!l.isEmpty && l != [0]) ==> { + let ls = self.shrinkArbitrary(l) return (ls.filter({ $0 == [] || $0 == [0] }).count >= 1) } } diff --git a/Tests/SwiftCheckTests/SimpleSpec.swift b/Tests/SwiftCheckTests/SimpleSpec.swift index 918169f..f9b0f29 100644 --- a/Tests/SwiftCheckTests/SimpleSpec.swift +++ b/Tests/SwiftCheckTests/SimpleSpec.swift @@ -13,11 +13,11 @@ import FileCheck #endif private func pack(_ f : @escaping (A, B) -> C) -> ((A, B)) -> C { - return f + return { xs in f(xs.0, xs.1) } } private func pack(_ f : @escaping (A, B, C, D, E, F, G, H, I, J, K, L, M, N) -> O) -> ((A, B, C, D, E, F, G, H, I, J, K, L, M, N)) -> O { - return f + return { xs in f(xs.0, xs.1, xs.2, xs.3, xs.4, xs.5, xs.6, xs.7, xs.8, xs.9, xs.10, xs.11, xs.12, xs.13) } } public struct ArbitraryFoo { diff --git a/Tutorial.playground/Contents.swift b/Tutorial.playground/Contents.swift index d62b475..7c07839 100644 --- a/Tutorial.playground/Contents.swift +++ b/Tutorial.playground/Contents.swift @@ -336,11 +336,11 @@ property("The reverse of the reverse of an array is that array") <- forAll { (xs //: Because `forAll` is variadic it works for a large number and variety of types too: -// +--- This Modifier Type produces Arrays of Integers. -// | +--- This Modifier Type generates functions. That's right, SwiftCheck -// | | can generate *functions*!! -// v v -property("filter behaves") <- forAll { (xs : ArrayOf, pred : ArrowOf) in +// +--- Produce arrays of integers. +// | +--- This Modifier Type generates functions. That's right, SwiftCheck +// | | can generate *functions*!! +// v v +property("filter behaves") <- forAll { (xs : [Int], pred : ArrowOf) in let f = pred.getArrow return xs.getArray.filter(f).reduce(true, { $0 && f($1) }) // ^ This property says that if we filter an array then apply the predicate diff --git a/Tutorial.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Tutorial.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Tutorial.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + +