Files
swift-mirror/stdlib/unittest/StdlibUnittest.swift.gyb
Dave Abrahams 6d1095f44e Protocol names end in "Type," "ible," or "able"
Mechanically add "Type" to the end of any protocol names that don't end
in "Type," "ible," or "able."  Also, drop "Type" from the end of any
associated type names, except for those of the *LiteralConvertible
protocols.

There are obvious improvements to make in some of these names, which can
be handled with separate commits.

Fixes <rdar://problem/17165920> Protocols `Integer` etc should get
uglier names.

Swift SVN r19883
2014-07-12 17:29:57 +00:00

474 lines
12 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 Darwin
public struct SourceLoc {
let file: String
let line: UWord
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: [SourceLoc] = []
public
init() {}
init(_ loc: SourceLoc) {
locs = [ loc ]
}
init(_locs: [SourceLoc]) {
locs = _locs
}
var isEmpty: Bool {
return locs.isEmpty
}
func with(loc: SourceLoc) -> SourceLocStack {
var locs = self.locs
locs += loc
return SourceLocStack(_locs: locs)
}
public
func withCurrentLoc(
file: String = __FILE__, line: UWord = __LINE__
) -> SourceLocStack {
return with(SourceLoc(file, line))
}
}
internal func _printStackTrace(stackTrace: SourceLocStack?) {
if let s = stackTrace {
println("stacktrace:")
for i in 0..<s.locs.count {
let loc = s.locs[s.locs.count - i - 1]
let comment = loc.comment ? " ; \(loc.comment!)" : ""
println(" #\(i): \(loc.file):\(loc.line)\(comment)")
}
}
}
var _anyExpectFailed = false
public func expectEqual<T : Equatable>(
expected: T, actual: T,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__
) {
if expected != actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\" (of type \(_stdlib_getTypeName(expected)))")
println("actual: \"\(actual)\" (of type \(_stdlib_getTypeName(expected)))")
println()
}
}
public func expectEqual<T : Equatable>(
expected: T, actual: T,
stackTrace: SourceLocStack? = nil,
collectMoreInfo: () -> String,
file: String = __FILE__, line: UWord = __LINE__
) {
if expected != actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\" (of type \(_stdlib_getTypeName(expected)))")
println("actual: \"\(actual)\" (of type \(_stdlib_getTypeName(expected)))")
println(collectMoreInfo())
println()
}
}
public func expectNotEqual<T : Equatable>(
expected: T, actual: T,
file: String = __FILE__, line: UWord = __LINE__
) {
if expected == actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("unexpected value: \"\(actual)\" (of type \(_stdlib_getTypeName(actual)))")
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?,
file: String = __FILE__, line: UWord = __LINE__
) {
if !actual || expected != actual! {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("expected: \"\(expected)\" (of type \(_stdlib_getTypeName(expected)))")
println("actual: \"\(actual)\" (of type \(_stdlib_getTypeName(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>', 'Slice<T>'),
% ('<T : Equatable>', 'Array<T>'),
% ('<T, U : Equatable>', 'Dictionary<T, U>'),
% ('<T : ForwardIndexType>', 'T')]:
public func expectEqual${Generic}(
expected: ${EquatableType}, actual: ${EquatableType},
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__
) {
if expected != actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\" (of type \(_stdlib_getTypeName(expected)))")
println("actual: \"\(actual)\" (of type \(_stdlib_getTypeName(actual)))")
println()
}
}
public func expectEqual${Generic}(
expected: ${EquatableType}, actual: ${EquatableType},
stackTrace: SourceLocStack? = nil,
collectMoreInfo: () -> String,
file: String = __FILE__, line: UWord = __LINE__
) {
if expected != actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: \"\(expected)\" (of type \(_stdlib_getTypeName(expected)))")
println("actual: \"\(actual)\" (of type \(_stdlib_getTypeName(actual)))")
println(collectMoreInfo())
println()
}
}
func _expectNotEqual${Generic}(
expected: ${EquatableType}, actual: ${EquatableType},
file: String = __FILE__, line: UWord = __LINE__
) {
if expected == actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("unexpected value: \"\(actual)\" (of type \(_stdlib_getTypeName(actual)))")
println()
}
}
%end
%for ComparableType in ['Int']:
public func expectLE(
expected: ${ComparableType}, actual: ${ComparableType},
file: String = __FILE__, line: UWord = __LINE__
) {
if !(expected <= actual) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("expected: \"\(expected)\"")
println("actual: \"\(actual)\"")
println()
}
}
public func expectGE(
expected: ${ComparableType}, actual: ${ComparableType},
file: String = __FILE__, line: UWord = __LINE__
) {
if !(expected >= actual) {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("expected: \"\(expected)\"")
println("actual: \"\(actual)\"")
println()
}
}
%end
public struct AssertionResult : Printable, LogicValueType {
init(isPass: Bool) {
self._isPass = isPass
}
public func getLogicValue() -> 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)
}
%for BoolType in ['Bool', 'AssertionResult']:
public func expectTrue(
actual: ${BoolType},
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__
) {
if !actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected: true")
println("actual: \(actual)")
println()
}
}
public func expectFalse(
actual: ${BoolType},
file: String = __FILE__, line: UWord = __LINE__
) {
if actual {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("expected: false")
println("actual: \(actual)")
println()
}
}
%end
public func expectEmpty<T>(
value: Optional<T>,
stackTrace: SourceLocStack? = nil,
file: String = __FILE__, line: UWord = __LINE__
) {
if value {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
_printStackTrace(stackTrace)
println("expected optional to be empty")
println("actual: \"\(value)\"")
println()
}
}
public func expectNotEmpty<T>(
value: Optional<T>,
file: String = __FILE__, line: UWord = __LINE__
) {
if !value {
_anyExpectFailed = true
println("check failed at \(file), line \(line)")
println("expected optional to be non-empty")
println()
}
}
public struct TestCase {
public init(_ name: String) {
self.name = name
}
public mutating func test(name: String, testFunction: () -> ()) {
_tests.append(_Test(name: name, code: testFunction))
}
public mutating func run() {
var anyTestFailed = false
for t in _tests {
var fullTestName = "\(name).\(t.name)"
println("[ RUN ] \(fullTestName)")
_anyExpectFailed = false
t.code()
if _anyExpectFailed {
anyTestFailed = true
println("[ FAIL ] \(fullTestName)")
} else {
println("[ OK ] \(fullTestName)")
}
}
if anyTestFailed {
println("Some tests failed, aborting")
abort()
} else {
println("\(name): All tests passed")
}
}
struct _Test {
var name: String
var code: () -> ()
}
var name: String
var _tests: [_Test] = []
}
// These APIs don't really belong in a unittesting library, but are useful
// in tests, and stdlib does not have such facilities yet.
public func asHex(a: [UInt8]) -> String {
return "[ " + ", ".join(a.map { "0x" + String($0, radix: 16) }) + " ]"
}
public func asHex(a: [UInt32]) -> String {
return "[ " + ", ".join(a.map { "0x" + String($0, radix: 16) }) + " ]"
}
//
// Helpers that verify invariants of various stdlib types.
//
public
func checkGenerator<
Element : Equatable, G : GeneratorType
where G.Element == Element>(
expected: [Element], generator: G, stackTrace: SourceLocStack) {
// Copying a `GeneratorType` is allowed.
var mutableGen = generator
var actual: [Element] = []
while let e = mutableGen.next() {
actual += e
}
expectEqual(expected, actual, stackTrace: stackTrace.withCurrentLoc())
// Having returned `.None` once, a `GeneratorType` should not generate more
// elements.
for i in 0..<10 {
expectEmpty(mutableGen.next(), stackTrace: stackTrace.withCurrentLoc())
}
}
public
func checkSequence<
Element : Equatable, S : SequenceType
where S.Generator.Element == Element>(
expected: [Element], sequence: S, stackTrace: SourceLocStack) {
checkGenerator(expected, sequence.generate(), stackTrace.withCurrentLoc())
expectGE(expected.count, underestimateCount(sequence))
}
public
func checkCollection<
Element : Equatable, C : CollectionType
where C.Generator.Element == Element>(
expected: [Element], collection: C, stackTrace: SourceLocStack) {
// A `CollectionType` is a multi-pass `SequenceType`.
for i in 0..<3 {
checkSequence(expected, collection, stackTrace.withCurrentLoc())
}
expectEqual(expected.count.toIntMax(), countElements(collection).toIntMax(),
stackTrace: stackTrace.withCurrentLoc())
for i in 0..<3 {
let startIndex = collection.startIndex
let endIndex = collection.endIndex
var actual: [Element] = []
var index = collection.startIndex
while index != collection.endIndex {
// Iteration should not change `startIndex` or `endIndex`.
expectEqual(startIndex, collection.startIndex)
expectEqual(endIndex, collection.endIndex)
actual += collection[index]
++index
}
expectEqual(expected, actual, stackTrace: stackTrace.withCurrentLoc())
}
}
public
func checkSliceableWithBidirectionalIndex<
Element : Equatable, S : Sliceable
where S.Generator.Element == Element,
S.SubSlice.Generator.Element == Element,
S.Index : BidirectionalIndexType>(
expected: [Element], sliceable: S, stackTrace: SourceLocStack) {
// A `Sliceable` is a `CollectionType`.
checkCollection(expected, sliceable, stackTrace.withCurrentLoc())
var start = sliceable.startIndex
for startNumericIndex in 0...expected.count {
if start != sliceable.endIndex {
++start
--start
++start
--start
}
var end = start
for endNumericIndex in startNumericIndex...expected.count {
if end != sliceable.endIndex {
++end
--end
++end
--end
}
let expectedSlice: [Element] =
Array(expected[startNumericIndex..<endNumericIndex])
let slice = sliceable[start..<end]
checkCollection(expectedSlice, slice, stackTrace.withCurrentLoc())
if end != sliceable.endIndex {
++end
}
}
if start != sliceable.endIndex {
++start
}
}
}
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End: