diff --git a/.travis.yml b/.travis.yml index 3477e13..7a41ec2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,13 +32,13 @@ matrix: - os: linux language: generic sudo: required - dist: trusty + dist: xenial 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-5.0-release/ubuntu1404/swift-5.0-RELEASE/swift-5.0-RELEASE-ubuntu14.04.tar.gz - - tar xzf swift-5.0-RELEASE-ubuntu14.04.tar.gz - - export PATH=${PWD}/swift-5.0-RELEASE-ubuntu14.04/usr/bin:"${PATH}" + - wget https://swift.org/builds/swift-5.2.4-release/ubuntu1604/swift-5.2.4-RELEASE/swift-5.2.4-RELEASE-ubuntu16.04.tar.gz + - tar xzf swift-5.2.4-RELEASE-ubuntu16.04.tar.gz + - export PATH=${PWD}/swift-5.2.4-RELEASE-ubuntu16.04/usr/bin:"${PATH}" - pushd Utilities - ./compile.sh - popd diff --git a/Sources/SwiftCheck/Arbitrary.swift b/Sources/SwiftCheck/Arbitrary.swift index b4e8ca8..af21212 100644 --- a/Sources/SwiftCheck/Arbitrary.swift +++ b/Sources/SwiftCheck/Arbitrary.swift @@ -370,6 +370,62 @@ extension Mirror : Arbitrary { } } +import Foundation + +extension Date: Arbitrary { + public static var arbitrary: Gen { + return TimeInterval.arbitrary.map(Date.init(timeIntervalSinceNow:)) + } +} + +extension UUID: Arbitrary { + /// Returns a generator of `UUID` values. + public static var arbitrary: Gen { + return Gen.compose { composer in + var bytes = (0..<16).map { _ in composer.generate(using: UInt8.arbitrary) } + bytes[7] = bytes[7] | 0b01000000 // UUID version 4 + bytes[9] = bytes[9] | 0b01000000 // clock_seq_hi_and_reserved + + let part1 = Data(bytes[0..<4]).hexEncodedString() + let part2 = Data(bytes[4..<6]).hexEncodedString() + let part3 = Data(bytes[6..<8]).hexEncodedString() + let part4 = Data(bytes[8..<10]).hexEncodedString() + let part5 = Data(bytes[10..<16]).hexEncodedString() + + return UUID(uuidString: part1 + "-" + part2 + "-" + part3 + "-" + part4 + "-" + part5)! + } + } +} + +extension Data { + + /// Creates a new `Data` instance using the hexadecimal-encoded string. + /// + /// - Parameter string: A string with even non-zero length containing only digits or a/A through f/F. + public init?(hexEncoded string: String) { + if string.count == 0 || string.count % 2 != 0 { return nil } + + var bytes = [UInt8]() + var start = string.startIndex + while start < string.endIndex { + let chunkEnd = string.index(start, offsetBy: 2) + let chunk = string[start.. String { + return [UInt8](self).map { String(format: "%.2x", $0) }.reduce("", {$0+$1}) + } +} + #if os(Linux) import Glibc #else diff --git a/SwiftCheck.xcodeproj/project.pbxproj b/SwiftCheck.xcodeproj/project.pbxproj index 60aad52..e0a18f4 100644 --- a/SwiftCheck.xcodeproj/project.pbxproj +++ b/SwiftCheck.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 02135F9324AA3BB300E33BF1 /* ArbitrarySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02135F9224AA3BA800E33BF1 /* ArbitrarySpec.swift */; }; + 02135F9424AA3BB300E33BF1 /* ArbitrarySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02135F9224AA3BA800E33BF1 /* ArbitrarySpec.swift */; }; + 02135F9524AA3BB400E33BF1 /* ArbitrarySpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02135F9224AA3BA800E33BF1 /* ArbitrarySpec.swift */; }; 6A761B9E1F14E92100A7D74F /* Arbitrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B771F14E91400A7D74F /* Arbitrary.swift */; }; 6A761B9F1F14E92100A7D74F /* Cartesian.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B781F14E91400A7D74F /* Cartesian.swift */; }; 6A761BA01F14E92100A7D74F /* Check.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A761B791F14E91400A7D74F /* Check.swift */; }; @@ -176,6 +179,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 02135F9224AA3BA800E33BF1 /* ArbitrarySpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArbitrarySpec.swift; sourceTree = ""; }; 6A761B751F14E91400A7D74F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 6A761B771F14E91400A7D74F /* Arbitrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Arbitrary.swift; sourceTree = ""; }; 6A761B781F14E91400A7D74F /* Cartesian.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cartesian.swift; sourceTree = ""; }; @@ -328,6 +332,7 @@ 6A761B8C1F14E91500A7D74F /* SwiftCheckTests */ = { isa = PBXGroup; children = ( + 02135F9224AA3BA800E33BF1 /* ArbitrarySpec.swift */, 6A761B8D1F14E91500A7D74F /* BooleanIdentitySpec.swift */, 6A761B8E1F14E91500A7D74F /* CartesianSpec.swift */, 6A761B8F1F14E91500A7D74F /* ComplexSpec.swift */, @@ -676,6 +681,7 @@ 8235D34C1F72DD0B00207FA1 /* Diagnostics.swift in Sources */, 8235D34D1F72DD0B00207FA1 /* EditDistance.swift in Sources */, 8235D34E1F72DD0B00207FA1 /* FileCheck.swift in Sources */, + 02135F9524AA3BB400E33BF1 /* ArbitrarySpec.swift in Sources */, 8235D34F1F72DD0B00207FA1 /* Pattern.swift in Sources */, 6A761C021F14E93B00A7D74F /* SimpleSpec.swift in Sources */, 6A761C031F14E93B00A7D74F /* TestSpec.swift in Sources */, @@ -727,6 +733,7 @@ 8235D3561F72DD2200207FA1 /* CheckString.swift in Sources */, 8235D3571F72DD2200207FA1 /* ColoredStream.swift in Sources */, 8235D3581F72DD2200207FA1 /* Diagnostics.swift in Sources */, + 02135F9324AA3BB300E33BF1 /* ArbitrarySpec.swift in Sources */, 8235D3591F72DD2200207FA1 /* EditDistance.swift in Sources */, 8235D35A1F72DD2200207FA1 /* FileCheck.swift in Sources */, 8235D35B1F72DD2200207FA1 /* Pattern.swift in Sources */, @@ -778,6 +785,7 @@ 8235D3501F72DD1B00207FA1 /* CheckString.swift in Sources */, 8235D3511F72DD1B00207FA1 /* ColoredStream.swift in Sources */, 8235D3521F72DD1B00207FA1 /* Diagnostics.swift in Sources */, + 02135F9424AA3BB300E33BF1 /* ArbitrarySpec.swift in Sources */, 8235D3531F72DD1B00207FA1 /* EditDistance.swift in Sources */, 8235D3541F72DD1B00207FA1 /* FileCheck.swift in Sources */, 8235D3551F72DD1B00207FA1 /* Pattern.swift in Sources */, diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index fc2c0b5..b0a8ce4 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -12,6 +12,7 @@ import XCTest #if !os(macOS) XCTMain([ + ArbitrarySpec.allTests, BooleanIdentitySpec.allTests, ComplexSpec.allTests, DiscardSpec.allTests, diff --git a/Tests/SwiftCheckTests/ArbitrarySpec.swift b/Tests/SwiftCheckTests/ArbitrarySpec.swift new file mode 100644 index 0000000..ba07a25 --- /dev/null +++ b/Tests/SwiftCheckTests/ArbitrarySpec.swift @@ -0,0 +1,34 @@ +import SwiftCheck +import XCTest +import Foundation +#if SWIFT_PACKAGE +import FileCheck +#endif + +class ArbitrarySpec : XCTestCase { + func testAll() { + XCTAssert(fileCheckOutput { + // CHECK: *** Passed 100 tests + // CHECK-NEXT: . + property("generates arbitrary `Date`s") <- forAll { (_ : Date) in + // The fact that we can return something here means that + // generating the Date succeeded + return true + } + + // CHECK: *** Passed 100 tests + // CHECK-NEXT: . + property("generates arbitrary `UUID`s") <- forAll { (_ : UUID) in + // The fact that we can return something here means that + // generating the UUID succeeded + return true + } + }) + } + + #if !(os(macOS) || os(iOS) || os(watchOS) || os(tvOS)) + static var allTests = testCase([ + ("testAll", testAll), + ]) + #endif +}