// -*- swift -*- // RUN: rm -rf %t ; mkdir -p %t // RUN: %S/../../utils/gyb %s -o %t/Slice.swift // RUN: %S/../../utils/line-directive %t/Slice.swift -- %target-build-swift %t/Slice.swift -o %t/a.out // RUN: %S/../../utils/line-directive %t/Slice.swift -- %target-run %t/a.out // REQUIRES: executable_test import StdlibUnittest import StdlibCollectionUnittest import SwiftPrivate // Also import modules which are used by StdlibUnittest internally. This // workaround is needed to link all required libraries in case we compile // StdlibUnittest with -sil-serialize-all. #if _runtime(_ObjC) import ObjectiveC #endif var SliceTests = TestSuite("Collection") //===----------------------------------------------------------------------===// // Slice //===----------------------------------------------------------------------===// SliceTests.test("Slice/AssociatedTypes") { %for traversal in [ 'Forward', 'Bidirectional', 'RandomAccess' ]: do { typealias Base = Minimal${traversal}Collection> typealias ${traversal}Slice = Slice expectSliceType(${traversal}Slice.self) expectCollectionAssociatedTypes( collectionType: ${traversal}Slice.self, iteratorType: IndexingIterator<${traversal}Slice>.self, subSequenceType: ${traversal}Slice.self, indexType: Minimal${traversal}Index.self) } %end func checkStaticTypealiases(_: Base) { expectEqualType(Base.Index.self, Slice.Index.self) } } SliceTests.test("Slice/init(_base:bounds:)") { for test in subscriptRangeTests { let base = MinimalForwardCollection(elements: test.collection) var result = Slice(_base: base, bounds: test.boundsIn(base)) expectType( Slice>>.self, &result) checkForwardCollection( test.expected, result, stackTrace: SourceLocStack().with(test.loc)) { $0.value == $1.value } } } SliceTests.test("Slice.{startIndex,endIndex}") { for test in subscriptRangeTests { let base = MinimalForwardCollection(elements: test.collection) let bounds = test.boundsIn(base) var slice = Slice(_base: base, bounds: bounds) expectType( Slice>>.self, &slice) expectEqual(bounds.startIndex, slice.startIndex) expectEqual(bounds.endIndex, slice.endIndex) } } SliceTests.test("Slice.subscript(_: Index)") { for test in subscriptRangeTests { typealias Base = MinimalForwardCollection> Base.Index.trapOnRangeCheckFailure.value = false let base = Base(elements: test.collection) let bounds = test.boundsIn(base) var slice = Slice(_base: base, bounds: bounds) expectType(Slice.self, &slice) for i in bounds { var element = slice[i] expectType(OpaqueValue.self, &element) expectEqual(base[i].value, element.value) } for (i, index) in base.indices.enumerated() { if test.bounds.contains(i) { expectEqual(base[index].value, slice[index].value) } else { // `Slice` disallows out-of-bounds indices when the underlying index // type can perform a range check. expectFailure { _blackHole(slice[index]) } } } } } SliceTests.test("Slice.subscript(_: Range)") { for test in subscriptRangeTests { typealias Base = MinimalForwardCollection> Base.Index.trapOnRangeCheckFailure.value = false let base = Base(elements: test.collection) var slice = Slice(_base: base, bounds: base.indices) expectType(Slice.self, &slice) var result = slice[test.boundsIn(slice)] expectType(Slice.self, &result) checkForwardCollection(test.expected, result) { $0.value == $1.value } if test.bounds == test.collection.indices { let reSliced = result[base.indices] checkForwardCollection( test.collection, reSliced, stackTrace: SourceLocStack().with(test.loc)) { $0.value == $1.value } } else { // `Slice` disallows out-of-bounds slicing when the underlying index type // can perform a range check. expectFailure { _blackHole(result[base.indices]) } } } } //===----------------------------------------------------------------------===// // MutableSlice //===----------------------------------------------------------------------===// SliceTests.test("MutableSlice/AssociatedTypes") { %for traversal in [ 'Forward', 'Bidirectional', 'RandomAccess' ]: do { typealias Base = Minimal${traversal}MutableCollection> typealias ${traversal}MutableSlice = MutableSlice expectMutableSliceType(${traversal}MutableSlice.self) expectCollectionAssociatedTypes( collectionType: ${traversal}MutableSlice.self, iteratorType: IndexingIterator<${traversal}MutableSlice>.self, subSequenceType: ${traversal}MutableSlice.self, indexType: Minimal${traversal}Index.self) } %end func checkStaticTypealiases< Base : MutableCollection >(_: Base) { expectEqualType(Base.Index.self, MutableSlice.Index.self) } } /* FIXME: uncomment this test when the following bug is fixed: Recast Slice and MutableSlice in terms of Collection and MutableCollection extension MutableSlice { func _checkBaseSubSequenceElementIsElement() { Element.self, Iterator.Element.self) expectEqualType( Element.self, Iterator.Element.self, Base.Iterator.Element.self) expectEqualType( Element.self, Iterator.Element.self, Base.SubSequence.Iterator.Element.self) } } */ SliceTests.test("MutableSlice/init(_base:bounds:)") { for test in subscriptRangeTests { let c = MinimalForwardMutableCollection(elements: test.collection) var result = MutableSlice(_base: c, bounds: test.boundsIn(c)) expectType( MutableSlice>>.self, &result) checkForwardCollection( test.expected, result, stackTrace: SourceLocStack().with(test.loc)) { $0.value == $1.value } } } SliceTests.test("MutableSlice.{startIndex,endIndex}") { for test in subscriptRangeTests { let c = MinimalForwardMutableCollection(elements: test.collection) let bounds = test.boundsIn(c) var slice = MutableSlice(_base: c, bounds: bounds) expectType( MutableSlice>>.self, &slice) expectEqual(bounds.startIndex, slice.startIndex) expectEqual(bounds.endIndex, slice.endIndex) } } SliceTests.test("MutableSlice.subscript(_: Index)/{get,set}") { for test in subscriptRangeTests { typealias Base = MinimalForwardMutableCollection> Base.Index.trapOnRangeCheckFailure.value = false let base = Base(elements: test.collection) let bounds = test.boundsIn(base) var slice = MutableSlice(_base: base, bounds: bounds) expectType(MutableSlice.self, &slice) for i in bounds { // Test getter. var element = slice[i] expectType(OpaqueValue.self, &element) expectEqual(base[i].value, element.value) } do { var sliceForSetter = slice for i in bounds { // Test setter. sliceForSetter[i].value += 1 expectEqual(base[i].value + 1, sliceForSetter[i].value) } } var sliceForSetter = slice for (i, index) in base.indices.enumerated() { if test.bounds.contains(i) { // Test getter. expectEqual(base[index].value, slice[index].value) // Test setter. sliceForSetter[index].value += 1 expectEqual(base[index].value + 1, sliceForSetter[index].value) } else { // `MutableSlice` disallows out-of-bounds indices when the underlying // index type can perform a range check. // Test getter. expectFailure { _blackHole(slice[index]) } // Test setter. expectFailure { sliceForSetter[index].value += 1 } } } // Check that none of the mutations above affected the original collection. expectEqualSequence(test.collection, base) { $0.value == $1.value } } } runAllTests()