Files
swift-mirror/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
2015-05-07 00:30:41 +00:00

2710 lines
77 KiB
Swift

//===--- StdlibUnittest.swift.gyb -----------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import SwiftPrivate
import SwiftPrivatePthreadExtras
import SwiftPrivateDarwinExtras
#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#elseif os(Linux)
import Glibc
#endif
#if _runtime(_ObjC)
import ObjectiveC
#endif
public struct SourceLoc {
public let file: String
public let line: UWord
public let comment: String?
public init(_ file: String, _ line: UWord, comment: String? = nil) {
self.file = file
self.line = line
self.comment = comment
}
public func withCurrentLoc(
file: String = __FILE__, line: UWord = __LINE__
) -> SourceLocStack {
return SourceLocStack(self).with(SourceLoc(file, line))
}
}
public struct SourceLocStack {
let locs: _UnitTestArray<SourceLoc>
public init() {
locs = []
}
public init(_ loc: SourceLoc) {
locs = [ loc ]
}
init(_locs: _UnitTestArray<SourceLoc>) {
locs = _locs
}
var isEmpty: Bool {
return locs.isEmpty
}
public func with(loc: SourceLoc) -> SourceLocStack {
var locs = self.locs
locs.append(loc)
return SourceLocStack(_locs: locs)
}
public func withCurrentLoc(
file: String = __FILE__, line: UWord = __LINE__
) -> SourceLocStack {
return with(SourceLoc(file, line))
}
}
func _printStackTrace(stackTrace: SourceLocStack?) {
guard let s = stackTrace else { return }
println("stacktrace:")
for i in 0..<s.locs.count() {
let loc = s.locs[s.locs.count() - i - 1]
let comment = (loc.comment != nil) ? " ; \(loc.comment!)" : ""
println(" #\(i): \(loc.file):\(loc.line)\(comment)")
}
}
// FIXME: these variables should be atomic, since multiple threads can call
// `expect*()` functions.
var _anyExpectFailed = false
var _seenExpectCrash = false
public func expectEqual<T : Equatable>(
expected: T, _ actual: T,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
expectEqual(expected, actual, {$0 == $1},
stackTrace: stackTrace, file: file, line: line,
collectMoreInfo: collectMoreInfo)
}
public func expectEqual<T : Equatable, U : Equatable>(
expected: (T, U), _ actual: (T, U),
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
expectEqual(expected.0, actual.0, {$0 == $1},
stackTrace: stackTrace, file: file, line: line,
collectMoreInfo: collectMoreInfo)
expectEqual(expected.1, actual.1, {$0 == $1},
stackTrace: stackTrace, file: file, line: line,
collectMoreInfo: collectMoreInfo)
}
public func expectEqual<T>(
expected: T, _ actual: T, _ equal: (T,T)->Bool,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if !equal(expected, actual) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\" (of type \(_stdlib_getDemangledTypeName(expected)))")
println("actual: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(expected)))")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
public func expectNotEqual<T : Equatable>(
expected: T, _ actual: T,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if expected == actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("unexpected value: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
// Can not write a sane set of overloads using generics because of:
// <rdar://problem/17015923> Array->NSArray implicit conversion insanity
public func expectOptionalEqual<T : Equatable>(
expected: T, _ actual: T?,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__
) {
if (actual == nil) || expected != actual! {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\" (of type \(_stdlib_getDemangledTypeName(expected)))")
println("actual: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
println()
}
}
public func expectEqual<T : Equatable>(
expected: T?, _ actual: T?,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__
) {
if (actual == nil) != (expected == nil)
|| actual != nil && expected! != actual! {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\" (of type \(_stdlib_getDemangledTypeName(expected)))")
println("actual: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
println()
}
}
// Array<T> is not Equatable if T is. Provide additional overloads.
// Same for Dictionary.
%for (Generic, EquatableType) in [
% ('<T : Equatable>', 'ContiguousArray<T>'),
% ('<T : Equatable>', '_UnitTestArray<T>'),
% ('<T : Equatable>', 'ArraySlice<T>'),
% ('<T : Equatable>', 'Array<T>'),
% ('<T, U : Equatable>', 'Dictionary<T, U>')]:
public func expectEqual${Generic}(
expected: ${EquatableType}, _ actual: ${EquatableType},
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
expectEqual(
expected, actual,
// FIXME: Simpler closures don't work here due to
// <rdar://problem/17716712> and <rdar://problem/17717618>
{ (x: ${EquatableType}, y: ${EquatableType})->Bool in x == y },
stackTrace: stackTrace, file: file, line: line,
collectMoreInfo: collectMoreInfo)
}
public func expectEqualSequence${Generic}(
expected: ${EquatableType}, _ actual: ${EquatableType},
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
expectEqual(
expected, actual,
// FIXME: Simpler closures don't work here due to
// <rdar://problem/17716712> and <rdar://problem/17717618>
{ (x: ${EquatableType}, y: ${EquatableType})->Bool in x == y },
stackTrace: stackTrace, file: file, line: line,
collectMoreInfo: collectMoreInfo)
}
func _expectNotEqual${Generic}(
expected: ${EquatableType}, actual: ${EquatableType},
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if expected == actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("unexpected value: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
public func expectOptionalEqual${Generic}(
expected: ${EquatableType}, _ actual: ${EquatableType}?,
file: String = __FILE__, line: UWord = __LINE__
) {
if (actual == nil) || expected != actual! {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("expected: \"\(expected)\" (of type \(_stdlib_getDemangledTypeName(expected)))")
println("actual: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
println()
}
}
%end
%for ComparableType in ['Int']:
public func expectLT(
expected: ${ComparableType}, _ actual: ${ComparableType},
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if !(expected < actual) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\"")
println("actual: \"\(actual)\"")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
public func expectLE(
expected: ${ComparableType}, _ actual: ${ComparableType},
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if !(expected <= actual) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\"")
println("actual: \"\(actual)\"")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
public func expectGE(
expected: ${ComparableType}, _ actual: ${ComparableType},
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if !(expected >= actual) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\"")
println("actual: \"\(actual)\"")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
%end
public func expectType<T>(_: T.Type, inout _ x: T) {}
public func isSequenceType<X : SequenceType>(x: X) -> X { return x }
public func expectIsBooleanType<X : BooleanType>(inout x: X) -> X { return x }
public struct AssertionResult : CustomStringConvertible, BooleanType {
init(isPass: Bool) {
self._isPass = isPass
}
public var boolValue: Bool {
return _isPass
}
public func withDescription(description: String) -> AssertionResult {
var result = self
result.description += description
return result
}
let _isPass: Bool
public var description: String = ""
}
public func assertionSuccess() -> AssertionResult {
return AssertionResult(isPass: true)
}
public func assertionFailure() -> AssertionResult {
return AssertionResult(isPass: false)
}
public func expectUnreachable(
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("this code should not be executed")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
public func expectUnreachableCatch(
error: _ErrorType,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("error should not be thrown: \"\(error)\"")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
%for BoolType in ['Bool', 'AssertionResult']:
public func expectTrue(
actual: ${BoolType},
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if !actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: true")
println("actual: \(actual)")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
public func expectFalse(
actual: ${BoolType},
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: false")
println("actual: \(actual)")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
%end
public func expectEmpty<T>(
value: Optional<T>,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if value != nil {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected optional to be empty")
println("actual: \"\(value)\"")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
public func expectNotEmpty<T>(
value: Optional<T>,
file: String = __FILE__, line: UWord = __LINE__
) -> T? {
if value == nil {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("expected optional to be non-empty")
println()
}
return value
}
public func expectCrashLater() {
println("\(_stdlibUnittestStreamPrefix);expectCrash;\(_anyExpectFailed)")
var stderr = _Stderr()
println("\(_stdlibUnittestStreamPrefix);expectCrash", &stderr)
_seenExpectCrash = true
}
func _defaultTestSuiteFailedCallback() {
abort()
}
var _testSuiteFailedCallback: () -> () = _defaultTestSuiteFailedCallback
public func _setTestSuiteFailedCallback(callback: () -> ()) {
_testSuiteFailedCallback = callback
}
extension ProcessTerminationStatus {
var isSwiftTrap: Bool {
switch self {
case .Exit(var status):
return false
case .Signal(var signal):
return CInt(signal) == SIGILL || CInt(signal) == SIGTRAP
}
}
}
func _stdlib_getline() -> String? {
var result = _UnitTestArray<UInt8>()
while true {
let c = getchar()
if c == EOF {
if result.isEmpty {
return nil
}
return String._fromWellFormedCodeUnitSequence(UTF8.self, input: result)
}
if c == CInt(UnicodeScalar("\n").value) {
return String._fromWellFormedCodeUnitSequence(UTF8.self, input: result)
}
result.append(UInt8(c))
}
}
func _printDebuggingAdvice(fullTestName: String) {
println("To debug, run:")
println("$ \(Process.arguments[0]) " +
"--stdlib-unittest-in-process --stdlib-unittest-filter \"\(fullTestName)\"")
}
var _allTestSuites: _UnitTestArray<TestSuite> = []
var _testSuiteNameToIndex: [String : Int] = [:]
let _stdlibUnittestStreamPrefix = "__STDLIB_UNITTEST__"
@asmname("swift_stdlib_installTrapInterceptor")
func _stdlib_installTrapInterceptor()
func _childProcess() {
_stdlib_installTrapInterceptor()
while let line = _stdlib_getline() {
let parts = line._split(";")
let testSuiteName = parts[0]
let testName = parts[1]
let testSuite = _allTestSuites[_testSuiteNameToIndex[testSuiteName]!]
_anyExpectFailed = false
testSuite._runTest(testName)
println("\(_stdlibUnittestStreamPrefix);end;\(_anyExpectFailed)")
var stderr = _Stderr()
println("\(_stdlibUnittestStreamPrefix);end", &stderr)
if !testSuite._testByName(testName).canReuseChildProcessAfterTest {
return
}
}
}
struct _ParentProcess {
internal var _pid: pid_t = -1
internal var _childStdin: _FDOutputStream = _FDOutputStream(fd: -1)
internal var _childStdout: _FDInputStream = _FDInputStream(fd: -1)
internal var _childStderr: _FDInputStream = _FDInputStream(fd: -1)
internal var _runTestsInProcess: Bool
internal var _filter: String?
init(runTestsInProcess: Bool, filter: String?) {
self._runTestsInProcess = runTestsInProcess
self._filter = filter
}
mutating func _spawnChild() {
let (pid, childStdinFD, childStdoutFD, childStderrFD) =
spawnChild([ "--stdlib-unittest-run-child" ])
_pid = pid
_childStdin = _FDOutputStream(fd: childStdinFD)
_childStdout = _FDInputStream(fd: childStdoutFD)
_childStderr = _FDInputStream(fd: childStderrFD)
}
mutating func _waitForChild() -> ProcessTerminationStatus {
let status = posixWaitpid(_pid)
_pid = -1
_childStdin.close()
_childStdout.close()
_childStderr.close()
_childStdin = _FDOutputStream(fd: -1)
_childStdout = _FDInputStream(fd: -1)
_childStderr = _FDInputStream(fd: -1)
return status
}
/// Returns the values of the corresponding variables in the child process.
mutating func _runTestInChild(testSuite: TestSuite, _ testName: String)
-> (anyExpectFailed: Bool, seenExpectCrash: Bool,
status: ProcessTerminationStatus?,
crashStdout: _UnitTestArray<String>, crashStderr: _UnitTestArray<String>) {
if _pid <= 0 {
_spawnChild()
}
println("\(testSuite.name);\(testName)", &_childStdin)
let currentTest = testSuite._testByName(testName)
if let stdinText = currentTest.stdinText {
print(stdinText, &_childStdin)
}
if currentTest.stdinEndsWithEOF {
_childStdin.close()
}
var readfds = _stdlib_fd_set()
var writefds = _stdlib_fd_set()
var errorfds = _stdlib_fd_set()
var stdoutSeenCrashDelimiter = false
var stderrSeenCrashDelimiter = false
var stdoutEnd = false
var stderrEnd = false
var capturedCrashStdout = _UnitTestArray<String>()
var capturedCrashStderr = _UnitTestArray<String>()
var anyExpectFailedInChild = false
while !((_childStdout.isEOF && _childStderr.isEOF) ||
(stdoutEnd && stderrEnd)) {
readfds.zero()
errorfds.zero()
if !_childStdout.isEOF {
readfds.set(_childStdout.fd)
errorfds.set(_childStdout.fd)
}
if !_childStderr.isEOF {
readfds.set(_childStderr.fd)
errorfds.set(_childStderr.fd)
}
var ret: CInt
repeat {
ret = _stdlib_select(&readfds, &writefds, &errorfds, nil)
} while ret == -1 && errno == EINTR
if ret <= 0 {
fatalError("select() returned an error")
}
if readfds.isset(_childStdout.fd) || errorfds.isset(_childStdout.fd) {
_childStdout.read()
while var line = _childStdout.getline() {
if let index = findSubstring(line, _stdlibUnittestStreamPrefix) {
let controlMessage = line[index..<line.endIndex]._split(";")
switch controlMessage[1] {
case "expectCrash":
stdoutSeenCrashDelimiter = true
anyExpectFailedInChild = controlMessage[2] == "true"
case "end":
stdoutEnd = true
anyExpectFailedInChild = controlMessage[2] == "true"
default:
fatalError("unexpected message")
}
line = line[line.startIndex..<index]
if line.isEmpty {
continue
}
}
if stdoutSeenCrashDelimiter {
capturedCrashStdout.append(line)
}
println("out>>> \(line)")
}
continue
}
if readfds.isset(_childStderr.fd) || errorfds.isset(_childStderr.fd) {
_childStderr.read()
while var line = _childStderr.getline() {
if let index = findSubstring(line, _stdlibUnittestStreamPrefix) {
let controlMessage = line[index..<line.endIndex]._split(";")
switch controlMessage[1] {
case "expectCrash":
stderrSeenCrashDelimiter = true
case "end":
stderrEnd = true
default:
fatalError("unexpected message")
}
line = line[line.startIndex..<index]
if line.isEmpty {
continue
}
}
if stderrSeenCrashDelimiter {
capturedCrashStderr.append(line)
}
println("err>>> \(line)")
}
continue
}
}
// Check if the child has sent us "end" markers for the current test.
if stdoutEnd && stderrEnd {
testSuite._testByName(testName)
var status: ProcessTerminationStatus? = nil
if !testSuite._testByName(testName).canReuseChildProcessAfterTest {
status = _waitForChild()
switch status! {
case .Exit(0):
status = nil
default:
()
}
}
return (
anyExpectFailedInChild,
stdoutSeenCrashDelimiter || stderrSeenCrashDelimiter, status,
capturedCrashStdout, capturedCrashStderr)
}
// We reached EOF on stdout and stderr and we did not see "end" markers, so
// it looks like child crashed (of course it could have closed the file
// descriptors, but we assume it did not, since it prevent further
// communication with the parent).
let status = _waitForChild()
return (
anyExpectFailedInChild,
stdoutSeenCrashDelimiter || stderrSeenCrashDelimiter, status,
capturedCrashStdout, capturedCrashStderr)
}
mutating func run() {
if let filter = _filter {
println("StdlibUnittest: using filter: \(filter)")
}
for testSuite in _allTestSuites {
var uxpassedTests = _UnitTestArray<String>()
var failedTests = _UnitTestArray<String>()
var skippedTests = _UnitTestArray<String>()
for t in testSuite._tests {
let fullTestName = "\(testSuite.name).\(t.name)"
if let filter = _filter where findSubstring(fullTestName, filter) == nil {
continue
}
let activeSkips = t.getActiveSkipPredicates()
if !activeSkips.isEmpty {
skippedTests += [ t.name ]
println("[ SKIP ] \(fullTestName) (skip: \(activeSkips))")
continue
}
let activeXFails = t.getActiveXFailPredicates()
let expectXFail = !activeXFails.isEmpty
let activeXFailsText = expectXFail ? " (XFAIL: \(activeXFails))" : ""
println("[ RUN ] \(fullTestName)\(activeXFailsText)")
var expectCrash = false
var childTerminationStatus: ProcessTerminationStatus? = nil
var crashStdout = _UnitTestArray<String>()
var crashStderr = _UnitTestArray<String>()
if _runTestsInProcess {
if t.stdinText != nil {
println("The test \(fullTestName) requires stdin input and can't be run in-process, marking as failed")
_anyExpectFailed = true
} else {
_anyExpectFailed = false
testSuite._runTest(t.name)
}
} else {
(_anyExpectFailed, expectCrash, childTerminationStatus, crashStdout,
crashStderr) =
_runTestInChild(testSuite, t.name)
}
// Determine if the test passed, not taking XFAILs into account.
var testPassed = false
var testFailureExplanation = ""
switch (_anyExpectFailed, childTerminationStatus, expectCrash) {
case (_, .None, false):
testPassed = !_anyExpectFailed
case (_, .None, true):
testPassed = false
testFailureExplanation = "expecting a crash, but the test did not crash"
case (_, .Some(let status), false):
testPassed = false
testFailureExplanation = "the test crashed unexpectedly"
case (_, .Some(let status), true):
testPassed = !_anyExpectFailed
}
if testPassed && t.crashOutputMatches.count() > 0 {
// If we still think that the test passed, check if the crash
// output matches our expectations.
let crashOutput = crashStdout + crashStderr
for expectedCrashOutput in t.crashOutputMatches {
var found = false
for s in crashOutput {
if findSubstring(s, expectedCrashOutput) != nil {
found = true
break
}
}
if !found {
println("did not find expected string after crash: \(expectedCrashOutput.debugDescription)")
testPassed = false
}
}
}
// Apply XFAILs.
switch (testPassed, expectXFail) {
case (true, false):
println("[ OK ] \(fullTestName)")
case (true, true):
uxpassedTests += [ t.name ]
println("[ UXPASS ] \(fullTestName)")
case (false, false):
failedTests += [ t.name ]
println("[ FAIL ] \(fullTestName)")
case (false, true):
println("[ XFAIL ] \(fullTestName)")
}
}
if !uxpassedTests.isEmpty || !failedTests.isEmpty {
println("\(testSuite.name): Some tests failed, aborting")
println("UXPASS: \(uxpassedTests)")
println("FAIL: \(failedTests)")
println("SKIP: \(skippedTests)")
if !uxpassedTests.isEmpty {
_printDebuggingAdvice(uxpassedTests[0])
}
if !failedTests.isEmpty {
_printDebuggingAdvice(failedTests[0])
}
_testSuiteFailedCallback()
} else {
println("\(testSuite.name): All tests passed")
}
}
}
}
public func runAllTests() {
struct PersistentState {
static var runAllTestsWasCalled: Bool = false
}
if PersistentState.runAllTestsWasCalled {
println("runAllTests() called twice. It is not allowed, aborting.")
_testSuiteFailedCallback()
return
}
PersistentState.runAllTestsWasCalled = true
#if _runtime(ObjC)
autoreleasepool {
_stdlib_initializeReturnAutoreleased()
}
#endif
let _isChildProcess: Bool =
Process.arguments.contains("--stdlib-unittest-run-child")
if _isChildProcess {
_childProcess()
} else {
var runTestsInProcess: Bool = false
var filter: String? = nil
for var i = 0; i < Process.arguments.count(); {
let arg = Process.arguments[i]
if arg == "--stdlib-unittest-in-process" {
runTestsInProcess = true
++i
continue
}
if arg == "--stdlib-unittest-filter" {
filter = Process.arguments[i + 1]
i += 2
continue
}
if arg == "--help" {
println(
"optional arguments:\n" +
"--stdlib-unittest-in-process\n" +
" run tests in-process without intercepting crashes.\n" +
" Useful for running under a debugger.\n" +
"--stdlib-unittest-filter FILTER-STRING\n" +
" only run tests whose names contain FILTER-STRING as\n" +
" a substring.")
return
}
// FIXME: skipping unrecognized parameters.
++i
}
var parent = _ParentProcess(
runTestsInProcess: runTestsInProcess, filter: filter)
parent.run()
}
}
public class TestSuite {
public init(_ name: String) {
self.name = name
_precondition(
_testNameToIndex[name] == nil,
"test suite with the same name already exists")
_allTestSuites.append(self)
_testSuiteNameToIndex[name] = _allTestSuites.count() - 1
}
public func test(name: String, _ testFunction: () -> ()) {
_TestBuilder(testSuite: self, name: name).code(testFunction)
}
public func test(name: String) -> _TestBuilder {
return _TestBuilder(testSuite: self, name: name)
}
public func setUp(code: () -> ()) {
_precondition(_testSetUpCode == nil, "set-up code already set")
_testSetUpCode = code
}
public func tearDown(code: () -> ()) {
_precondition(_testTearDownCode == nil, "tear-down code already set")
_testTearDownCode = code
}
func _runTest(testName: String) {
if let f = _testSetUpCode {
f()
}
_testByName(testName).code()
if let f = _testTearDownCode {
f()
}
}
func _testByName(testName: String) -> _Test {
return _tests[_testNameToIndex[testName]!]
}
struct _Test {
let name: String
let xfail: _UnitTestArray<TestRunPredicate>
let skip: _UnitTestArray<TestRunPredicate>
let stdinText: String?
let stdinEndsWithEOF: Bool
let crashOutputMatches: [String]
let code: () -> ()
/// Whether the test harness should stop reusing the child process after
/// running this test.
var canReuseChildProcessAfterTest: Bool {
return stdinText == nil
}
func getActiveXFailPredicates() -> _UnitTestArray<TestRunPredicate> {
return xfail.filter { $0.evaluate() }
}
func getActiveSkipPredicates() -> _UnitTestArray<TestRunPredicate> {
return skip.filter { $0.evaluate() }
}
}
public struct _TestBuilder {
let _testSuite: TestSuite
var _name: String
var _data: _Data = _Data()
class _Data {
var _xfail: _UnitTestArray<TestRunPredicate> = []
var _skip: _UnitTestArray<TestRunPredicate> = []
var _stdinText: String? = nil
var _stdinEndsWithEOF: Bool = false
var _crashOutputMatches: [String] = []
}
init(testSuite: TestSuite, name: String) {
_testSuite = testSuite
_name = name
}
public func xfail(predicate: TestRunPredicate) -> _TestBuilder {
_data._xfail.append(predicate)
return self
}
public func skip(predicate: TestRunPredicate) -> _TestBuilder {
_data._skip.append(predicate)
return self
}
public func stdin(stdinText: String, eof: Bool = false) -> _TestBuilder {
_data._stdinText = stdinText
_data._stdinEndsWithEOF = eof
return self
}
public func crashOutputMatches(string: String) -> _TestBuilder {
_data._crashOutputMatches.append(string)
return self
}
public func code(testFunction: () -> ()) {
_testSuite._tests.append(_Test(
name: _name, xfail: _data._xfail, skip: _data._skip,
stdinText: _data._stdinText,
stdinEndsWithEOF: _data._stdinEndsWithEOF,
crashOutputMatches: _data._crashOutputMatches, code: testFunction))
_testSuite._testNameToIndex[_name] = _testSuite._tests.count() - 1
}
}
var name: String
var _tests: _UnitTestArray<_Test> = []
/// Code that is run before every test.
var _testSetUpCode: (() -> ())?
/// Code that is run after every test.
var _testTearDownCode: (() -> ())?
/// Maps test name to index in `_tests`.
var _testNameToIndex: [String : Int] = [:]
}
#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
@asmname("swift_stdlib_getSystemVersionPlistProperty")
func _stdlib_getSystemVersionPlistPropertyImpl(
propertyName: UnsafePointer<CChar>) -> UnsafePointer<CChar>
func _stdlib_getSystemVersionPlistProperty(propertyName: String) -> String? {
return String.fromCString(
_stdlib_getSystemVersionPlistPropertyImpl(propertyName))
}
#endif
public enum OSVersion : CustomStringConvertible {
case OSX(major: Int, minor: Int, bugFix: Int)
case iOS(major: Int, minor: Int, bugFix: Int)
case iOSSimulator
case Linux
public var description: String {
switch self {
case OSX(var major, var minor, var bugFix):
return "OS X \(major).\(minor).\(bugFix)"
case iOS(var major, var minor, var bugFix):
return "iOS \(major).\(minor).\(bugFix)"
case iOSSimulator:
return "iOSSimulator"
case Linux:
return "Linux"
}
}
}
func _parseDottedVersion(s: String) -> _UnitTestArray<Int> {
return _UnitTestArray(lazy(s._split(".")).map { Int($0)! })
}
public func _parseDottedVersionTriple(s: String) -> (Int, Int, Int) {
var array = _parseDottedVersion(s)
if array.count() >= 4 {
fatalError("unexpected version")
}
return (
array.count() >= 1 ? array[0] : 0,
array.count() >= 2 ? array[1] : 0,
array.count() >= 3 ? array[2] : 0)
}
func _getOSVersion() -> OSVersion {
#if os(iOS) && (arch(i386) || arch(x86_64))
// On simulator, the plist file that we try to read turns out to be host's
// plist file, which indicates OS X.
//
// FIXME: how to get the simulator version *without* UIKit?
return .iOSSimulator
#elseif os(Linux)
return .Linux
#else
let productName = _stdlib_getSystemVersionPlistProperty("ProductName")!
let productVersion = _stdlib_getSystemVersionPlistProperty("ProductVersion")!
let (major, minor, bugFix) = _parseDottedVersionTriple(productVersion)
switch productName {
case "Mac OS X":
return .OSX(major: major, minor: minor, bugFix: bugFix)
case "iPhone OS":
return .iOS(major: major, minor: minor, bugFix: bugFix)
default:
fatalError("could not determine OS version")
}
#endif
}
var _runningOSVersion: OSVersion = _getOSVersion()
var _overrideOSVersion: OSVersion? = nil
/// Override the OS version for testing.
public func _setOverrideOSVersion(v: OSVersion) {
_overrideOSVersion = v
}
func _getRunningOSVersion() -> OSVersion {
// Allow overriding the OS version for testing.
return _overrideOSVersion ?? _runningOSVersion
}
public enum TestRunPredicate : CustomStringConvertible {
case Custom(() -> Bool, reason: String)
case OSXAny(/*reason:*/ String)
case OSXMajor(Int, reason: String)
case OSXMinor(Int, Int, reason: String)
case OSXMinorRange(Int, Range<Int>, reason: String)
case OSXBugFix(Int, Int, Int, reason: String)
case OSXBugFixRange(Int, Int, Range<Int>, reason: String)
case iOSAny(/*reason:*/ String)
case iOSMajor(Int, reason: String)
case iOSMinor(Int, Int, reason: String)
case iOSMinorRange(Int, Range<Int>, reason: String)
case iOSBugFix(Int, Int, Int, reason: String)
case iOSBugFixRange(Int, Int, Range<Int>, reason: String)
case iOSSimulatorAny(/*reason:*/ String)
case LinuxAny(reason: String)
public var description: String {
switch self {
case Custom(_, let reason):
return "Custom(reason: \(reason))"
case OSXAny(let reason):
return "OSX(*, reason: \(reason))"
case OSXMajor(let major, let reason):
return "OSX(\(major).*, reason: \(reason))"
case OSXMinor(let major, let minor, let reason):
return "OSX(\(major).\(minor), reason: \(reason))"
case OSXMinorRange(let major, let minorRange, let reason):
return "OSX(\(major).[\(minorRange)], reason: \(reason))"
case OSXBugFix(let major, let minor, let bugFix, let reason):
return "OSX(\(major).\(minor).\(bugFix), reason: \(reason))"
case OSXBugFixRange(let major, let minor, let bugFixRange, let reason):
return "OSX(\(major).\(minor).[\(bugFixRange)], reason: \(reason))"
case iOSAny(let reason):
return "iOS(*, reason: \(reason))"
case iOSMajor(let major, let reason):
return "iOS(\(major).*, reason: \(reason))"
case iOSMinor(let major, let minor, let reason):
return "iOS(\(major).\(minor), reason: \(reason))"
case iOSMinorRange(let major, let minorRange, let reason):
return "iOS(\(major).[\(minorRange)], reason: \(reason))"
case iOSBugFix(let major, let minor, let bugFix, let reason):
return "iOS(\(major).\(minor).\(bugFix), reason: \(reason))"
case iOSBugFixRange(let major, let minor, let bugFixRange, let reason):
return "iOS(\(major).\(minor).[\(bugFixRange)], reason: \(reason))"
case iOSSimulatorAny(let reason):
return "iOSSimulatorAny(*, reason: \(reason))"
case LinuxAny(reason: let reason):
return "LinuxAny(*, reason: \(reason))"
}
}
public func evaluate() -> Bool {
switch self {
case Custom(let predicate, _):
return predicate()
case OSXAny:
switch _getRunningOSVersion() {
case .OSX:
return true
default:
return false
}
case OSXMajor(let major, _):
switch _getRunningOSVersion() {
case .OSX(major, _, _):
return true
default:
return false
}
case OSXMinor(let major, let minor, _):
switch _getRunningOSVersion() {
case .OSX(major, minor, _):
return true
default:
return false
}
case OSXMinorRange(let major, let minorRange, _):
switch _getRunningOSVersion() {
case .OSX(major, let runningMinor, _):
return minorRange.contains(runningMinor)
default:
return false
}
case OSXBugFix(let major, let minor, let bugFix, _):
switch _getRunningOSVersion() {
case .OSX(major, minor, bugFix):
return true
default:
return false
}
case OSXBugFixRange(let major, let minor, let bugFixRange, _):
switch _getRunningOSVersion() {
case .OSX(major, minor, let runningBugFix):
return bugFixRange.contains(runningBugFix)
default:
return false
}
case iOSAny:
switch _getRunningOSVersion() {
case .iOS:
return true
default:
return false
}
case iOSMajor(let major, _):
switch _getRunningOSVersion() {
case .iOS(major, _, _):
return true
default:
return false
}
case iOSMinor(let major, let minor, _):
switch _getRunningOSVersion() {
case .iOS(major, minor, _):
return true
default:
return false
}
case iOSMinorRange(let major, let minorRange, _):
switch _getRunningOSVersion() {
case .iOS(major, let runningMinor, _):
return minorRange.contains(runningMinor)
default:
return false
}
case iOSBugFix(let major, let minor, let bugFix, _):
switch _getRunningOSVersion() {
case .iOS(major, minor, bugFix):
return true
default:
return false
}
case iOSBugFixRange(let major, let minor, let bugFixRange, _):
switch _getRunningOSVersion() {
case .iOS(major, minor, let runningBugFix):
return bugFixRange.contains(runningBugFix)
default:
return false
}
case iOSSimulatorAny:
switch _getRunningOSVersion() {
case .iOSSimulator:
return true
default:
return false
}
case LinuxAny:
switch _getRunningOSVersion() {
case .Linux:
return true
default:
return false
}
}
}
}
//
// Helpers that verify invariants of various stdlib types.
//
public func checkEquatable<T : Equatable>(
expectedEqual: Bool, _ lhs: T, _ rhs: T, _ stackTrace: SourceLocStack,
collectMoreInfo: (()->String)? = nil
) {
// Test operator '==' that is found through witness tables.
expectEqual(
expectedEqual, lhs == rhs, stackTrace: stackTrace,
collectMoreInfo: collectMoreInfo)
expectEqual(
!expectedEqual, lhs != rhs, stackTrace: stackTrace,
collectMoreInfo: collectMoreInfo)
}
public func checkEquatable<T : Equatable>(
expectedEqual: Bool, _ lhs: T, _ rhs: T,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
checkEquatable(
expectedEqual, lhs, rhs, SourceLocStack().with(SourceLoc(file, line)))
}
public func checkHashable<T : Hashable>(
expectedEqual: Bool, _ lhs: T, _ rhs: T, _ stackTrace: SourceLocStack,
collectMoreInfo: (()->String)? = nil
) {
// Test operator '==' that is found through witness tables.
expectEqual(
expectedEqual, lhs == rhs, stackTrace: stackTrace,
collectMoreInfo: collectMoreInfo)
expectEqual(
!expectedEqual, lhs != rhs, stackTrace: stackTrace,
collectMoreInfo: collectMoreInfo)
// Test 'hashValue'.
//
// If objects are not equal, then the hash value can be different or it can
// collide.
if expectedEqual {
expectEqual(lhs.hashValue, rhs.hashValue,
stackTrace: stackTrace, collectMoreInfo: collectMoreInfo)
}
}
public func checkHashable<T : Hashable>(
expectedEqual: Bool, _ lhs: T, _ rhs: T,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
checkHashable(
expectedEqual, lhs, rhs, SourceLocStack(SourceLoc(file, line)),
collectMoreInfo: collectMoreInfo)
}
public enum ExpectedComparisonResult {
case LT, EQ, GT
public func isLT() -> Bool {
return self == .LT
}
public func isEQ() -> Bool {
return self == .EQ
}
public func isGT() -> Bool {
return self == .GT
}
public func isLE() -> Bool {
return isLT() || isEQ()
}
public func isGE() -> Bool {
return isGT() || isEQ()
}
public func isNE() -> Bool {
return !isEQ()
}
public func flip() -> ExpectedComparisonResult {
switch self {
case .LT:
return .GT
case .EQ:
return .EQ
case .GT:
return .LT
}
}
}
extension ExpectedComparisonResult : CustomStringConvertible {
public var description: String {
switch self {
case .LT:
return "<"
case .EQ:
return "=="
case .GT:
return ">"
}
}
}
public func checkComparable<T : Comparable>(
expected: ExpectedComparisonResult,
_ lhs: T, _ rhs: T, _ stackTrace: SourceLocStack,
collectMoreInfo: (()->String)? = nil
) {
expectEqual(expected.isLT(), lhs < rhs,
stackTrace: stackTrace, collectMoreInfo: collectMoreInfo)
expectEqual(expected.isLE(), lhs <= rhs,
stackTrace: stackTrace, collectMoreInfo: collectMoreInfo)
expectEqual(expected.isGE(), lhs >= rhs,
stackTrace: stackTrace, collectMoreInfo: collectMoreInfo)
expectEqual(expected.isGT(), lhs > rhs,
stackTrace: stackTrace, collectMoreInfo: collectMoreInfo)
}
public func checkComparable<T : Comparable>(
expected: ExpectedComparisonResult,
_ lhs: T, _ rhs: T,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
checkComparable(expected, lhs, rhs, SourceLocStack(SourceLoc(file, line)),
collectMoreInfo: collectMoreInfo)
}
public struct CollectionMisuseResiliencyChecks {
public var callNextOnExhaustedGenerator: Bool = true
public static var all: CollectionMisuseResiliencyChecks {
return CollectionMisuseResiliencyChecks()
}
public static var none: CollectionMisuseResiliencyChecks {
return CollectionMisuseResiliencyChecks(
callNextOnExhaustedGenerator: false)
}
}
// Generate two overloads: one for _UnitTestArray (which will get
// picked up when the caller passes a literal), and another that
// accepts any appropriate Collection type.
% for genericParam, Element, Expected in zip(
% ('Expected: CollectionType', 'Element'),
% ('Expected.Generator.Element', 'Element'),
% ('Expected', '_UnitTestArray<Element>')):
public func checkGenerator<
G : GeneratorType, ${genericParam}
where ${Element} == G.Element
>(
expected: ${Expected},
_ generator: G,
_ sameValue: (${Element}, ${Element}) -> Bool,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
_ stackTrace: SourceLocStack,
collectMoreInfo: (()->String)? = nil
) {
// Copying a `GeneratorType` is allowed.
var mutableGen = generator
var actual: _UnitTestArray<${Element}> = []
while let e = mutableGen.next() {
actual.append(e)
}
expectEqualSequence(
expected, actual, sameValue,
stackTrace: stackTrace.withCurrentLoc(),
collectMoreInfo: collectMoreInfo)
if resiliencyChecks.callNextOnExhaustedGenerator {
// Having returned `.None` once, a `GeneratorType` should not generate more
// elements.
for i in 0..<10 {
expectEmpty(
mutableGen.next(),
stackTrace: stackTrace.withCurrentLoc(),
collectMoreInfo: collectMoreInfo)
}
}
}
public func checkGenerator<
G : GeneratorType, ${genericParam}
where ${Element} == G.Element, ${Element} : Equatable
>(
expected: ${Expected},
_ generator: G,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
_ stackTrace: SourceLocStack,
collectMoreInfo: (()->String)? = nil
) {
checkGenerator(
expected, generator, { $0 == $1 },
resiliencyChecks: resiliencyChecks,
stackTrace.withCurrentLoc(),
collectMoreInfo: collectMoreInfo)
}
public func checkSequence<
${genericParam}, S : SequenceType
where S.Generator.Element == ${Element}
>(
expected: ${Expected},
_ sequence: S,
_ sameValue: (${Element}, ${Element}) -> Bool,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
_ stackTrace: SourceLocStack,
collectMoreInfo: (()->String)? = nil
) {
let expectedCount: Int = numericCast(expected.count())
checkGenerator(
expected, sequence.generate(), sameValue,
resiliencyChecks: resiliencyChecks,
stackTrace.withCurrentLoc())
expectGE(
expectedCount, sequence.underestimateCount(),
stackTrace: stackTrace.withCurrentLoc(),
collectMoreInfo: collectMoreInfo)
}
public func checkSequence<
${genericParam}, S : SequenceType
where S.Generator.Element == ${Element}
>(
expected: ${Expected},
_ sequence: S,
_ sameValue: (${Element}, ${Element}) -> Bool,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
checkSequence(
expected, sequence, sameValue,
resiliencyChecks: resiliencyChecks,
SourceLocStack().with(SourceLoc(file, line)),
collectMoreInfo: collectMoreInfo)
}
public func checkSequence<
${genericParam}, S : SequenceType
where S.Generator.Element == ${Element}, ${Element} : Equatable
>(
expected: ${Expected},
_ sequence: S,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
_ stackTrace: SourceLocStack,
collectMoreInfo: (()->String)? = nil
) {
checkSequence(
expected, sequence, { $0 == $1 },
resiliencyChecks: resiliencyChecks,
stackTrace.withCurrentLoc(),
collectMoreInfo: collectMoreInfo)
}
public func checkSequence<
${genericParam}, S : SequenceType
where S.Generator.Element == ${Element}, ${Element} : Equatable
>(
expected: ${Expected},
_ sequence: S,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
checkSequence(
expected, sequence, { $0 == $1 },
resiliencyChecks: resiliencyChecks,
SourceLocStack().with(SourceLoc(file, line)),
collectMoreInfo: collectMoreInfo)
}
%for traversal in [ 'Forward', 'Bidirectional', 'RandomAccess' ]:
public func check${traversal}Collection<
${genericParam}, C : CollectionType
where
C.Generator.Element == ${Element},
C.Index : ${traversal}IndexType
>(
expected: ${Expected},
_ collection: C,
_ sameValue: (${Element}, ${Element}) -> Bool,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
_ stackTrace: SourceLocStack,
collectMoreInfo: (()->String)? = nil
) {
// A `CollectionType` is a multi-pass `SequenceType`.
for i in 0..<3 {
checkSequence(
expected, collection, sameValue,
resiliencyChecks: resiliencyChecks,
stackTrace.withCurrentLoc(),
collectMoreInfo: collectMoreInfo)
}
let expectedArray = Array(expected)
expectEqual(
expectedArray.count().toIntMax(),
collection.count().toIntMax(),
stackTrace: stackTrace.withCurrentLoc(),
collectMoreInfo: collectMoreInfo)
for i in 0..<3 {
if true {
let startIndex = collection.startIndex
let endIndex = collection.endIndex
for i in collection.indices {
expectEqual(startIndex, collection.startIndex,
stackTrace: stackTrace.withCurrentLoc()) {
"Iteration should not change startIndex"
}
expectEqual(endIndex, collection.endIndex,
stackTrace: stackTrace.withCurrentLoc()) {
"Iteration should not change endIndex"
}
}
}
var allIndices: [C.Index] = []
for i in collection.indices {
allIndices.append(i)
}
if expectedArray.count() >= 2 {
for i in 0..<allIndices.count()-1 {
var successor1 = allIndices[i].successor()
var successor2 = allIndices[i]
successor2++
var successor3 = allIndices[i]
++successor3
for s in [ successor1, successor2, successor3 ] {
expectEqual(
allIndices[i + 1], s,
stackTrace: stackTrace.withCurrentLoc())
expectEqual(
expectedArray[i + 1],
collection[s],
sameValue,
stackTrace: stackTrace.withCurrentLoc())
}
}
% if traversal == "Bidirectional":
for i in 1..<allIndices.count() {
var predecessor1 = allIndices[i].predecessor()
var predecessor2 = allIndices[i]
predecessor2--
var predecessor3 = allIndices[i]
--predecessor3
for p in [ predecessor1, predecessor2, predecessor3 ] {
expectEqual(
allIndices[i - 1], p,
stackTrace: stackTrace.withCurrentLoc())
expectEqual(
expectedArray[i - 1], collection[p],
sameValue,
stackTrace: stackTrace.withCurrentLoc())
}
}
for i in 1..<allIndices.count() {
var index = allIndices[i]
--index
++index
expectEqual(
allIndices[i], index,
stackTrace: stackTrace.withCurrentLoc())
expectEqual(
expectedArray[i], collection[index],
sameValue,
stackTrace: stackTrace.withCurrentLoc())
}
% end
}
if true {
var allIndices2: [C.Index] = []
for i in collection.indices {
allIndices2.append(i)
}
expectEqualSequence(
allIndices, allIndices2,
stackTrace: stackTrace.withCurrentLoc()) {
"iteration should not invalidate indices"
}
expectEqualSequence(
expectedArray,
allIndices._prext_map { collection[$0] },
sameValue,
stackTrace: stackTrace.withCurrentLoc())
expectEqualSequence(
expectedArray,
allIndices2._prext_map { collection[$0] },
sameValue,
stackTrace: stackTrace.withCurrentLoc())
}
}
// FIXME: more checks for bidirectional and random access collections.
}
public func check${traversal}Collection<
${genericParam}, C : CollectionType
where
C.Generator.Element == ${Element},
C.Index : ${traversal}IndexType
>(
expected: ${Expected},
_ collection: C,
_ sameValue: (${Element}, ${Element}) -> Bool,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
check${traversal}Collection(
expected, collection, sameValue,
resiliencyChecks: resiliencyChecks,
SourceLocStack().with(SourceLoc(file, line)),
collectMoreInfo: collectMoreInfo)
}
public func check${traversal}Collection<
${genericParam}, C : CollectionType
where
C.Generator.Element == ${Element},
C.Index : ${traversal}IndexType,
${Element} : Equatable
>(
expected: ${Expected},
_ collection: C,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
_ stackTrace: SourceLocStack,
collectMoreInfo: (()->String)? = nil
) {
check${traversal}Collection(
expected, collection, { $0 == $1 },
resiliencyChecks: resiliencyChecks,
stackTrace.withCurrentLoc(),
collectMoreInfo: collectMoreInfo)
}
public func check${traversal}Collection<
${genericParam}, C : CollectionType
where
C.Generator.Element == ${Element},
C.Index : ${traversal}IndexType,
${Element} : Equatable
>(
expected: ${Expected},
_ collection: C,
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
check${traversal}Collection(
expected, collection, { $0 == $1 },
resiliencyChecks: resiliencyChecks,
SourceLocStack().with(SourceLoc(file, line)),
collectMoreInfo: collectMoreInfo)
}
% end
public func checkSliceableWithBidirectionalIndex<
${genericParam}, S : Sliceable
where
S.Generator.Element == ${Element},
S.SubSlice.Generator.Element == ${Element},
S.Index : BidirectionalIndexType,
S.SubSlice.Index : BidirectionalIndexType,
${Element} : Equatable
>(
expected: ${Expected},
_ sliceable: S, _ stackTrace: SourceLocStack
) {
// A `Sliceable` is a `CollectionType`.
checkBidirectionalCollection(expected, sliceable, stackTrace.withCurrentLoc())
let expectedArray = _UnitTestArray(expected)
var start = sliceable.startIndex
for startNumericIndex in 0...expectedArray.count() {
if start != sliceable.endIndex {
++start
--start
++start
--start
}
var end = start
for endNumericIndex in startNumericIndex...expectedArray.count() {
if end != sliceable.endIndex {
++end
--end
++end
--end
}
let expectedSlice = expectedArray[startNumericIndex..<endNumericIndex]
let slice = sliceable[start..<end]
checkBidirectionalCollection(
expectedSlice, slice, stackTrace.withCurrentLoc())
if end != sliceable.endIndex {
++end
}
}
if start != sliceable.endIndex {
++start
}
}
}
% end
public func nthIndex<C: CollectionType>(x: C, _ n: Int) -> C.Index {
return advance(x.startIndex, numericCast(n))
}
public func nth<C: CollectionType>(x: C, _ n: Int) -> C.Generator.Element {
return x[nthIndex(x, n)]
}
public func checkRangeReplaceable<
C: RangeReplaceableCollectionType,
N: CollectionType
where
C.Generator.Element : Equatable, C.Generator.Element == N.Generator.Element
>(
makeCollection: ()->C,
_ makeNewValues: (Int)->N
) {
typealias A = C
// First make an independent copy of the array that we can use for
// comparison later.
let source = _UnitTestArray<A.Generator.Element>(makeCollection())
for (ix, i) in source.indices.enumerate() {
for (jx_, j) in (i..<source.endIndex).enumerate() {
let jx = jx_ + ix
let oldCount = jx - ix
for newCount in 0..<(2 * oldCount) {
let newValues = makeNewValues(newCount)
func reportFailure(inout a: A, _ message: String) {
println("\(message) when replacing indices \(ix)...\(jx)")
println(" in \(_UnitTestArray(source)) with \(_UnitTestArray(newValues))")
println(" yielding \(_UnitTestArray(a))")
println("====================================")
expectTrue(false)
}
var a = makeCollection()
a.replaceRange(nthIndex(a, ix)..<nthIndex(a, jx), with: newValues)
let growth = newCount - oldCount
let expectedCount = source.count() + growth
let actualCount = numericCast(a.count()) as Int
if actualCount != expectedCount {
reportFailure(
&a, "\(actualCount) != expected count \(expectedCount)")
}
for (kx, k) in a.indices.enumerate() {
let expectedValue = kx < ix ? nth(source, kx)
: kx < jx + growth ? nth(newValues, kx - ix)
: nth(source, kx - growth)
if a[k] != expectedValue {
reportFailure(
&a,
// FIXME: why do we need to break this string into two parts?
"a[\(kx)] = "
+ "\(a[k]) != expected value \(expectedValue)")
}
}
}
}
}
}
public func expectEqualSequence<
Expected: SequenceType,
Actual: SequenceType
where Expected.Generator.Element == Actual.Generator.Element,
Expected.Generator.Element : Equatable
>(
expected: Expected, _ actual: Actual,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
expectEqualSequence(
expected, actual, { $0 == $1 }, stackTrace: stackTrace,
file: file, line: line, collectMoreInfo: collectMoreInfo)
}
public func expectEqualSequence<
Expected : SequenceType,
Actual : SequenceType,
T : Equatable,
U : Equatable
where Expected.Generator.Element == Actual.Generator.Element,
Expected.Generator.Element == (T, U)
>(
expected: Expected, _ actual: Actual,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
expectEqualSequence(
expected, actual, { $0.0 == $1.0 && $0.1 == $1.1 },
stackTrace: stackTrace, file: file, line: line,
collectMoreInfo: collectMoreInfo)
}
public func expectEqualSequence<
Expected: SequenceType,
Actual: SequenceType
where Expected.Generator.Element == Actual.Generator.Element
>(
expected: Expected, _ actual: Actual,
_ sameValue: (Expected.Generator.Element, Expected.Generator.Element)->Bool,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
if !expected.elementsEqual(actual, isEquivalent: sameValue) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected elements: \"\(expected)\"")
println("actual: \"\(actual)\" (of type \(_stdlib_getDemangledTypeName(actual)))")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
public func expectEqualsUnordered<
Expected : SequenceType,
Actual : SequenceType
where Expected.Generator.Element == Actual.Generator.Element
>(
expected: Expected, _ actual: Actual,
_ compare: (Expected.Generator.Element, Expected.Generator.Element)
-> ExpectedComparisonResult,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
let x: [Expected.Generator.Element] = sorted(
Array(expected), compose(compare, { $0.isLT() }))
let y: [Actual.Generator.Element] = sorted(
Array(actual), compose(compare, { $0.isLT() }))
expectEqualSequence(
x, y, compose(compare, { $0.isEQ() }), stackTrace: stackTrace,
file: file, line: line, collectMoreInfo: collectMoreInfo)
}
public func expectEqualsUnordered<
Expected : SequenceType,
Actual : SequenceType
where
Expected.Generator.Element == Actual.Generator.Element,
Expected.Generator.Element : Comparable
>(
expected: Expected, _ actual: Actual,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
func compare(
lhs: Expected.Generator.Element,
rhs: Expected.Generator.Element
) -> ExpectedComparisonResult {
if lhs < rhs {
return .LT
}
if lhs == rhs {
return .EQ
}
return .GT
}
expectEqualsUnordered(
expected, actual, compare,
stackTrace: stackTrace.map { $0.withCurrentLoc() },
file: file, line: line, collectMoreInfo: collectMoreInfo)
}
public func expectEqualsUnordered<T : Comparable>(
expected: [T], _ actual: [T],
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
let x = sorted(expected)
let y = sorted(actual)
expectEqualSequence(
x, y, { $0 == $1 }, stackTrace: stackTrace,
file: file, line: line, collectMoreInfo: collectMoreInfo)
}
/// A nominal type that is equivalent to a tuple of two elements.
///
/// We need a nominal type because we can't add protocol conformances to
/// tuples.
struct Pair<T : Comparable> : Comparable {
init(_ first: T, _ second: T) {
self.first = first
self.second = second
}
var first: T
var second: T
}
func == <T>(lhs: Pair<T>, rhs: Pair<T>) -> Bool {
return lhs.first == rhs.first && lhs.second == rhs.second
}
func < <T>(lhs: Pair<T>, rhs: Pair<T>) -> Bool {
return [ lhs.first, lhs.second ].lexicographicalCompare(
[ rhs.first, rhs.second ])
}
public func expectEqualsUnordered<T : Comparable>(
expected: [(T, T)], _ actual: [(T, T)],
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
let x = sorted(expected, { Pair($0.0, $0.1) < Pair($1.0, $1.1) })
let y = sorted(actual, { Pair($0.0, $0.1) < Pair($1.0, $1.1) })
expectEqualSequence(
x, y, { Pair($0.0, $0.1) == Pair($1.0, $1.1) }, stackTrace: stackTrace,
file: file, line: line, collectMoreInfo: collectMoreInfo)
}
/*
This code crashes the compiler. If we could use this code, we wouldn't need
the explicit overload for [(T, T)].
rdar://problem/19792730
rdar://problem/19792768
public func expectEqualsUnordered<
Expected : SequenceType,
Actual : SequenceType,
T : Comparable
where
Expected.Generator.Element == Actual.Generator.Element,
Expected.Generator.Element == (T, T)
>(
expected: Expected, _ actual: Actual,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
func comparePairLess(lhs: (T, T), rhs: (T, T)) -> Bool {
return lexicographicalCompare([ lhs.0, lhs.1 ], [ rhs.0, rhs.1 ])
}
let x: [(T, T)] = sorted(Array(expected), comparePairLess)
let y: [(T, T)] = sorted(Array(actual), comparePairLess)
func comparePairEquals(lhs: (T, T), rhs: (T, T)) -> Bool {
return lhs.0 == rhs.0 && lhs.1 == rhs.1
}
expectEqualSequence(
x, y, comparePairEquals, stackTrace: stackTrace,
file: file, line: line, collectMoreInfo: collectMoreInfo)
}*/
public func expectEqualFunctionsForDomain<ArgumentType, Result : Equatable>(
arguments: [ArgumentType], _ function1: ArgumentType -> Result,
_ function2: ArgumentType -> Result
) {
for a in arguments {
let expected = function1(a)
let actual = function2(a)
expectEqual(expected, actual) {
"where the argument is: \(a)"
}
}
}
public func expectEqualMethodsForDomain<
SelfType, ArgumentType, Result : Equatable
>(
selfs: [SelfType], _ arguments: [ArgumentType],
_ function1: SelfType -> ArgumentType -> Result,
_ function2: SelfType -> ArgumentType -> Result
) {
for s in selfs {
for a in arguments {
let expected = function1(s)(a)
let actual = function2(s)(a)
expectEqual(expected, actual) {
"where the first argument is: \(s)\nand the second argument is: \(a)"
}
}
}
}
public func expectEqualUnicodeScalars(
expected: _UnitTestArray<UInt32>, _ actual: String,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__,
collectMoreInfo: (()->String)? = nil
) {
let actualUnicodeScalars = _UnitTestArray(lazy(actual.unicodeScalars).map { $0.value })
if !expected.elementsEqual(actualUnicodeScalars) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected elements: \"\(asHex(expected))\"")
println("actual: \"\(asHex(actualUnicodeScalars))\"")
if collectMoreInfo != nil { println(collectMoreInfo!()) }
println()
}
}
public func expectPrinted<T>(
expectedOneOf patterns: _UnitTestArray<String>, _ object: T,
file: StaticString = __FILE__, line: UWord = __LINE__
) {
let actual = String(object)
if !patterns.contains(actual) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("expected: any of \(patterns.debugDescription)")
println("actual: \"\(actual)\"")
println()
}
}
public func expectPrinted<T>(
expected: String, _ object: T,
file: StaticString = __FILE__, line: UWord = __LINE__
) {
expectPrinted(expectedOneOf: [expected], object, file: file, line: line)
}
public func expectDebugPrinted<T>(
expectedOneOf patterns: _UnitTestArray<String>, _ object: T,
file: StaticString = __FILE__, line: UWord = __LINE__
) {
let actual = String(reflecting: object)
if !patterns.contains(actual) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("expected: any of \(patterns.debugDescription)")
println("actual: \"\(actual)\"")
println()
}
}
public func expectDebugPrinted<T>(
expected: String, _ object: T,
file: StaticString = __FILE__, line: UWord = __LINE__
) {
expectDebugPrinted(expectedOneOf: [expected], object, file: file, line: line)
}
func compose<A, B, C>(f: A -> B, _ g: B -> C) -> A -> C {
return { a in
return g(f(a))
}
}
/// State that is created every time a fresh generator is created with
/// `MinimalSequence.generate()`.
internal class _MinimalGeneratorPrivateState<T> {
internal init() {}
internal var returnedNilCounter: Int = 0
}
/// State shared by all generators of a MinimalSequence.
internal class _MinimalGeneratorSharedState<T> {
internal init(_ data: [T]) {
self.data = data
}
internal let data: [T]
internal var i: Int = 0
internal var underestimatedCount: Int = 0
}
//===----------------------------------------------------------------------===//
// MinimalGenerator
//===----------------------------------------------------------------------===//
/// A GeneratorType that implements the protocol contract in the most
/// narrow way possible.
///
/// This generator will return `nil` only once.
public struct MinimalGenerator<T> : GeneratorType {
public init<S : SequenceType where S.Generator.Element == T>(_ s: S) {
self._sharedState = _MinimalGeneratorSharedState(Array(s))
}
public init(_ data: [T]) {
self._sharedState = _MinimalGeneratorSharedState(data)
}
internal init(_ _sharedState: _MinimalGeneratorSharedState<T>) {
self._sharedState = _sharedState
}
public func next() -> T? {
if _sharedState.i == _sharedState.data.count() {
if isConsumed {
expectUnreachable() { "next() was called on a consumed generator" }
}
++_privateState.returnedNilCounter
return nil
}
return _sharedState.data[_sharedState.i++]
}
public var isConsumed: Bool {
return returnedNilCounter >= 1
}
public var returnedNilCounter: Int {
return _privateState.returnedNilCounter
}
internal let _privateState: _MinimalGeneratorPrivateState<T> =
_MinimalGeneratorPrivateState()
internal let _sharedState: _MinimalGeneratorSharedState<T>
}
//===----------------------------------------------------------------------===//
// MinimalSequence
//===----------------------------------------------------------------------===//
public enum UnderestimateCountBehavior {
/// Return the actual number of elements.
case Precise
/// Return the actual number of elements divided by 2.
case Half
/// Return an overestimated count. Useful to test how algorithms reserve
/// memory.
case Overestimate
/// Return the provided value.
case Value(Int)
}
/// A SequenceType that implements the protocol contract in the most
/// narrow way possible.
///
/// This sequence is consumed when its generator is advanced.
public struct MinimalSequence<T> : SequenceType {
public init<S : SequenceType where S.Generator.Element == T>(
_ s: S,
underestimatedCount: UnderestimateCountBehavior = .Value(0)
) {
let data = Array(s)
self._sharedState = _MinimalGeneratorSharedState(data)
switch underestimatedCount {
case .Precise:
self._sharedState.underestimatedCount = data.count()
case .Half:
self._sharedState.underestimatedCount = data.count() / 2
case .Overestimate:
self._sharedState.underestimatedCount = data.count() * 3 + 5
case .Value(let count):
self._sharedState.underestimatedCount = count
}
}
public func generate() -> MinimalGenerator<T> {
return MinimalGenerator(_sharedState)
}
public func underestimateCount() -> Int {
return max(0, self._sharedState.underestimatedCount - self._sharedState.i)
}
internal let _sharedState: _MinimalGeneratorSharedState<T>
}
//===----------------------------------------------------------------------===//
// MinimalForwardIndex
//===----------------------------------------------------------------------===//
% for Distance in [ '', 'Int32' ]:
public struct MinimalForward${Distance}Index : ForwardIndexType {
% if Distance != '':
typealias Distance = ${Distance}
% end
public init(position: Int, endIndex: Int) {
self.position = position
self.endIndex = endIndex
}
public init(position: Int, startIndex _: Int, endIndex: Int) {
self.position = position
self.endIndex = endIndex
}
public func successor() -> MinimalForward${Distance}Index {
expectNotEqual(endIndex, position)
return MinimalForward${Distance}Index(
position: position + 1,
endIndex: endIndex)
}
public let position: Int
public let endIndex: Int
}
public func == (
lhs: MinimalForward${Distance}Index,
rhs: MinimalForward${Distance}Index
) -> Bool {
return lhs.position == rhs.position
}
% end
//===----------------------------------------------------------------------===//
// MinimalBidirectionalIndex
//===----------------------------------------------------------------------===//
public struct MinimalBidirectionalIndex : BidirectionalIndexType {
public init(position: Int, startIndex: Int, endIndex: Int) {
self.position = position
self.startIndex = startIndex
self.endIndex = endIndex
}
public func successor() -> MinimalBidirectionalIndex {
expectNotEqual(endIndex, position)
return MinimalBidirectionalIndex(
position: position + 1, startIndex: startIndex, endIndex: endIndex)
}
public func predecessor() -> MinimalBidirectionalIndex {
expectNotEqual(startIndex, position)
return MinimalBidirectionalIndex(
position: position - 1, startIndex: startIndex, endIndex: endIndex)
}
public let position: Int
public let startIndex: Int
public let endIndex: Int
}
public func == (
lhs: MinimalBidirectionalIndex,
rhs: MinimalBidirectionalIndex
) -> Bool {
return lhs.position == rhs.position
}
//===----------------------------------------------------------------------===//
// MinimalRandomAccessIndex
//===----------------------------------------------------------------------===//
public struct MinimalRandomAccessIndex : RandomAccessIndexType {
public init(position: Int, startIndex: Int, endIndex: Int) {
self.position = position
self.startIndex = startIndex
self.endIndex = endIndex
}
public func successor() -> MinimalRandomAccessIndex {
expectNotEqual(endIndex, position)
return MinimalRandomAccessIndex(
position: position + 1, startIndex: startIndex, endIndex: endIndex)
}
public func predecessor() -> MinimalRandomAccessIndex {
expectNotEqual(startIndex, position)
return MinimalRandomAccessIndex(
position: position - 1, startIndex: startIndex, endIndex: endIndex)
}
public func distanceTo(other: MinimalRandomAccessIndex) -> Int {
return other.position - position
}
public func advancedBy(n: Int) -> MinimalRandomAccessIndex {
expectNotEqual(endIndex, position)
let newPosition = position + n
expectLE(startIndex, newPosition)
expectGE(endIndex, newPosition)
return MinimalRandomAccessIndex(
position: newPosition, startIndex: startIndex, endIndex: endIndex)
}
public let position: Int
public let startIndex: Int
public let endIndex: Int
}
public func == (
lhs: MinimalRandomAccessIndex,
rhs: MinimalRandomAccessIndex
) -> Bool {
return lhs.position == rhs.position
}
//===----------------------------------------------------------------------===//
// Minimal***Collection
//===----------------------------------------------------------------------===//
% for traversal in [ 'Forward', 'Bidirectional', 'RandomAccess' ]:
% for mutable in [ False, True ]:
// This comment is a workaround for <rdar://problem/18900352> gyb miscompiles nested loops
% Self = 'Minimal%s%sCollection' % ('Mutable' if mutable else '', traversal)
% Index = 'Minimal%sIndex' % traversal
/// A minimal implementation of `CollectionType` with extra checks.
public struct ${Self}<T> : ${'MutableCollectionType' if mutable else 'CollectionType'} {
public init<S : SequenceType where S.Generator.Element == T>(
_ s: S,
underestimatedCount: UnderestimateCountBehavior = .Value(0)
) {
self._elements = Array(s)
switch underestimatedCount {
case .Precise:
self.underestimatedCount = _elements.count()
case .Half:
self.underestimatedCount = _elements.count() / 2
case .Overestimate:
self.underestimatedCount = _elements.count() * 3 + 5
case .Value(let count):
self.underestimatedCount = count
}
}
public func generate() -> MinimalGenerator<T> {
return MinimalGenerator(_elements)
}
public var startIndex: ${Index} {
return ${Index}(
position: 0,
startIndex: 0,
endIndex: _elements.endIndex)
}
public var endIndex: ${Index} {
return ${Index}(
position: _elements.endIndex,
startIndex: 0,
endIndex: _elements.endIndex)
}
public subscript(i: ${Index}) -> T {
get {
return _elements[i.position]
}
% if mutable:
set {
_elements[i.position] = newValue
}
% end
}
public func underestimateCount() -> Int {
return underestimatedCount
}
public var underestimatedCount: Int
internal var _elements: [T]
}
% end
% end
//===----------------------------------------------------------------------===//
// Minimal***RangeReplaceableCollectionType
//===----------------------------------------------------------------------===//
%for traversal in [ 'Forward', 'Bidirectional', 'RandomAccess' ]:
% Self = 'Minimal%sRangeReplaceableCollectionType' % traversal
% Index = 'Minimal%sIndex' % traversal
/// A minimal implementation of `RangeReplaceableCollectionType` with extra
/// checks.
public struct ${Self}<T> : RangeReplaceableCollectionType {
public init<S : SequenceType where S.Generator.Element == T>(
_ s: S,
underestimatedCount: UnderestimateCountBehavior = .Value(0)
) {
self.elements = Array(s)
switch underestimatedCount {
case .Precise:
self.underestimatedCount = elements.count()
case .Half:
self.underestimatedCount = elements.count() / 2
case .Overestimate:
self.underestimatedCount = elements.count() * 3 + 5
case .Value(let count):
self.underestimatedCount = count
}
}
public init() {
self.underestimatedCount = 0
self.elements = []
}
public func generate() -> MinimalGenerator<T> {
return MinimalGenerator(elements)
}
public func underestimateCount() -> Int {
return underestimatedCount
}
public var startIndex: ${Index} {
return ${Index}(
position: 0,
startIndex: 0,
endIndex: elements.endIndex)
}
public var endIndex: ${Index} {
return ${Index}(
position: elements.endIndex,
startIndex: 0,
endIndex: elements.endIndex)
}
public subscript(i: ${Index}) -> T {
return elements[i.position]
}
public mutating func reserveCapacity(n: Int) {
elements.reserveCapacity(n)
reservedCapacity = max(reservedCapacity, n)
}
public mutating func append(x: T) {
elements.append(x)
}
public mutating func extend<
S : SequenceType where S.Generator.Element == T
>(newElements: S) {
elements.extend(newElements)
}
public mutating func replaceRange<
C : CollectionType where C.Generator.Element == T
>(
subRange: Range<${Index}>, with newElements: C
) {
elements.replaceRange(
subRange.startIndex.position..<subRange.endIndex.position,
with: newElements)
}
public mutating func insert(newElement: T, atIndex i: ${Index}) {
elements.insert(newElement, atIndex: i.position)
}
public mutating func splice<
S : CollectionType where S.Generator.Element == T
>(newElements: S, atIndex i: ${Index}) {
elements.splice(newElements, atIndex: i.position)
}
public mutating func removeAtIndex(i: ${Index}) -> T {
return elements.removeAtIndex(i.position)
}
public mutating func removeRange(subRange: Range<${Index}>) {
elements.removeRange(
subRange.startIndex.position..<subRange.endIndex.position
)
}
public mutating func removeAll(keepCapacity keepCapacity: Bool = false) {
// Ignore the value of `keepCapacity`.
elements.removeAll(keepCapacity: false)
}
public var underestimatedCount: Int
public var reservedCapacity: Int = 0
public var elements: [T]
}
%end
/// A type that does not conform to any protocols.
///
/// This type can be used to check that generic functions don't rely on any
/// conformances.
public struct OpaqueValue<Underlying> {
public var value: Underlying
public var identity: Int
public init(_ value: Underlying) {
self.value = value
self.identity = 0
}
public init(_ value: Underlying, identity: Int) {
self.value = value
self.identity = identity
}
}
/// A type that conforms only to `Equatable`.
///
/// This type can be used to check that generic functions don't rely on any
/// other conformances.
public struct MinimalEquatableValue : Equatable {
public static var timesEqualEqualWasCalled: Int = 0
public var value: Int
public var identity: Int
public init(_ value: Int) {
self.value = value
self.identity = 0
}
public init(_ value: Int, identity: Int) {
self.value = value
self.identity = identity
}
}
public func == (
lhs: MinimalEquatableValue,
rhs: MinimalEquatableValue
) -> Bool {
++MinimalEquatableValue.timesEqualEqualWasCalled
return lhs.value == rhs.value
}
% for kind in [ 'Value', 'Class' ]:
% Self = 'MinimalHashable%s' % kind
/// A type that conforms only to `Equatable` and `Hashable`.
///
/// This type can be used to check that generic functions don't rely on any
/// other conformances.
public struct ${Self} : Equatable, Hashable {
public static var timesEqualEqualWasCalled: Int = 0
public static var timesHashValueWasCalled: Int = 0
public var value: Int
public var identity: Int
public init(_ value: Int) {
self.value = value
self.identity = 0
}
public init(_ value: Int, identity: Int) {
self.value = value
self.identity = identity
}
public var hashValue: Int {
++${Self}.timesHashValueWasCalled
return value.hashValue
}
}
public func == (
lhs: ${Self},
rhs: ${Self}
) -> Bool {
++${Self}.timesEqualEqualWasCalled
return lhs.value == rhs.value
}
% end
/// A type that conforms only to `Equatable` and `Comparable`.
///
/// This type can be used to check that generic functions don't rely on any
/// other conformances.
public struct MinimalComparableValue : Equatable, Comparable {
public static var timesEqualEqualWasCalled: Int = 0
public static var timesLessWasCalled: Int = 0
public var value: Int
public var identity: Int
public init(_ value: Int) {
self.value = value
self.identity = 0
}
public init(_ value: Int, identity: Int) {
self.value = value
self.identity = identity
}
}
public func == (
lhs: MinimalComparableValue,
rhs: MinimalComparableValue
) -> Bool {
++MinimalComparableValue.timesEqualEqualWasCalled
return lhs.value == rhs.value
}
public func < (
lhs: MinimalComparableValue,
rhs: MinimalComparableValue
) -> Bool {
++MinimalComparableValue.timesLessWasCalled
return lhs.value < rhs.value
}
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End: