//===--- ExistentialCollection.swift.gyb ----------------------*- swift -*-===// // // 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 // //===----------------------------------------------------------------------===// // RUN: %target-run-simple-swiftgyb // REQUIRES: executable_test // With a non-optimized stdlib the test takes very long. // REQUIRES: optimized_stdlib %{ from gyb_stdlib_support import ( TRAVERSALS, collectionForTraversal ) }% import StdlibUnittest import StdlibCollectionUnittest // Check that the generic parameter is called 'Element'. protocol TestProtocol1 {} extension AnyIterator where Element : TestProtocol1 { var _elementIsTestProtocol1: Bool { fatalError("not implemented") } } extension AnySequence where Element : TestProtocol1 { var _elementIsTestProtocol1: Bool { fatalError("not implemented") } } extension AnyCollection where Element : TestProtocol1 { var _elementIsTestProtocol1: Bool { fatalError("not implemented") } } extension AnyBidirectionalCollection where Element : TestProtocol1 { var _elementIsTestProtocol1: Bool { fatalError("not implemented") } } extension AnyRandomAccessCollection where Element : TestProtocol1 { var _elementIsTestProtocol1: Bool { fatalError("not implemented") } } func storesSameUnderlyingCollection< L: _AnyCollectionProtocol, R: _AnyCollectionProtocol >(_ lhs: L, _ rhs: R) -> Bool { return lhs._boxID == rhs._boxID } var tests = TestSuite("ExistentialCollection") tests.test("AnyIterator") { func digits() -> AnyIterator> { let integers: CountableRange = 0..<5 let lazyStrings = integers.lazy.map { OpaqueValue($0) } // This is a really complicated type of no interest to our // clients. let iterator: LazyMapSequence< CountableRange, OpaqueValue >.Iterator = lazyStrings.makeIterator() return AnyIterator(iterator) } expectEqual([0, 1, 2, 3, 4], Array(digits()).map { $0.value }) var x = 7 let iterator = AnyIterator { if x >= 15 { return nil } x += 1 return x-1 } expectEqual([ 7, 8, 9, 10, 11, 12, 13, 14 ], Array(iterator)) } tests.test("AnySequence.init(Sequence)") { do { let base = MinimalSequence>(elements: []) var s = AnySequence(base) expectType(AnySequence>.self, &s) checkSequence([], s, resiliencyChecks: .none) { $0.value == $1.value } } do { let intData = [ 1, 2, 3, 5, 8, 13, 21 ] let data = intData.map(OpaqueValue.init) let base = MinimalSequence(elements: data) var s = AnySequence(base) expectType(AnySequence>.self, &s) checkSequence(data, s, resiliencyChecks: .none) { $0.value == $1.value } } } tests.test("AnySequence.init(() -> Generator)") { do { var s = AnySequence { return MinimalIterator>([]) } expectType(AnySequence>.self, &s) checkSequence([], s, resiliencyChecks: .none) { $0.value == $1.value } } do { let intData = [ 1, 2, 3, 5, 8, 13, 21 ] let data = intData.map(OpaqueValue.init) var s = AnySequence { return MinimalIterator(data) } expectType(AnySequence>.self, &s) checkSequence(data, s, resiliencyChecks: .none) { $0.value == $1.value } } } % for Traversal in ['Sequence'] + TRAVERSALS: % if Traversal == 'Sequence': % TestedType = 'AnySequence' % LoggingWrapper = 'LoggingSequence' % MinimalBase = 'MinimalSequence' % else: % TestedType = 'Any' + collectionForTraversal(Traversal) % LoggingWrapper = 'Logging' + collectionForTraversal(Traversal) % MinimalBase = 'Minimal' + collectionForTraversal(Traversal) % end tests.test("${TestedType}: dispatch to wrapped, SequenceLog") { typealias Base = ${LoggingWrapper}<${MinimalBase}>> typealias Log = SequenceLog let base = Base(wrapping: ${MinimalBase}(elements: (0..<10).map(OpaqueValue.init))) var s = ${TestedType}(base) expectType(${TestedType}>.self, &s) Log.makeIterator.expectIncrement(Base.self) { _ = s.makeIterator() } Log.underestimatedCount.expectIncrement(Base.self) { _ = s.underestimatedCount } Log._customContainsEquatableElement.expectIncrement(Base.self) { _ = s._customContainsEquatableElement(OpaqueValue(42)) } Log._copyToContiguousArray.expectIncrement(Base.self) { _ = s._copyToContiguousArray() } do { var result = Array(repeating: OpaqueValue(0), count: 10) Log._copyContents.expectIncrement(Base.self) { result.withUnsafeMutableBufferPointer { _ = s._copyContents(initializing: $0) } } } } % if Traversal != 'Sequence': tests.test("${TestedType}: dispatch to wrapped, CollectionLog") { typealias Base = ${LoggingWrapper}<${MinimalBase}>> typealias Log = CollectionLog let base = Base(wrapping: ${MinimalBase}(elements: (0..<10).map(OpaqueValue.init))) var c = ${TestedType}(base) expectType(${TestedType}>.self, &c) do { var i = c.startIndex // `startIndex` is cached in the type erased wrapper, so first mutation // makes a unique copy. Log.successor.expectIncrement(Base.self) { Log.formSuccessor.expectUnchanged(Base.self) { c.formIndex(after: &i) } } Log.successor.expectUnchanged(Base.self) { Log.formSuccessor.expectIncrement(Base.self) { c.formIndex(after: &i) } } } % if Traversal in ['Bidirectional', 'RandomAccess']: do { typealias Log = BidirectionalCollectionLog var i = c.endIndex // `startIndex` is cached in the type erased wrapper, so first mutation // makes a unique copy. Log.predecessor.expectIncrement(Base.self) { Log.formPredecessor.expectUnchanged(Base.self) { c.formIndex(before: &i) } } Log.predecessor.expectUnchanged(Base.self) { Log.formPredecessor.expectIncrement(Base.self) { c.formIndex(before: &i) } } } % end do { let startIndex = c.startIndex var badBounds = c.index(c.startIndex, offsetBy: 3)..]) -> ${AnyCollection}> { let base = ${Base}(elements: elements) return ${AnyCollection}(base) } func makeCollectionOfEquatable(elements: [MinimalEquatableValue]) -> ${AnyCollection} { let base = ${Base}(elements: elements) return ${AnyCollection}(base) } func makeCollectionOfComparable(elements: [MinimalComparableValue]) -> ${AnyCollection} { let base = ${Base}(elements: elements) return ${AnyCollection}(base) } AnyCollectionTests.add${collectionForTraversal(Traversal)}Tests( "tests.", makeCollection: makeCollection, wrapValue: identity, extractValue: identity, makeCollectionOfEquatable: makeCollectionOfEquatable, wrapValueIntoEquatable: identityEq, extractValueFromEquatable: identityEq, resiliencyChecks: CollectionMisuseResiliencyChecks.all, collectionIsBidirectional: ${'false' if Traversal == 'Forward' else 'true'} ) } % end runAllTests()