| //===----------------------------------------------------------------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 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 |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| import StdlibUnittest |
| |
| internal enum TestError : Error { |
| case error1 |
| case error2 |
| } |
| |
| public struct DropFirstTest { |
| public var sequence: [Int] |
| public let dropElements: Int |
| public let expected: [Int] |
| public let loc: SourceLoc |
| |
| public init(sequence: [Int], dropElements: Int, expected: [Int], |
| file: String = #file, line: UInt = #line) { |
| self.sequence = sequence |
| self.dropElements = dropElements |
| self.expected = expected |
| self.loc = SourceLoc(file, line, comment: "dropFirst() test data") |
| } |
| } |
| |
| public struct DropLastTest { |
| public var sequence: [Int] |
| public let dropElements: Int |
| public let expected: [Int] |
| public let loc: SourceLoc |
| |
| public init(sequence: [Int], dropElements: Int, expected: [Int], |
| file: String = #file, line: UInt = #line) { |
| self.sequence = sequence |
| self.dropElements = dropElements |
| self.expected = expected |
| self.loc = SourceLoc(file, line, comment: "dropLast() test data") |
| } |
| } |
| |
| public struct ElementsEqualTest { |
| public let expected: Bool |
| public let sequence: [Int] |
| public let other: [Int] |
| public let expectedLeftoverSequence: [Int] |
| public let expectedLeftoverOther: [Int] |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: Bool, _ sequence: [Int], _ other: [Int], |
| _ expectedLeftoverSequence: [Int], |
| _ expectedLeftoverOther: [Int], |
| file: String = #file, line: UInt = #line, |
| comment: String = "" |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.other = other |
| self.expectedLeftoverSequence = expectedLeftoverSequence |
| self.expectedLeftoverOther = expectedLeftoverOther |
| self.loc = SourceLoc(file, line, comment: "test data" + comment) |
| } |
| |
| func flip() -> ElementsEqualTest { |
| return ElementsEqualTest( |
| expected, other, sequence, |
| expectedLeftoverOther, expectedLeftoverSequence, |
| file: loc.file, line: loc.line, comment: " (flipped)") |
| } |
| } |
| |
| public struct ElementsEqualWithPredicateTest { |
| public let expected: Bool |
| public let sequence: [Int] |
| public let other: [String] |
| public let predicate: (Int, String) -> Bool |
| public let expectedLeftoverSequence: [Int] |
| public let expectedLeftoverOther: [String] |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: Bool, _ sequence: [Int], _ other: [String], |
| _ predicate: @escaping (Int, String) -> Bool, |
| _ expectedLeftoverSequence: [Int], |
| _ expectedLeftoverOther: [String], |
| file: String = #file, line: UInt = #line, |
| comment: String = "" |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.other = other |
| self.predicate = predicate |
| self.expectedLeftoverSequence = expectedLeftoverSequence |
| self.expectedLeftoverOther = expectedLeftoverOther |
| self.loc = SourceLoc(file, line, comment: "test data" + comment) |
| } |
| } |
| |
| public struct EnumerateTest { |
| public let expected: [(Int, Int)] |
| public let sequence: [Int] |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: [(Int, Int)], _ sequence: [Int], |
| file: String = #file, line: UInt = #line, |
| comment: String = "" |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.loc = SourceLoc(file, line, comment: "test data" + comment) |
| } |
| } |
| |
| public struct FilterTest { |
| public let expected: [Int] |
| public let sequence: [Int] |
| public let includeElement: (Int) -> Bool |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: [Int], |
| _ sequence: [Int], |
| _ includeElement: @escaping (Int) -> Bool, |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.includeElement = includeElement |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| public struct FindTest { |
| public let expected: Int? |
| public let element: MinimalEquatableValue |
| public let sequence: [MinimalEquatableValue] |
| public let expectedLeftoverSequence: [MinimalEquatableValue] |
| public let loc: SourceLoc |
| |
| public init( |
| expected: Int?, element: Int, sequence: [Int], |
| expectedLeftoverSequence: [Int], |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected |
| self.element = MinimalEquatableValue(element) |
| self.sequence = sequence.enumerated().map { |
| return MinimalEquatableValue($1, identity: $0) |
| } |
| self.expectedLeftoverSequence = expectedLeftoverSequence.map( |
| MinimalEquatableValue.init) |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| public struct CollectionBinaryOperationTest { |
| public let expected: [MinimalEquatableValue] |
| public let lhs: [MinimalEquatableValue] |
| public let rhs: [MinimalEquatableValue] |
| public let loc: SourceLoc |
| |
| public init( |
| expected: [Int], lhs: [Int], rhs: [Int], |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected.enumerated().map { |
| return MinimalEquatableValue($1, identity: $0) |
| } |
| self.lhs = lhs.map { |
| return MinimalEquatableValue($0, identity: $0) |
| } |
| self.rhs = rhs.map { |
| return MinimalEquatableValue($0, identity: $0) |
| } |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| public struct CollectionPredicateTest { |
| public let expected: Bool |
| public let lhs: [MinimalEquatableValue] |
| public let rhs: [MinimalEquatableValue] |
| public let loc: SourceLoc |
| |
| public init( |
| expected: Bool, lhs: [Int], rhs: [Int], |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected |
| self.lhs = lhs.enumerated().map { |
| return MinimalEquatableValue($1, identity: $0) |
| } |
| self.rhs = rhs.enumerated().map { |
| return MinimalEquatableValue($1, identity: $0) |
| } |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| public struct FlatMapTest { |
| public let expected: [Int32] |
| public let sequence: [Int] |
| public let transform: (Int) -> [Int32] |
| public let loc: SourceLoc |
| |
| public init( |
| expected: [Int32], |
| sequence: [Int], |
| transform: @escaping (Int) -> [Int32], |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.transform = transform |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| public struct FlatMapToOptionalTest { |
| public let expected: [Int32] |
| public let sequence: [Int] |
| public let transform: (Int) -> Int32? |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: [Int32], |
| _ sequence: [Int], |
| _ transform: @escaping (Int) -> Int32?, |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.transform = transform |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| /// This test performs a side effect on each element of `sequence`. The expected |
| /// side effect for the purposes of testing is to append each element to an |
| /// external array, which can be compared to `sequence`. |
| internal struct ForEachTest { |
| let sequence: [Int] |
| let loc: SourceLoc |
| |
| init( |
| _ sequence: [Int], |
| file: String = #file, line: UInt = #line |
| ) { |
| self.sequence = sequence |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| public struct LexicographicallyPrecedesTest { |
| public let expected: ExpectedComparisonResult |
| public let sequence: [Int] |
| public let other: [Int] |
| public let expectedLeftoverSequence: [Int] |
| public let expectedLeftoverOther: [Int] |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: ExpectedComparisonResult, _ sequence: [Int], _ other: [Int], |
| _ expectedLeftoverSequence: [Int], |
| _ expectedLeftoverOther: [Int], |
| file: String = #file, line: UInt = #line, |
| comment: String = "" |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.other = other |
| self.expectedLeftoverSequence = expectedLeftoverSequence |
| self.expectedLeftoverOther = expectedLeftoverOther |
| self.loc = SourceLoc(file, line, comment: "test data" + comment) |
| } |
| |
| func flip() -> LexicographicallyPrecedesTest { |
| return LexicographicallyPrecedesTest( |
| expected.flip(), other, sequence, |
| expectedLeftoverOther, expectedLeftoverSequence, |
| file: loc.file, line: loc.line, comment: " (flipped)") |
| } |
| } |
| |
| public struct MapTest { |
| public let expected: [Int32] |
| public let sequence: [Int] |
| public let transform: (Int) -> Int32 |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: [Int32], |
| _ sequence: [Int], |
| _ transform: @escaping (Int) -> Int32, |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.transform = transform |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| public struct MinMaxTest { |
| public let expectedMinValue: Int? |
| public let expectedMinIndex: Int? |
| public let expectedMaxValue: Int? |
| public let expectedMaxIndex: Int? |
| public let sequence: [Int] |
| public let loc: SourceLoc |
| |
| public init( |
| minValue expectedMinValue: Int?, |
| index expectedMinIndex: Int?, |
| maxValue expectedMaxValue: Int?, |
| index expectedMaxIndex: Int?, |
| _ sequence: [Int], |
| file: String = #file, line: UInt = #line, |
| comment: String = "" |
| ) { |
| self.expectedMinValue = expectedMinValue |
| self.expectedMinIndex = expectedMinIndex |
| self.expectedMaxValue = expectedMaxValue |
| self.expectedMaxIndex = expectedMaxIndex |
| self.sequence = sequence |
| self.loc = SourceLoc(file, line, comment: "test data" + comment) |
| } |
| } |
| |
| public struct PrefixTest { |
| public var sequence: [Int] |
| public let maxLength: Int |
| public let expected: [Int] |
| public let loc: SourceLoc |
| |
| public init(sequence: [Int], maxLength: Int, expected: [Int], |
| file: String = #file, line: UInt = #line) { |
| self.sequence = sequence |
| self.maxLength = maxLength |
| self.expected = expected |
| self.loc = SourceLoc(file, line, comment: "prefix() test data") |
| } |
| } |
| |
| public struct ReduceTest { |
| public let sequence: [Int] |
| public let loc: SourceLoc |
| |
| public init( |
| _ sequence: [Int], |
| file: String = #file, line: UInt = #line |
| ) { |
| self.sequence = sequence |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| public struct ReverseTest { |
| public let expected: [Int] |
| public let sequence: [Int] |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: [Int], _ sequence: [Int], |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| public struct SuffixTest { |
| public var sequence: [Int] |
| public let maxLength: Int |
| public let expected: [Int] |
| public let loc: SourceLoc |
| |
| public init(sequence: [Int], maxLength: Int, expected: [Int], |
| file: String = #file, line: UInt = #line) { |
| self.sequence = sequence |
| self.maxLength = maxLength |
| self.expected = expected |
| self.loc = SourceLoc(file, line, comment: "suffix() test data") |
| } |
| } |
| |
| public struct SplitTest { |
| public var sequence: [Int] |
| public let maxSplits: Int |
| public let separator: Int |
| public let omittingEmptySubsequences: Bool |
| public let expected: [[Int]] |
| public let loc: SourceLoc |
| |
| public init( |
| sequence: [Int], maxSplits: Int, separator: Int, expected: [[Int]], |
| omittingEmptySubsequences: Bool, file: String = #file, line: UInt = #line |
| ) { |
| self.sequence = sequence |
| self.maxSplits = maxSplits |
| self.separator = separator |
| self.omittingEmptySubsequences = omittingEmptySubsequences |
| self.expected = expected |
| self.loc = SourceLoc(file, line, comment: "suffix() test data") |
| } |
| } |
| |
| public struct StartsWithTest { |
| public let expected: Bool |
| public let sequence: [Int] |
| public let prefix: [Int] |
| public let expectedLeftoverSequence: [Int] |
| public let expectedLeftoverPrefix: [Int] |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: Bool, _ sequence: [Int], _ prefix: [Int], |
| _ expectedLeftoverSequence: [Int], |
| _ expectedLeftoverPrefix: [Int], |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.prefix = prefix |
| self.expectedLeftoverSequence = expectedLeftoverSequence |
| self.expectedLeftoverPrefix = expectedLeftoverPrefix |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| public struct ZipTest { |
| public let expected: [(Int, Int32)] |
| public let sequence: [Int] |
| public let other: [Int32] |
| public let expectedLeftoverSequence: [Int] |
| public let expectedLeftoverOther: [Int32] |
| public let loc: SourceLoc |
| |
| public init( |
| _ expected: [(Int, Int32)], |
| sequences sequence: [Int], |
| _ other: [Int32], |
| leftovers expectedLeftoverSequence: [Int], |
| _ expectedLeftoverOther: [Int32], |
| file: String = #file, line: UInt = #line |
| ) { |
| self.expected = expected |
| self.sequence = sequence |
| self.other = other |
| self.expectedLeftoverSequence = expectedLeftoverSequence |
| self.expectedLeftoverOther = expectedLeftoverOther |
| self.loc = SourceLoc(file, line, comment: "test data") |
| } |
| } |
| |
| |
| public let elementsEqualTests: [ElementsEqualTest] = [ |
| ElementsEqualTest(true, [], [], [], []), |
| |
| ElementsEqualTest(false, [ 1 ], [], [], []), |
| ElementsEqualTest(false, [], [ 1 ], [], []), |
| |
| ElementsEqualTest(false, [ 1, 2 ], [], [ 2 ], []), |
| ElementsEqualTest(false, [], [ 1, 2 ], [], [ 2 ]), |
| |
| ElementsEqualTest(false, [ 1, 2, 3, 4 ], [ 1, 2 ], [ 4 ], []), |
| ElementsEqualTest(false, [ 1, 2 ], [ 1, 2, 3, 4 ], [], [ 4 ]), |
| ].flatMap { [ $0, $0.flip() ] } |
| |
| func elementsEqualPredicate(_ x: Int, y: String) -> Bool { |
| if let intVal = Int(y) { |
| return x == intVal |
| } else { |
| return false |
| } |
| } |
| |
| public let elementsEqualWithPredicateTests: [ElementsEqualWithPredicateTest] = [ |
| ElementsEqualWithPredicateTest(true, [], [], elementsEqualPredicate, [], []), |
| |
| ElementsEqualWithPredicateTest(false, [ 1 ], [], elementsEqualPredicate, [ 1 ], []), |
| ElementsEqualWithPredicateTest(false, [], [ "1" ], elementsEqualPredicate, [], [ "1" ]), |
| |
| ElementsEqualWithPredicateTest(false, [ 1, 2 ], [], elementsEqualPredicate, [ 1, 2 ], []), |
| ElementsEqualWithPredicateTest(false, [], [ "1", "2" ], elementsEqualPredicate, [], [ "1", "2" ]), |
| |
| ElementsEqualWithPredicateTest(false, [ 1, 2, 3, 4 ], [ "1", "2" ], elementsEqualPredicate, [ 3, 4 ], []), |
| ElementsEqualWithPredicateTest(false, [ 1, 2 ], [ "1", "2", "3", "4" ], elementsEqualPredicate, [], [ "3", "4" ]), |
| |
| ElementsEqualWithPredicateTest(true, [ 1, 2, 3, 4 ], [ "1", "2", "3", "4" ], elementsEqualPredicate, [], []), |
| ElementsEqualWithPredicateTest(true, [ 1, 2 ], [ "1", "2" ], elementsEqualPredicate, [], []), |
| ] |
| |
| public let enumerateTests = [ |
| EnumerateTest([], []), |
| EnumerateTest([ (0, 10) ], [ 10 ]), |
| EnumerateTest([ (0, 10), (1, 20) ], [ 10, 20 ]), |
| EnumerateTest([ (0, 10), (1, 20), (2, 30) ], [ 10, 20, 30 ]), |
| ] |
| |
| public let filterTests = [ |
| FilterTest( |
| [], [], |
| { _ -> Bool in expectUnreachable(); return true }), |
| |
| FilterTest([], [ 0, 30, 10, 90 ], { _ -> Bool in false }), |
| FilterTest( |
| [ 0, 30, 10, 90 ], [ 0, 30, 10, 90 ], { _ -> Bool in true } |
| ), |
| FilterTest( |
| [ 0, 30, 90 ], [ 0, 30, 10, 90 ], { (x: Int) -> Bool in x % 3 == 0 } |
| ), |
| ] |
| |
| public let findTests = [ |
| FindTest( |
| expected: nil, |
| element: 42, |
| sequence: [], |
| expectedLeftoverSequence: []), |
| |
| FindTest( |
| expected: nil, |
| element: 42, |
| sequence: [ 1010 ], |
| expectedLeftoverSequence: []), |
| FindTest( |
| expected: 0, |
| element: 1010, |
| sequence: [ 1010 ], |
| expectedLeftoverSequence: []), |
| |
| FindTest( |
| expected: nil, |
| element: 42, |
| sequence: [ 1010, 1010 ], |
| expectedLeftoverSequence: []), |
| FindTest( |
| expected: 0, |
| element: 1010, |
| sequence: [ 1010, 1010 ], |
| expectedLeftoverSequence: [ 1010 ]), |
| |
| FindTest( |
| expected: nil, |
| element: 42, |
| sequence: [ 1010, 2020, 3030, 4040 ], |
| expectedLeftoverSequence: []), |
| FindTest( |
| expected: 0, |
| element: 1010, |
| sequence: [ 1010, 2020, 3030, 4040 ], |
| expectedLeftoverSequence: [ 2020, 3030, 4040 ]), |
| FindTest( |
| expected: 1, |
| element: 2020, |
| sequence: [ 1010, 2020, 3030, 4040 ], |
| expectedLeftoverSequence: [ 3030, 4040 ]), |
| FindTest( |
| expected: 2, |
| element: 3030, |
| sequence: [ 1010, 2020, 3030, 4040 ], |
| expectedLeftoverSequence: [ 4040 ]), |
| FindTest( |
| expected: 3, |
| element: 4040, |
| sequence: [ 1010, 2020, 3030, 4040 ], |
| expectedLeftoverSequence: []), |
| |
| FindTest( |
| expected: 1, |
| element: 2020, |
| sequence: [ 1010, 2020, 3030, 2020, 4040 ], |
| expectedLeftoverSequence: [ 3030, 2020, 4040 ]), |
| ] |
| |
| public let unionTests = [ |
| CollectionBinaryOperationTest(expected: [1, 2, 3, 4, 5], lhs: [1, 3, 5], rhs: [2, 4]), |
| CollectionBinaryOperationTest(expected: [3, 5], lhs: [3], rhs: [5]) |
| ] |
| |
| public let intersectionTests = [ |
| CollectionBinaryOperationTest(expected: [1, 5], lhs: [1, 3, 5], rhs: [1, 2, 5]) |
| ] |
| |
| public let symmetricDifferenceTests = [ |
| CollectionBinaryOperationTest(expected: [1, 3, 5], lhs: [1, 2, 3, 4], rhs: [2, 4, 5]) |
| ] |
| |
| public let subtractTests = [ |
| CollectionBinaryOperationTest(expected: [1, 3], lhs: [1, 2, 3, 4], rhs: [2, 4, 5]) |
| ] |
| |
| public let subtractingTests = [ |
| CollectionBinaryOperationTest(expected: [1, 3, 4], lhs: [1, 2, 3, 4, 5], rhs: [2, 5, 6, 7]) |
| ] |
| |
| public let strictSupersetTests = [ |
| CollectionPredicateTest(expected: true, lhs: [1, 2, 3, 4, 5, 6], rhs: [1, 2, 3, 4]), |
| CollectionPredicateTest(expected: false, lhs: [1, 2], rhs: [1, 2, 4]) |
| ] |
| |
| /// For a number of form `NNN_MMM`, returns an array of `NNN` numbers that all |
| /// have `MMM` as their last three digits. |
| func flatMapTransformation(_ x: Int) -> [Int32] { |
| let repetitions = x / 1000 |
| let identity = x % 1000 |
| let range = (1..<(repetitions+1)) |
| return range.map { Int32($0 * 1000 + identity) } |
| } |
| |
| public let flatMapTests = [ |
| FlatMapTest( |
| expected: [], |
| sequence: [], |
| transform: { _ -> [Int32] in |
| expectUnreachable() |
| return [ 0xffff ] |
| }), |
| |
| FlatMapTest( |
| expected: [], |
| sequence: [ 1 ], |
| transform: { _ -> [Int32] in [] }), |
| FlatMapTest( |
| expected: [], |
| sequence: [ 1, 2 ], |
| transform: { _ -> [Int32] in [] }), |
| FlatMapTest( |
| expected: [], |
| sequence: [ 1, 2, 3 ], |
| transform: { _ -> [Int32] in [] }), |
| |
| FlatMapTest( |
| expected: [ 101 ], |
| sequence: [ 1 ], |
| transform: { (x: Int) -> [Int32] in [ Int32(x + 100) ] }), |
| FlatMapTest( |
| expected: [ 101, 102 ], |
| sequence: [ 1, 2 ], |
| transform: { (x: Int) -> [Int32] in [ Int32(x + 100) ] }), |
| FlatMapTest( |
| expected: [ 101, 102, 103 ], |
| sequence: [ 1, 2, 3 ], |
| transform: { (x: Int) -> [Int32] in [ Int32(x + 100) ] }), |
| |
| FlatMapTest( |
| expected: [ 101, 201 ], |
| sequence: [ 1 ], |
| transform: { (x: Int) -> [Int32] in [ Int32(x + 100), Int32(x + 200) ] }), |
| FlatMapTest( |
| expected: [ 101, 201, 102, 202 ], |
| sequence: [ 1, 2 ], |
| transform: { (x: Int) -> [Int32] in [ Int32(x + 100), Int32(x + 200) ] }), |
| FlatMapTest( |
| expected: [ 101, 201, 102, 202, 103, 203 ], |
| sequence: [ 1, 2, 3 ], |
| transform: { (x: Int) -> [Int32] in [ Int32(x + 100), Int32(x + 200) ] }), |
| |
| FlatMapTest( |
| expected: [ 1_071, 1_075 ], |
| sequence: [ 1_071, 72, 73, 74, 1_075 ], |
| transform: flatMapTransformation), |
| FlatMapTest( |
| expected: [ 1_072, 1_073, 2_073 ], |
| sequence: [ 1, 1_072, 2_073 ], |
| transform: flatMapTransformation), |
| FlatMapTest( |
| expected: [ 1_071, 2_071, 1_073, 2_073, 3_073, 1_074 ], |
| sequence: [ 2_071, 2, 3_073, 1_074 ], |
| transform: flatMapTransformation), |
| |
| FlatMapTest( |
| expected: [ 1_073, 1_076, 2_076, 1_079, 2_079, 3_079 ], |
| sequence: [ 1, 2, 1_073, 4, 5, 2_076, 7, 8, 3_079, 10, 11 ], |
| transform: flatMapTransformation), |
| FlatMapTest( |
| expected: [ 1_073, 1_076, 2_076, 1_079, 2_079, 3_079 ], |
| sequence: [ 1_073, 4, 5, 2_076, 7, 8, 3_079, 10, 11 ], |
| transform: flatMapTransformation), |
| FlatMapTest( |
| expected: [ 1_073, 1_076, 2_076, 1_079, 2_079, 3_079 ], |
| sequence: [ 1, 2, 1_073, 4, 5, 2_076, 7, 8, 3_079 ], |
| transform: flatMapTransformation), |
| |
| FlatMapTest( |
| expected: [ 1_073, 1_076, 2_076, 1_079, 2_079, 3_079 ], |
| sequence: [ 1, 1_073, 4, 2_076, 7, 3_079, 10 ], |
| transform: flatMapTransformation), |
| FlatMapTest( |
| expected: [ 1_073, 1_076, 2_076, 1_079, 2_079, 3_079 ], |
| sequence: [ 1_073, 4, 2_076, 7, 3_079, 10 ], |
| transform: flatMapTransformation), |
| FlatMapTest( |
| expected: [ 1_073, 1_076, 2_076, 1_079, 2_079, 3_079 ], |
| sequence: [ 1, 1_073, 4, 2_076, 7, 3_079 ], |
| transform: flatMapTransformation), |
| ] |
| |
| public let flatMapToOptionalTests = [ |
| FlatMapToOptionalTest( |
| [], [], |
| { _ -> Int32? in expectUnreachable(); return 0xffff }), |
| |
| FlatMapToOptionalTest([], [ 1 ], { _ -> Int32? in nil }), |
| FlatMapToOptionalTest([], [ 1, 2 ], { _ -> Int32? in nil }), |
| FlatMapToOptionalTest([], [ 1, 2, 3 ], { _ -> Int32? in nil }), |
| |
| FlatMapToOptionalTest( |
| [ 1 ], [ 1 ], |
| { (x: Int) -> Int32? in x > 10 ? nil : Int32(x) }), |
| FlatMapToOptionalTest( |
| [ 2 ], [ 11, 2, 13, 14 ], |
| { (x: Int) -> Int32? in x > 10 ? nil : Int32(x) }), |
| FlatMapToOptionalTest( |
| [ 1, 4 ], [ 1, 12, 13, 4 ], |
| { (x: Int) -> Int32? in x > 10 ? nil : Int32(x) }), |
| FlatMapToOptionalTest( |
| [ 1, 2, 3 ], [ 1, 2, 3 ], |
| { (x: Int) -> Int32? in x > 10 ? nil : Int32(x) }), |
| ] |
| |
| |
| public let dropFirstTests = [ |
| DropFirstTest( |
| sequence: [], |
| dropElements: 0, |
| expected: [] |
| ), |
| DropFirstTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 1, |
| expected: [2020, 3030] |
| ), |
| DropFirstTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 2, |
| expected: [3030] |
| ), |
| DropFirstTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 3, |
| expected: [] |
| ), |
| DropFirstTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 777, |
| expected: [] |
| ), |
| DropFirstTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 0, |
| expected: [1010, 2020, 3030] |
| ), |
| ] |
| |
| public let dropLastTests = [ |
| DropLastTest( |
| sequence: [], |
| dropElements: 0, |
| expected: [] |
| ), |
| DropLastTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 1, |
| expected: [1010, 2020] |
| ), |
| DropLastTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 2, |
| expected: [1010] |
| ), |
| DropLastTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 3, |
| expected: [] |
| ), |
| DropLastTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 777, |
| expected: [] |
| ), |
| DropLastTest( |
| sequence: [1010, 2020, 3030], |
| dropElements: 0, |
| expected: [1010, 2020, 3030] |
| ), |
| ] |
| |
| internal let forEachTests = [ |
| ForEachTest([]), |
| ForEachTest([1010]), |
| ForEachTest([1010, 2020, 3030, 4040, 5050]), |
| ] |
| |
| public let lexicographicallyPrecedesTests = [ |
| LexicographicallyPrecedesTest(.eq, [], [], [], []), |
| LexicographicallyPrecedesTest(.eq, [ 1 ], [ 1 ], [], []), |
| |
| LexicographicallyPrecedesTest(.gt, [ 1 ], [], [], []), |
| |
| LexicographicallyPrecedesTest(.gt, [ 1 ], [ 0 ], [], []), |
| LexicographicallyPrecedesTest(.eq, [ 1 ], [ 1 ], [], []), |
| LexicographicallyPrecedesTest(.lt, [ 1 ], [ 2 ], [], []), |
| |
| LexicographicallyPrecedesTest(.gt, [ 1, 2 ], [], [ 2 ], []), |
| |
| LexicographicallyPrecedesTest(.gt, [ 1, 2 ], [ 0 ], [ 2 ], []), |
| LexicographicallyPrecedesTest(.gt, [ 1, 2 ], [ 1 ], [], []), |
| LexicographicallyPrecedesTest(.lt, [ 1, 2 ], [ 2 ], [ 2 ], []), |
| |
| LexicographicallyPrecedesTest(.gt, [ 1, 2 ], [ 0, 0 ], [ 2 ], [ 0 ]), |
| LexicographicallyPrecedesTest(.gt, [ 1, 2 ], [ 1, 0 ], [], []), |
| LexicographicallyPrecedesTest(.lt, [ 1, 2 ], [ 2, 0 ], [ 2 ], [ 0 ]), |
| |
| LexicographicallyPrecedesTest(.gt, [ 1, 2 ], [ 0, 1 ], [ 2 ], [ 1 ]), |
| LexicographicallyPrecedesTest(.gt, [ 1, 2 ], [ 1, 1 ], [], []), |
| LexicographicallyPrecedesTest(.lt, [ 1, 2 ], [ 2, 1 ], [ 2 ], [ 1 ]), |
| |
| LexicographicallyPrecedesTest(.gt, [ 1, 2 ], [ 0, 2 ], [ 2 ], [ 2 ]), |
| LexicographicallyPrecedesTest(.eq, [ 1, 2 ], [ 1, 2 ], [], []), |
| LexicographicallyPrecedesTest(.lt, [ 1, 2 ], [ 2, 2 ], [ 2 ], [ 2 ]), |
| |
| LexicographicallyPrecedesTest(.gt, [ 1, 2 ], [ 0, 3 ], [ 2 ], [ 3 ]), |
| LexicographicallyPrecedesTest(.lt, [ 1, 2 ], [ 1, 3 ], [], []), |
| LexicographicallyPrecedesTest(.lt, [ 1, 2 ], [ 2, 3 ], [ 2 ], [ 3 ]), |
| ].flatMap { [ $0, $0.flip() ] } |
| |
| public let mapTests = [ |
| MapTest( |
| [], [], |
| { _ -> Int32 in expectUnreachable(); return 0xffff }), |
| |
| MapTest([ 101 ], [ 1 ], |
| { (x: Int) -> Int32 in Int32(x + 100) }), |
| MapTest([ 101, 102 ], [ 1, 2 ], |
| { (x: Int) -> Int32 in Int32(x + 100) }), |
| MapTest([ 101, 102, 103 ], [ 1, 2, 3 ], |
| { (x: Int) -> Int32 in Int32(x + 100) }), |
| MapTest(Array(101..<200), Array(1..<100), |
| { (x: Int) -> Int32 in Int32(x + 100) }), |
| ] |
| |
| public let minMaxTests = [ |
| MinMaxTest( |
| minValue: nil, index: nil, |
| maxValue: nil, index: nil, |
| []), |
| MinMaxTest( |
| minValue: 42, index: 0, |
| maxValue: 42, index: 0, |
| [ 42 ]), |
| MinMaxTest( |
| minValue: -1, index: 1, |
| maxValue: 30, index: 2, |
| [ 10, -1, 30, -1, 30 ]), |
| MinMaxTest( |
| minValue: -2, index: 5, |
| maxValue: 31, index: 6, |
| [ 10, -1, 30, -1, 30, -2, 31 ]), |
| ] |
| |
| public let reduceTests = [ |
| ReduceTest([]), |
| ReduceTest([ 1 ]), |
| ReduceTest([ 1, 2 ]), |
| ReduceTest([ 1, 2, 3 ]), |
| ReduceTest([ 1, 2, 3, 4, 5, 6, 7 ]), |
| ] |
| |
| public let reverseTests: [ReverseTest] = [ |
| ReverseTest([], []), |
| ReverseTest([ 1 ], [ 1 ]), |
| ReverseTest([ 2, 1 ], [ 1, 2 ]), |
| ReverseTest([ 3, 2, 1 ], [ 1, 2, 3 ]), |
| ReverseTest([ 4, 3, 2, 1 ], [ 1, 2, 3, 4]), |
| ReverseTest( |
| [ 7, 6, 5, 4, 3, 2, 1 ], |
| [ 1, 2, 3, 4, 5, 6, 7 ]), |
| ] |
| |
| public let splitTests: [SplitTest] = [ |
| // |
| // Empty sequence. |
| // |
| |
| // Empty sequence, maxSplits == 0. |
| SplitTest( |
| sequence: [], |
| maxSplits: 0, |
| separator: 99, |
| expected: [[]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [], |
| maxSplits: 0, |
| separator: 99, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| |
| // Empty sequence, maxSplits == 1. |
| SplitTest( |
| sequence: [], |
| maxSplits: 1, |
| separator: 99, |
| expected: [[]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [], |
| maxSplits: 1, |
| separator: 99, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| |
| // Empty sequence, maxSplits == Int.max. |
| SplitTest( |
| sequence: [], |
| maxSplits: Int.max, |
| separator: 99, |
| expected: [[]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [], |
| maxSplits: Int.max, |
| separator: 99, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| |
| // |
| // 1-element sequence. |
| // |
| |
| // 1-element sequence, maxSplits == 0. |
| SplitTest( |
| sequence: [1], |
| maxSplits: 0, |
| separator: 1, |
| expected: [[1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1], |
| maxSplits: 0, |
| separator: 99, |
| expected: [[1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1], |
| maxSplits: 0, |
| separator: 1, |
| expected: [[1]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1], |
| maxSplits: 0, |
| separator: 99, |
| expected: [[1]], |
| omittingEmptySubsequences: true |
| ), |
| |
| // 1-element sequence, maxSplits == 1. |
| SplitTest( |
| sequence: [1], |
| maxSplits: 1, |
| separator: 1, |
| expected: [[], []], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1], |
| maxSplits: 1, |
| separator: 99, |
| expected: [[1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1], |
| maxSplits: 1, |
| separator: 1, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1], |
| maxSplits: 1, |
| separator: 99, |
| expected: [[1]], |
| omittingEmptySubsequences: true |
| ), |
| |
| // 1-element sequence, maxSplits == Int.max. |
| SplitTest( |
| sequence: [1], |
| maxSplits: Int.max, |
| separator: 1, |
| expected: [[], []], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1], |
| maxSplits: Int.max, |
| separator: 99, |
| expected: [[1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1], |
| maxSplits: Int.max, |
| separator: 1, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1], |
| maxSplits: Int.max, |
| separator: 99, |
| expected: [[1]], |
| omittingEmptySubsequences: true |
| ), |
| |
| // |
| // 2-element sequence [1, 2]. |
| // |
| |
| // 2-element sequence [1, 2], maxSplits == 0. |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 0, |
| separator: 1, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 0, |
| separator: 2, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 0, |
| separator: 99, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 0, |
| separator: 1, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 0, |
| separator: 2, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 0, |
| separator: 99, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: true |
| ), |
| |
| // 2-element sequence [1, 2], maxSplits == 1. |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 1, |
| separator: 1, |
| expected: [[], [2]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 1, |
| separator: 2, |
| expected: [[1], []], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 1, |
| separator: 99, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 1, |
| separator: 1, |
| expected: [[2]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 1, |
| separator: 2, |
| expected: [[1]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: 1, |
| separator: 99, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: true |
| ), |
| |
| // 2-element sequence [1, 2], maxSplits == Int.max. |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: Int.max, |
| separator: 1, |
| expected: [[], [2]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: Int.max, |
| separator: 2, |
| expected: [[1], []], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: Int.max, |
| separator: 99, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: Int.max, |
| separator: 1, |
| expected: [[2]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: Int.max, |
| separator: 2, |
| expected: [[1]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 2], |
| maxSplits: Int.max, |
| separator: 99, |
| expected: [[1, 2]], |
| omittingEmptySubsequences: true |
| ), |
| |
| // |
| // 2-element sequence [1, 1]. |
| // |
| |
| // 2-element sequence [1, 1], maxSplits == 0. |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 0, |
| separator: 1, |
| expected: [[1, 1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 0, |
| separator: 99, |
| expected: [[1, 1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 0, |
| separator: 1, |
| expected: [[1, 1]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 0, |
| separator: 99, |
| expected: [[1, 1]], |
| omittingEmptySubsequences: true |
| ), |
| |
| // 2-element sequence [1, 1], maxSplits == 1. |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 1, |
| separator: 1, |
| expected: [[], [1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 1, |
| separator: 99, |
| expected: [[1, 1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 1, |
| separator: 1, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 1, |
| separator: 99, |
| expected: [[1, 1]], |
| omittingEmptySubsequences: true |
| ), |
| |
| // 2-element sequence [1, 1], maxSplits == 2. |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 2, |
| separator: 1, |
| expected: [[], [], []], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 2, |
| separator: 99, |
| expected: [[1, 1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 2, |
| separator: 1, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 1], |
| maxSplits: 2, |
| separator: 99, |
| expected: [[1, 1]], |
| omittingEmptySubsequences: true |
| ), |
| |
| // |
| // 3-element sequence [1, 1, 1]. |
| // |
| |
| SplitTest( |
| sequence: [1, 1, 1], |
| maxSplits: 1, |
| separator: 1, |
| expected: [[], [1, 1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1, 1], |
| maxSplits: 2, |
| separator: 1, |
| expected: [[], [], [1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1, 1], |
| maxSplits: 3, |
| separator: 1, |
| expected: [[], [], [], []], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1, 1], |
| maxSplits: Int.max, |
| separator: 1, |
| expected: [[], [], [], []], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 1, 1], |
| maxSplits: 1, |
| separator: 1, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 1, 1], |
| maxSplits: 2, |
| separator: 1, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 1, 1], |
| maxSplits: 3, |
| separator: 1, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 1, 1], |
| maxSplits: Int.max, |
| separator: 1, |
| expected: [], |
| omittingEmptySubsequences: true |
| ), |
| |
| // |
| // Other tests. |
| // |
| |
| SplitTest( |
| sequence: [1, 2, 2, 2, 1], |
| maxSplits: 1, |
| separator: 2, |
| expected: [[1], [2, 2, 1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2, 2, 2, 1], |
| maxSplits: Int.max, |
| separator: 2, |
| expected: [[1], [], [], [1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2, 2, 2, 1], |
| maxSplits: Int.max, |
| separator: 2, |
| expected: [[1], [1]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1], |
| maxSplits: Int.max, |
| separator: 2, |
| expected: [[1], [], [], [1], [], [], [1], [], [], [1]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1], |
| maxSplits: Int.max, |
| separator: 2, |
| expected: [[1], [1], [1], [1]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2], |
| maxSplits: Int.max, |
| separator: 2, |
| expected: |
| [[], [], [], [1], [], [], [1], [], [], [1], [], [], [1], [], [], []], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2], |
| maxSplits: Int.max, |
| separator: 2, |
| expected: [[1], [1], [1], [1]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 2, 3, 4, 5, 6, 7], |
| maxSplits: 4, |
| separator: 4, |
| expected: [[1, 2, 3], [5, 6, 7]], |
| omittingEmptySubsequences: true |
| ), |
| SplitTest( |
| sequence: [1, 2, 3, 3, 4, 5, 6, 7], |
| maxSplits: 3, |
| separator: 3, |
| expected: [[1, 2], [], [4, 5, 6, 7]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2, 2, 2, 2, 2, 2, 2, 2], |
| maxSplits: 3, |
| separator: 2, |
| expected: [[1], [], [], [2, 2, 2, 2, 2]], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2, 2, 2], |
| maxSplits: Int.max, |
| separator: 2, |
| expected: [[1], [], [], []], |
| omittingEmptySubsequences: false |
| ), |
| SplitTest( |
| sequence: [1, 2, 2, 2], |
| maxSplits: Int.max, |
| separator: 3, |
| expected: [[1, 2, 2, 2]], |
| omittingEmptySubsequences: false |
| ), |
| ] |
| |
| public let prefixTests = [ |
| PrefixTest( |
| sequence: [], |
| maxLength: 0, |
| expected: [] |
| ), |
| PrefixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 1, |
| expected: [1010] |
| ), |
| PrefixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 2, |
| expected: [1010, 2020] |
| ), |
| PrefixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 3, |
| expected: [1010, 2020, 3030] |
| ), |
| PrefixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 777, |
| expected: [1010, 2020, 3030] |
| ), |
| PrefixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 0, |
| expected: [] |
| ), |
| PrefixTest( |
| sequence: [2, 3, 5, 7, 11], |
| maxLength: 6, |
| expected: [2, 3, 5, 7, 11] |
| ), |
| PrefixTest( |
| sequence: [2, 3, 5, 7, 11], |
| maxLength: 5, |
| expected: [2, 3, 5, 7, 11] |
| ), |
| ] |
| |
| public let startsWithTests = [ |
| // Corner cases. |
| StartsWithTest(true, [], [], [], []), |
| |
| StartsWithTest(false, [], [ 1 ], [], []), |
| StartsWithTest(true, [ 1 ], [], [], []), |
| |
| // Equal sequences. |
| StartsWithTest(true, [ 1 ], [ 1 ], [], []), |
| StartsWithTest(true, [ 1, 2 ], [ 1, 2 ], [], []), |
| |
| // Proper prefix. |
| StartsWithTest(true, [ 0, 1, 2 ], [ 0, 1 ], [], []), |
| StartsWithTest(false, [ 0, 1 ], [ 0, 1, 2 ], [], []), |
| |
| StartsWithTest(true, [ 1, 2, 3, 4 ], [ 1, 2 ], [ 4 ], []), |
| StartsWithTest(false, [ 1, 2 ], [ 1, 2, 3, 4 ], [], [ 4 ]), |
| |
| // Not a prefix. |
| StartsWithTest(false, [ 1, 2, 3, 4 ], [ 1, 2, 10 ], [ 4 ], []), |
| StartsWithTest(false, [ 1, 2, 10 ], [ 1, 2, 3, 4 ], [], [ 4 ]), |
| |
| StartsWithTest(false, [ 1, 2, 3, 4, 10 ], [ 1, 2, 10 ], [ 4, 10 ], []), |
| StartsWithTest(false, [ 1, 2, 10 ], [ 1, 2, 3, 4, 10 ], [], [ 4, 10 ]), |
| ] |
| |
| |
| public let suffixTests = [ |
| SuffixTest( |
| sequence: [], |
| maxLength: 0, |
| expected: [] |
| ), |
| SuffixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 1, |
| expected: [3030] |
| ), |
| SuffixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 2, |
| expected: [2020, 3030] |
| ), |
| SuffixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 3, |
| expected: [1010, 2020, 3030] |
| ), |
| SuffixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 777, |
| expected: [1010, 2020, 3030] |
| ), |
| SuffixTest( |
| sequence: [1010, 2020, 3030], |
| maxLength: 0, |
| expected: [] |
| ), |
| ] |
| |
| public let zipTests = [ |
| ZipTest([], sequences: [], [], leftovers: [], []), |
| ZipTest([], sequences: [], [ 1 ], leftovers: [], [ 1 ]), |
| ZipTest([], sequences: [], [ 1, 2 ], leftovers: [], [ 1, 2 ]), |
| ZipTest([], sequences: [], [ 1, 2, 3 ], leftovers: [], [ 1, 2, 3 ]), |
| |
| ZipTest([], sequences: [ 10 ], [], leftovers: [], []), |
| ZipTest([ (10, 1) ], sequences: [ 10 ], [ 1 ], leftovers: [], []), |
| ZipTest([ (10, 1) ], sequences: [ 10 ], [ 1, 2 ], leftovers: [], [ 2 ]), |
| ZipTest([ (10, 1) ], sequences: [ 10 ], [ 1, 2, 3 ], leftovers: [], [ 2, 3 ]), |
| |
| ZipTest( |
| [], |
| sequences: [ 10, 20 ], [], |
| leftovers: [ 20 ], []), |
| ZipTest( |
| [ (10, 1) ], |
| sequences: [ 10, 20 ], [ 1 ], |
| leftovers: [], []), |
| ZipTest( |
| [ (10, 1), (20, 2) ], |
| sequences: [ 10, 20 ], [ 1, 2 ], |
| leftovers: [], []), |
| ZipTest( |
| [ (10, 1), (20, 2) ], |
| sequences: [ 10, 20 ], [ 1, 2, 3 ], |
| leftovers: [], [ 3 ]), |
| |
| ZipTest( |
| [], |
| sequences: [ 10, 20, 30 ], [], |
| leftovers: [ 20, 30 ], []), |
| ZipTest( |
| [ (10, 1) ], |
| sequences: [ 10, 20, 30 ], [ 1 ], |
| leftovers: [ 30 ], []), |
| ZipTest( |
| [ (10, 1), (20, 2) ], |
| sequences: [ 10, 20, 30 ], [ 1, 2 ], |
| leftovers: [], []), |
| ZipTest( |
| [ (10, 1), (20, 2), (30, 3) ], |
| sequences: [ 10, 20, 30 ], [ 1, 2, 3 ], |
| leftovers: [], []), |
| ] |
| |
| public func callGenericUnderestimatedCount<S : Sequence>(_ s: S) -> Int { |
| return s.underestimatedCount |
| } |
| |
| extension TestSuite { |
| public func addSequenceTests< |
| S : Sequence, |
| SequenceWithEquatableElement : Sequence |
| >( |
| _ testNamePrefix: String = "", |
| makeSequence: @escaping ([S.Iterator.Element]) -> S, |
| wrapValue: @escaping (OpaqueValue<Int>) -> S.Iterator.Element, |
| extractValue: @escaping (S.Iterator.Element) -> OpaqueValue<Int>, |
| |
| makeSequenceOfEquatable: @escaping ([SequenceWithEquatableElement.Iterator.Element]) -> SequenceWithEquatableElement, |
| wrapValueIntoEquatable: @escaping (MinimalEquatableValue) -> SequenceWithEquatableElement.Iterator.Element, |
| extractValueFromEquatable: @escaping ((SequenceWithEquatableElement.Iterator.Element) -> MinimalEquatableValue), |
| |
| resiliencyChecks: CollectionMisuseResiliencyChecks = .all |
| ) where |
| SequenceWithEquatableElement.Iterator.Element : Equatable { |
| |
| var testNamePrefix = testNamePrefix |
| |
| if !checksAdded.insert( |
| "\(testNamePrefix).\(S.self).\(#function)" |
| ).inserted { |
| return |
| } |
| |
| func makeWrappedSequence(_ elements: [OpaqueValue<Int>]) -> S { |
| return makeSequence(elements.map(wrapValue)) |
| } |
| |
| func makeWrappedSequenceWithEquatableElement( |
| _ elements: [MinimalEquatableValue] |
| ) -> SequenceWithEquatableElement { |
| return makeSequenceOfEquatable(elements.map(wrapValueIntoEquatable)) |
| } |
| |
| testNamePrefix += String(describing: S.Type.self) |
| |
| let isMultiPass = makeSequence([]) |
| ._preprocessingPass { true } ?? false |
| let isEquatableMultiPass = makeSequenceOfEquatable([]) |
| ._preprocessingPass { true } ?? false |
| expectEqual( |
| isMultiPass, isEquatableMultiPass, |
| "Two sequence types are of different kinds?") |
| |
| // FIXME: swift-3-indexing-model: add tests for `underestimatedCount` |
| // Check that it is non-negative, and an underestimate of the actual |
| // element count. |
| |
| //===----------------------------------------------------------------------===// |
| // contains() |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix).contains()/WhereElementIsEquatable/semantics") { |
| for test in findTests { |
| let s = makeWrappedSequenceWithEquatableElement(test.sequence) |
| |
| expectEqual( |
| test.expected != nil, |
| s.contains(wrapValueIntoEquatable(test.element)), |
| stackTrace: SourceLocStack().with(test.loc)) |
| |
| if !isMultiPass { |
| expectEqualSequence( |
| test.expectedLeftoverSequence, s.map(extractValueFromEquatable), |
| stackTrace: SourceLocStack().with(test.loc)) |
| } |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // dropFirst() |
| //===----------------------------------------------------------------------===// |
| self.test("\(testNamePrefix).dropFirst/semantics") { |
| for test in dropFirstTests { |
| let s = makeWrappedSequence(test.sequence.map(OpaqueValue.init)) |
| let result = s.dropFirst(test.dropElements) |
| expectEqualSequence( |
| test.expected, result.map { extractValue($0).value }, |
| stackTrace: SourceLocStack().with(test.loc)) |
| } |
| } |
| |
| self.test("\(testNamePrefix).dropFirst/semantics/equivalence") { |
| // Calling dropFirst(1) twice on a sequence should be the same as |
| // calling dropFirst(2) once on an equivalent sequence. |
| if true { |
| let s1 = makeWrappedSequence([1010, 2020, 3030, 4040].map(OpaqueValue.init)) |
| let s2 = makeWrappedSequence([1010, 2020, 3030, 4040].map(OpaqueValue.init)) |
| |
| let result0 = s1.dropFirst(1) |
| let result1 = result0.dropFirst(1) |
| let result2 = s2.dropFirst(2) |
| |
| expectEqualSequence( |
| result1.map { extractValue($0).value }, |
| result2.map { extractValue($0).value } |
| ) |
| } |
| } |
| |
| self.test("\(testNamePrefix).dropFirst/semantics/dropFirst()==dropFirst(1)") { |
| let s1 = makeWrappedSequence([1010, 2020, 3030].map(OpaqueValue.init)) |
| let s2 = makeWrappedSequence([1010, 2020, 3030].map(OpaqueValue.init)) |
| |
| let result1 = s1.dropFirst() |
| let result2 = s2.dropFirst(1) |
| |
| expectEqualSequence( |
| result1.map { extractValue($0).value }, |
| result2.map { extractValue($0).value } |
| ) |
| } |
| |
| self.test("\(testNamePrefix).dropFirst/semantics/negative") { |
| let s = makeWrappedSequence([1010, 2020, 3030].map(OpaqueValue.init)) |
| expectCrashLater() |
| _ = s.dropFirst(-1) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // dropLast() |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix).dropLast/semantics") { |
| for test in dropLastTests { |
| let s = makeWrappedSequence(test.sequence.map(OpaqueValue.init)) |
| let result = s.dropLast(test.dropElements) |
| expectEqualSequence(test.expected, result.map { extractValue($0).value }, |
| stackTrace: SourceLocStack().with(test.loc)) |
| } |
| } |
| |
| self.test("\(testNamePrefix).dropLast/semantics/equivalence") { |
| // Calling `dropLast(2)` twice on a sequence is equivalent to calling |
| // `dropLast(4)` once. |
| if true { |
| let s1 = makeWrappedSequence( |
| [1010, 2020, 3030, 4040, 5050].map(OpaqueValue.init)) |
| let s2 = makeWrappedSequence( |
| [1010, 2020, 3030, 4040, 5050].map(OpaqueValue.init)) |
| |
| let droppedOnce = s1.dropLast(4) |
| |
| // FIXME: this line should read: |
| // |
| // let droppedTwice_ = s2.dropLast(2).dropLast(2) |
| // |
| // We can change it when we have real default implementations in protocols |
| // that don't affect regular name lookup. |
| let droppedTwice_ = s2.dropLast(2) |
| let droppedTwice = droppedTwice_.dropLast(2) |
| |
| expectEqualSequence(droppedOnce, droppedTwice) { |
| extractValue($0).value == extractValue($1).value |
| } |
| } |
| } |
| |
| self.test("\(testNamePrefix).dropLast/semantics/negative") { |
| let s = makeWrappedSequence([1010, 2020, 3030].map(OpaqueValue.init)) |
| expectCrashLater() |
| _ = s.dropLast(-1) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // drop(while:) |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix).drop(while:)/semantics").forEach(in: findTests) { |
| test in |
| let s = makeWrappedSequenceWithEquatableElement(test.sequence) |
| let closureLifetimeTracker = LifetimeTracked(0) |
| let remainingSequence = s.drop { |
| _blackHole(closureLifetimeTracker) |
| return $0 != wrapValueIntoEquatable(test.element) |
| } |
| let remaining = Array(remainingSequence) |
| let expectedSuffix = test.sequence.suffix( |
| from: test.expected ?? test.sequence.endIndex) |
| expectEqual(expectedSuffix.count, remaining.count) |
| expectEqualSequence(expectedSuffix.map(wrapValueIntoEquatable), remaining) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // prefix() |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix).prefix/semantics") { |
| for test in prefixTests { |
| let s = makeWrappedSequence(test.sequence.map(OpaqueValue.init)) |
| let result = s.prefix(test.maxLength) |
| expectEqualSequence(test.expected, result.map { extractValue($0).value }, |
| stackTrace: SourceLocStack().with(test.loc)) |
| } |
| } |
| |
| self.test("\(testNamePrefix).prefix/semantics/equivalence") { |
| // Calling `prefix(3)` on a sequence twice in a row should be the same |
| // as calling it once. |
| let expected = [ |
| 1010, 2020, 3030, 4040, 5050, |
| 6060, 7070, 8080, 9090, 10010 |
| ].map(OpaqueValue.init) |
| |
| let s1 = makeWrappedSequence(expected) |
| let s2 = makeWrappedSequence(expected) |
| |
| let prefixedOnce = s1.prefix(3) |
| let temp = s2.prefix(3) |
| let prefixedTwice = temp.prefix(3) |
| |
| expectEqualSequence(prefixedOnce, prefixedTwice) { |
| extractValue($0).value == extractValue($1).value |
| } |
| } |
| |
| self.test("\(testNamePrefix).prefix/semantics/negative") { |
| let s = makeWrappedSequence([1010, 2020, 3030].map(OpaqueValue.init)) |
| expectCrashLater() |
| _ = s.prefix(-1) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // prefix(while:) |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix).prefix(while:)/semantics").forEach(in: findTests) { |
| test in |
| let s = makeWrappedSequenceWithEquatableElement(test.sequence) |
| let closureLifetimeTracker = LifetimeTracked(0) |
| let remainingSequence = s.prefix { |
| _blackHole(closureLifetimeTracker) |
| return $0 != wrapValueIntoEquatable(test.element) |
| } |
| let expectedPrefix = test.sequence.prefix( |
| upTo: test.expected ?? test.sequence.endIndex) |
| let remaining = Array(remainingSequence) |
| expectEqual(expectedPrefix.count, remaining.count) |
| expectEqualSequence(expectedPrefix.map(wrapValueIntoEquatable), remaining) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // suffix() |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix).suffix/semantics") { |
| for test in suffixTests { |
| let s = makeWrappedSequence(test.sequence.map(OpaqueValue.init)) |
| let result = s.suffix(test.maxLength) |
| expectEqualSequence(test.expected, result.map { extractValue($0).value }, |
| stackTrace: SourceLocStack().with(test.loc)) |
| } |
| } |
| |
| self.test("\(testNamePrefix).suffix/semantics/equivalence") { |
| // Calling `suffix(3)` on a sequence twice in a row should be the same |
| // as calling it once. |
| let expected = [ |
| 1010, 2020, 3030, 4040, 5050, |
| 6060, 7070, 8080, 9090, 10010 |
| ].map(OpaqueValue.init) |
| |
| let s1 = makeWrappedSequence(expected) |
| let s2 = makeWrappedSequence(expected) |
| |
| let prefixedOnce = s1.suffix(3) |
| let temp = s2.suffix(3) |
| let prefixedTwice = temp.prefix(3) |
| |
| expectEqualSequence(prefixedOnce, prefixedTwice) { |
| extractValue($0).value == extractValue($1).value |
| } |
| } |
| |
| self.test("\(testNamePrefix).suffix/semantics/negative") { |
| let s = makeWrappedSequence([1010, 2020, 3030].map(OpaqueValue.init)) |
| expectCrashLater() |
| _ = s.suffix(-1) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // split() |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix).split/closure/semantics") { |
| for test in splitTests { |
| let closureLifetimeTracker = LifetimeTracked(0) |
| expectEqual(1, LifetimeTracked.instances) |
| let s: S = makeWrappedSequence(test.sequence.map(OpaqueValue.init)) |
| let result = s.split( |
| maxSplits: test.maxSplits, |
| omittingEmptySubsequences: test.omittingEmptySubsequences) { |
| _blackHole(closureLifetimeTracker) |
| return extractValue($0).value == test.separator |
| } |
| expectEqualSequence(test.expected, result.map { |
| $0.map { |
| extractValue($0).value |
| } |
| }, |
| stackTrace: SourceLocStack().with(test.loc)) { $0 == $1 } |
| } |
| } |
| |
| self.test("\(testNamePrefix).split/separator/semantics") { |
| for test in splitTests { |
| let s = makeWrappedSequenceWithEquatableElement( |
| test.sequence.map(MinimalEquatableValue.init) |
| ) |
| let separator = wrapValueIntoEquatable(MinimalEquatableValue(test.separator)) |
| let result = s.split( |
| separator: separator, |
| maxSplits: test.maxSplits, |
| omittingEmptySubsequences: test.omittingEmptySubsequences) |
| expectEqualSequence( |
| test.expected, |
| result.map { |
| $0.map { |
| extractValueFromEquatable($0).value |
| } |
| }, |
| stackTrace: SourceLocStack().with(test.loc)) { $0 == $1 } |
| } |
| } |
| |
| self.test("\(testNamePrefix).split/semantics/closure/negativeMaxSplit") { |
| let s = makeWrappedSequenceWithEquatableElement([MinimalEquatableValue(1)]) |
| let separator = MinimalEquatableValue(1) |
| expectCrashLater() |
| _ = s.split( |
| maxSplits: -1, |
| omittingEmptySubsequences: false) { extractValueFromEquatable($0) == separator } |
| } |
| |
| self.test("\(testNamePrefix).split/semantics/separator/negativeMaxSplit") { |
| let s = makeWrappedSequenceWithEquatableElement([MinimalEquatableValue(1)]) |
| let separator = wrapValueIntoEquatable(MinimalEquatableValue(1)) |
| expectCrashLater() |
| _ = s.split(separator: separator, maxSplits: -1, omittingEmptySubsequences: false) |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // forEach() |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix).forEach/semantics") { |
| for test in forEachTests { |
| var elements: [Int] = [] |
| let closureLifetimeTracker = LifetimeTracked(0) |
| let s = makeWrappedSequence(test.sequence.map(OpaqueValue.init)) |
| s.forEach { |
| (element) in |
| _blackHole(closureLifetimeTracker) |
| elements.append(extractValue(element).value) |
| } |
| expectEqualSequence( |
| test.sequence, elements, |
| stackTrace: SourceLocStack().with(test.loc)) |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // first() |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix).first/semantics") { |
| for test in findTests { |
| let s = makeWrappedSequenceWithEquatableElement(test.sequence) |
| let closureLifetimeTracker = LifetimeTracked(0) |
| let found = s.first { |
| _blackHole(closureLifetimeTracker) |
| return $0 == wrapValueIntoEquatable(test.element) |
| } |
| expectEqual( |
| test.expected == nil ? nil : wrapValueIntoEquatable(test.element), |
| found, |
| stackTrace: SourceLocStack().with(test.loc)) |
| if let expectedIdentity = test.expected { |
| expectEqual( |
| expectedIdentity, extractValueFromEquatable(found!).identity, |
| "find() should find only the first element matching its predicate") |
| } |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // _preprocessingPass() |
| //===----------------------------------------------------------------------===// |
| |
| self.test("\(testNamePrefix)._preprocessingPass/semantics") { |
| for test in forEachTests { |
| let s = makeWrappedSequence(test.sequence.map(OpaqueValue.init)) |
| var wasInvoked = false |
| let result = s._preprocessingPass { |
| () -> OpaqueValue<Int> in |
| wasInvoked = true |
| |
| expectEqualSequence( |
| test.sequence, |
| s.map { extractValue($0).value }) |
| |
| return OpaqueValue(42) |
| } |
| if wasInvoked { |
| expectOptionalEqual(42, result?.value) |
| } else { |
| expectNil(result) |
| } |
| } |
| |
| for test in forEachTests { |
| let s = makeWrappedSequence(test.sequence.map(OpaqueValue.init)) |
| var wasInvoked = false |
| var caughtError: Error? |
| var result: OpaqueValue<Int>? |
| do { |
| result = try s._preprocessingPass { |
| () -> OpaqueValue<Int> in |
| wasInvoked = true |
| throw TestError.error2 |
| } |
| } catch { |
| caughtError = error |
| } |
| expectNil(result) |
| if wasInvoked { |
| expectOptionalEqual(TestError.error2, caughtError as? TestError) |
| } |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| } // addSequenceTests |
| } |