//===----------------------------------------------------------------------===// // // This source file is part of the Swift Collections open source project // // Copyright (c) 2021 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// /// Run the supplied closure with all values in `items` in a loop, /// recording the current value in the current test trace stack. public func withEvery( _ label: String, in items: S, file: StaticString = #file, line: UInt = #line, run body: (S.Element) throws -> Void ) rethrows { let context = TestContext.current for item in items { let entry = context.push("\(label): \(item)", file: file, line: line) var done = false defer { context.pop(entry) if !done { print(context.currentTrace(title: "Throwing trace")) } } try body(item) done = true } } public func withEveryRange( _ label: String, in bounds: Range, file: StaticString = #file, line: UInt = #line, run body: (Range) throws -> Void ) rethrows where T.Stride == Int { let context = TestContext.current for lowerBound in bounds.lowerBound ... bounds.upperBound { for upperBound in lowerBound ... bounds.upperBound { let range = lowerBound ..< upperBound let entry = context.push("\(label): \(range)", file: file, line: line) var done = false defer { context.pop(entry) if !done { print(context.currentTrace(title: "Throwing trace")) } } try body(range) done = true } } } internal func _samples(from items: C) -> [C.Element] { let c = items.count guard c > 7 else { return Array(items) } let offsets = [0, 1, c / 2 - 1, c / 2, c / 2 + 1, c - 2, c - 1] var offset = 0 var index = items.startIndex var result: [C.Element] = [] result.reserveCapacity(7) for o in offsets { items.formIndex(&index, offsetBy: o - offset) offset = o result.append(items[index]) } return result } /// Run the supplied closure with all values in `items` in a loop, /// recording the current value in the current test trace stack. public func withSome( _ label: String, in items: C, file: StaticString = #file, line: UInt = #line, run body: (C.Element) throws -> Void ) rethrows { let context = TestContext.current for item in _samples(from: items) { let entry = context.push("\(label): \(item)", file: file, line: line) var done = false defer { context.pop(entry) if !done { print(context.currentTrace(title: "Throwing trace")) } } try body(item) done = true } } public func withSomeRanges( _ label: String, in bounds: Range, file: StaticString = #file, line: UInt = #line, run body: (Range) throws -> Void ) rethrows where T.Stride == Int { let context = TestContext.current for lowerBound in _samples(from: bounds) { for upperBound in _samples(from: lowerBound ... bounds.upperBound) { let range = lowerBound ..< upperBound let entry = context.push("\(label): \(range)", file: file, line: line) var done = false defer { context.pop(entry) if !done { print(context.currentTrace(title: "Throwing trace")) } } try body(range) done = true } } } /// Utility function for testing mutations with value semantics. /// /// Calls `body` with on given collection value, while optionally keeping /// hidden a hidden copy of it around. Once `body` returns, checks that the copy /// remain unchanged. /// /// - Parameters: /// - `enabled`: if `false`, then no copies are made -- the values are passed to `body` with no processing. /// - `value`: The collection value that is being tested. /// - `body`: A closure performing a mutation on `value`. public func withHiddenCopies( if enabled: Bool, of value: inout S, file: StaticString = #file, line: UInt = #line, _ body: (inout S) throws -> R ) rethrows -> R where S.Element: Equatable { guard enabled else { return try body(&value) } let copy = value let expected = Array(value) let result = try body(&value) expectEqualElements(copy, expected, file: file, line: line) return result } /// Utility function for testing mutations with value semantics. /// /// Calls `body` with on given collection value, while optionally keeping /// hidden a hidden copy of it around. Once `body` returns, checks that the copy /// remain unchanged. /// /// - Parameters: /// - `enabled`: if `false`, then no copies are made -- the values are passed to `body` with no processing. /// - `value`: The collection value that is being tested. /// - `body`: A closure performing a mutation on `value`. public func withHiddenCopies< S: Sequence, Key: Equatable, Value: Equatable, R >( if enabled: Bool, of value: inout S, file: StaticString = #file, line: UInt = #line, _ body: (inout S) throws -> R ) rethrows -> R where S.Element == (key: Key, value: Value) { guard enabled else { return try body(&value) } let copy = value let expected = Array(value) let result = try body(&value) expectEqualElements(copy, expected, file: file, line: line) return result }