mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Array tests: split Objective-C-independent tests into a new file
And also merge the small test/1_stdlib/ArrayCore.swift test into it.
This commit is contained in:
@@ -48,447 +48,6 @@ extension ContiguousArray {
|
||||
|
||||
var ArrayTestSuite = TestSuite("Array")
|
||||
|
||||
ArrayTestSuite.test("sizeof") {
|
||||
var a = [ 10, 20, 30 ]
|
||||
#if arch(i386) || arch(arm)
|
||||
expectEqual(4, sizeofValue(a))
|
||||
#else
|
||||
expectEqual(8, sizeofValue(a))
|
||||
#endif
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("valueDestruction") {
|
||||
var a = [TestValueTy]()
|
||||
for i in 100...110 {
|
||||
a.append(TestValueTy(i))
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Native array tests
|
||||
// FIXME: incomplete.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ArrayTestSuite.test("Native/count/empty") {
|
||||
let a = [TestValueTy]()
|
||||
expectEqual(0, a.count)
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("Native/count") {
|
||||
let a = [ TestValueTy(10), TestValueTy(20), TestValueTy(30) ]
|
||||
expectEqual(3, a.count)
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("Native/isEmpty/empty") {
|
||||
let a = [TestValueTy]()
|
||||
expectTrue(a.isEmpty)
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("Native/isEmpty") {
|
||||
let a = [ TestValueTy(10), TestValueTy(20), TestValueTy(30) ]
|
||||
expectFalse(a.isEmpty)
|
||||
}
|
||||
|
||||
protocol TestProtocol1 {}
|
||||
|
||||
% for array_type in all_array_types:
|
||||
|
||||
// Check that the generic parameter is called 'Element'.
|
||||
extension ${array_type} where Element : TestProtocol1 {
|
||||
var _elementIsTestProtocol1: Bool {
|
||||
fatalError("not implemented")
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an ${array_type} that does not share its buffer with other arrays.
|
||||
func getFresh${array_type}<S : Sequence>(sequence: S)
|
||||
-> ${array_type}<S.Iterator.Element> {
|
||||
var result: ${array_type}<S.Iterator.Element> = []
|
||||
result.reserveCapacity(sequence.underestimatedCount)
|
||||
for element in sequence {
|
||||
result.append(element)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
% end
|
||||
|
||||
enum EnumWithoutPayloads : Equatable {
|
||||
case A, B, C, D
|
||||
}
|
||||
|
||||
func == (lhs: EnumWithoutPayloads, rhs: EnumWithoutPayloads) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.A, .A), (.B, .B), (.C, .C), (.D, .D):
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
struct SequenceWithCustomUnderestimatedCount : Sequence {
|
||||
init(_ data: [Int]) {
|
||||
self._data = MinimalSequence(elements: data.map(OpaqueValue.init))
|
||||
}
|
||||
|
||||
func makeIterator() -> MinimalSequence<OpaqueValue<Int>>.Iterator {
|
||||
return _data.makeIterator()
|
||||
}
|
||||
|
||||
var underestimatedCount: Int {
|
||||
SequenceWithCustomUnderestimatedCount.timesUnderestimatedCountWasCalled += 1
|
||||
return _data.underestimatedCount
|
||||
}
|
||||
|
||||
static var timesUnderestimatedCountWasCalled: Int = 0
|
||||
|
||||
let _data: MinimalSequence<OpaqueValue<Int>>
|
||||
}
|
||||
|
||||
% for array_type in all_array_types:
|
||||
|
||||
ArrayTestSuite.test("${array_type}/init(Sequence)") {
|
||||
let base = SequenceWithCustomUnderestimatedCount(
|
||||
[ 0, 30, 10, 90 ])
|
||||
|
||||
SequenceWithCustomUnderestimatedCount.timesUnderestimatedCountWasCalled = 0
|
||||
|
||||
let result = ${array_type}(base)
|
||||
|
||||
expectEqual([ 0, 30, 10, 90 ], result.map { $0.value })
|
||||
|
||||
expectEqual(1, SequenceWithCustomUnderestimatedCount.timesUnderestimatedCountWasCalled)
|
||||
|
||||
expectEqualSequence(
|
||||
[], Array(base).map { $0.value }, "sequence should be consumed")
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("${array_type}/Sliceable/Enums") {
|
||||
typealias E = EnumWithoutPayloads
|
||||
|
||||
do {
|
||||
let expected = [ E.A, E.B, E.C, E.D ]
|
||||
let sliceable = ${array_type}(expected)
|
||||
checkSliceableWithBidirectionalIndex(expected, sliceable)
|
||||
}
|
||||
|
||||
/*
|
||||
FIXME: add this test when Array<T> can be conditionally Equatable.
|
||||
do {
|
||||
let expected = [ [ E.A, E.B ], [ E.B, E.C ], [ E.D ], [ E.A, E.B, E.D ] ]
|
||||
let sliceable = ${array_type}(expected)
|
||||
checkSliceableWithBidirectionalIndex(
|
||||
expected, sliceable, SourceLocStack().withCurrentLoc())
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("${array_type}/appendNonUnique") {
|
||||
var x: ${array_type}<Int> = []
|
||||
x.reserveCapacity(10002)
|
||||
let capacity = x.capacity
|
||||
for _ in 1...10000 {
|
||||
let y = x
|
||||
x.append(1)
|
||||
expectTrue(x.capacity == capacity)
|
||||
let z = x
|
||||
x.remove(at: 0)
|
||||
}
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("${array_type}/emptyAllocation") {
|
||||
let arr0 = ${array_type}<Int>()
|
||||
let arr1 = ${array_type}<TestValueTy>(repeating: TestValueTy(0), count: 0)
|
||||
// Empty arrays all use the same buffer
|
||||
expectEqual(arr0._buffer.identity, arr1._buffer.identity)
|
||||
|
||||
let hasNilBuffer = arr1.identity == nil
|
||||
expectFalse(hasNilBuffer)
|
||||
|
||||
let arr2: ${array_type}<TestValueTy> = []
|
||||
let emptyLiteralsShareBuffer = arr0._buffer.identity == arr2._buffer.identity
|
||||
expectTrue(emptyLiteralsShareBuffer)
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("${array_type}/filter") {
|
||||
do {
|
||||
let arr: ${array_type}<Int> = []
|
||||
var result = arr.filter() {
|
||||
(x: Int) -> Bool in
|
||||
expectUnreachable()
|
||||
return true
|
||||
}
|
||||
expectType(Array<Int>.self, &result)
|
||||
expectEqual([], result)
|
||||
expectEqual(0, result.capacity)
|
||||
}
|
||||
do {
|
||||
let arr: ${array_type}<Int> = [ 0, 30, 10, 90 ]
|
||||
let result = arr.filter() { (x: Int) -> Bool in true }
|
||||
expectEqual([ 0, 30, 10, 90 ], result)
|
||||
expectGE(2 * result.count, result.capacity)
|
||||
}
|
||||
do {
|
||||
let arr: ${array_type}<Int> = [ 0, 30, 10, 90 ]
|
||||
let result = arr.filter() { (x: Int) -> Bool in false }
|
||||
expectEqual([], result)
|
||||
expectGE(2 * result.count, result.capacity)
|
||||
}
|
||||
do {
|
||||
let arr: ${array_type}<Int> = [ 0, 30, 10, 90 ]
|
||||
let result = arr.filter() { $0 % 3 == 0 }
|
||||
expectEqual([ 0, 30, 90 ], result)
|
||||
expectGE(2 * result.count, result.capacity)
|
||||
}
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("${array_type}/map") {
|
||||
do {
|
||||
let arr: ${array_type}<Int> = []
|
||||
var result = arr.map() {
|
||||
(x: Int) -> Int16 in
|
||||
expectUnreachable()
|
||||
return 42
|
||||
}
|
||||
expectType(Array<Int16>.self, &result)
|
||||
expectEqual([], result)
|
||||
expectEqual(0, result.capacity)
|
||||
}
|
||||
do {
|
||||
let arr: ${array_type}<Int> = [ 0, 30, 10, 90 ]
|
||||
let result = arr.map() { $0 + 1 }
|
||||
expectEqual([ 1, 31, 11, 91 ], result)
|
||||
expectGE(2 * result.count, result.capacity)
|
||||
}
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("${array_type}/flatMap") {
|
||||
let enumerate : Int -> ${array_type}<Int> =
|
||||
{ return ${array_type}(1..<($0 + 1)) }
|
||||
expectEqualSequence([], ${array_type}().flatMap(enumerate))
|
||||
expectEqualSequence([ 1 ], ${array_type}([ 1 ]).flatMap(enumerate))
|
||||
expectEqualSequence(
|
||||
[ 1, 1, 2 ],
|
||||
${array_type}([ 1, 2 ]).flatMap(enumerate))
|
||||
expectEqualSequence(
|
||||
[ 1, 1, 1, 2 ],
|
||||
${array_type}([ 1, 2 ]).flatMap(enumerate).flatMap(enumerate))
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("${array_type}/Mirror") {
|
||||
do {
|
||||
let input: ${array_type}<Int> = []
|
||||
var output = ""
|
||||
dump(input, to: &output)
|
||||
|
||||
let expected =
|
||||
"- 0 elements\n"
|
||||
|
||||
expectEqual(expected, output)
|
||||
}
|
||||
do {
|
||||
let input: ${array_type}<Int> = [ 10, 20, 30, 40 ]
|
||||
var output = ""
|
||||
dump(input, to: &output)
|
||||
|
||||
let expected =
|
||||
"▿ 4 elements\n" +
|
||||
" - 10\n" +
|
||||
" - 20\n" +
|
||||
" - 30\n" +
|
||||
" - 40\n"
|
||||
|
||||
expectEqual(expected, output)
|
||||
}
|
||||
% if array_type == 'ArraySlice':
|
||||
do {
|
||||
let base = [ 10, 20, 30, 40 ]
|
||||
let input: ArraySlice<Int> = base[1..<3]
|
||||
var output = ""
|
||||
dump(input, to: &output)
|
||||
|
||||
let expected =
|
||||
"▿ 2 elements\n" +
|
||||
" - 20\n" +
|
||||
" - 30\n"
|
||||
|
||||
expectEqual(expected, output)
|
||||
}
|
||||
% end
|
||||
}
|
||||
|
||||
% end
|
||||
|
||||
% for Kind in ['Array', 'ContiguousArray']:
|
||||
ArrayTestSuite.test("${Kind}/popLast") {
|
||||
// Empty
|
||||
do {
|
||||
var a = ${Kind}<Int>()
|
||||
let popped = a.popLast()
|
||||
expectEmpty(popped)
|
||||
expectTrue(a.isEmpty)
|
||||
}
|
||||
|
||||
do {
|
||||
var popped = [Int]()
|
||||
var a: ${Kind}<Int> = [1010, 2020, 3030]
|
||||
while let element = a.popLast() {
|
||||
popped.append(element)
|
||||
}
|
||||
expectEqualSequence([1010, 2020, 3030], popped.reversed())
|
||||
expectTrue(a.isEmpty)
|
||||
}
|
||||
}
|
||||
% end
|
||||
|
||||
// Check how removeFirst() affects indices.
|
||||
% for Kind in ['Array', 'ContiguousArray']:
|
||||
ArrayTestSuite.test("${Kind}/removeFirst") {
|
||||
do {
|
||||
var a: ${Kind}<OpaqueValue<Int>> = ${Kind}([ 1 ].map(OpaqueValue.init))
|
||||
a.removeFirst()
|
||||
expectEqual(0, a.startIndex)
|
||||
}
|
||||
do {
|
||||
var a: ${Kind}<OpaqueValue<Int>> = ${Kind}([ 1, 2 ].map(OpaqueValue.init))
|
||||
a.removeFirst()
|
||||
expectEqual(0, a.startIndex)
|
||||
}
|
||||
}
|
||||
% end
|
||||
|
||||
ArrayTestSuite.test("ArraySlice/removeFirst") {
|
||||
do {
|
||||
let a: [OpaqueValue<Int>] = [ 99, 1010, 99 ].map(OpaqueValue.init)
|
||||
var s = a[1..<2]
|
||||
expectEqual(1, s.startIndex)
|
||||
s.removeFirst()
|
||||
expectEqual(2, s.startIndex)
|
||||
}
|
||||
do {
|
||||
let a: [OpaqueValue<Int>] = [ 99, 1010, 2020, 99 ].map(OpaqueValue.init)
|
||||
var s = a[1..<2]
|
||||
expectEqual(1, s.startIndex)
|
||||
s.removeFirst()
|
||||
expectEqual(2, s.startIndex)
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// _withUnsafeMutableBufferPointerIfSupported()
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
struct WithUnsafeMutableBufferPointerIfSupportedTest {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
let withUnsafeMutableBufferPointerIfSupportedTests = [
|
||||
WithUnsafeMutableBufferPointerIfSupportedTest([]),
|
||||
WithUnsafeMutableBufferPointerIfSupportedTest([ 10 ]),
|
||||
WithUnsafeMutableBufferPointerIfSupportedTest([ 10, 20, 30, 40, 50 ]),
|
||||
]
|
||||
|
||||
% for array_type in all_array_types:
|
||||
|
||||
ArrayTestSuite.test("${array_type}/_withUnsafeMutableBufferPointerIfSupported") {
|
||||
for test in withUnsafeMutableBufferPointerIfSupportedTests {
|
||||
var a = getFresh${array_type}(test.sequence.map(OpaqueValue.init))
|
||||
do {
|
||||
// Read.
|
||||
var result = a._withUnsafeMutableBufferPointerIfSupported {
|
||||
(baseAddress, count) -> OpaqueValue<[OpaqueValue<Int>]> in
|
||||
let bufferPointer =
|
||||
UnsafeMutableBufferPointer(start: baseAddress, count: count)
|
||||
return OpaqueValue(Array(bufferPointer))
|
||||
}
|
||||
expectType(Optional<OpaqueValue<Array<OpaqueValue<Int>>>>.self, &result)
|
||||
expectEqualSequence(test.sequence, result!.value.map { $0.value })
|
||||
expectEqualSequence(test.sequence, a.map { $0.value })
|
||||
}
|
||||
do {
|
||||
// Read and write.
|
||||
var result = a._withUnsafeMutableBufferPointerIfSupported {
|
||||
(baseAddress, count) -> OpaqueValue<Array<OpaqueValue<Int>>> in
|
||||
let bufferPointer =
|
||||
UnsafeMutableBufferPointer(start: baseAddress, count: count)
|
||||
let result = OpaqueValue(Array(bufferPointer))
|
||||
for i in bufferPointer.indices {
|
||||
bufferPointer[i] = OpaqueValue(bufferPointer[i].value * 10)
|
||||
}
|
||||
return result
|
||||
}
|
||||
expectType(Optional<OpaqueValue<Array<OpaqueValue<Int>>>>.self, &result)
|
||||
expectEqualSequence(test.sequence, result!.value.map { $0.value })
|
||||
expectEqualSequence(
|
||||
test.sequence.map { $0 * 10 },
|
||||
a.map { $0.value })
|
||||
}
|
||||
}
|
||||
// FIXME: tests for arrays bridged from Objective-C.
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("${array_type}/_withUnsafeMutableBufferPointerIfSupported/ReplacingTheBufferTraps/1") {
|
||||
var a = getFresh${array_type}([ OpaqueValue(10) ])
|
||||
var result = a._withUnsafeMutableBufferPointerIfSupported {
|
||||
(baseAddress, count) -> OpaqueValue<Int> in
|
||||
// buffer = UnsafeMutableBufferPointer(start: buffer.baseAddress, count: 0)
|
||||
// FIXME: does not trap since the buffer is not passed inout.
|
||||
// expectCrashLater()
|
||||
return OpaqueValue(42)
|
||||
}
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("${array_type}/_withUnsafeMutableBufferPointerIfSupported/ReplacingTheBufferTraps/2") {
|
||||
var a = getFresh${array_type}([ OpaqueValue(10) ])
|
||||
var result = a._withUnsafeMutableBufferPointerIfSupported {
|
||||
(baseAddress, count) -> OpaqueValue<Int> in
|
||||
// buffer = UnsafeMutableBufferPointer(start: nil, count: 1)
|
||||
// FIXME: does not trap since the buffer is not passed inout.
|
||||
// expectCrashLater()
|
||||
return OpaqueValue(42)
|
||||
}
|
||||
}
|
||||
|
||||
//===---
|
||||
// Check that iterators traverse a snapshot of the collection.
|
||||
//===---
|
||||
|
||||
ArrayTestSuite.test(
|
||||
"${array_type}/mutationDoesNotAffectIterator/subscript/store") {
|
||||
var arr: ${array_type}<Int> = [ 1010, 1020, 1030 ]
|
||||
var iter = arr.makeIterator()
|
||||
arr[0] = 1011
|
||||
expectEqual([ 1010, 1020, 1030 ], Array(IteratorSequence(iter)))
|
||||
}
|
||||
|
||||
ArrayTestSuite.test(
|
||||
"${array_type}/mutationDoesNotAffectIterator/subscript/append") {
|
||||
var arr: ${array_type}<Int> = [ 1010, 1020, 1030 ]
|
||||
var iter = arr.makeIterator()
|
||||
arr.append(1040)
|
||||
expectEqual([ 1010, 1020, 1030 ], Array(IteratorSequence(iter)))
|
||||
}
|
||||
|
||||
ArrayTestSuite.test(
|
||||
"${array_type}/mutationDoesNotAffectIterator/subscript/replaceSubrange") {
|
||||
var arr: ${array_type}<Int> = [ 1010, 1020, 1030 ]
|
||||
var iter = arr.makeIterator()
|
||||
arr.replaceSubrange(1..<3, with: [ 1040, 1050, 1060 ])
|
||||
expectEqual([ 1010, 1020, 1030 ], Array(IteratorSequence(iter)))
|
||||
}
|
||||
|
||||
% end
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// COW tests
|
||||
// FIXME: incomplete.
|
||||
@@ -1574,189 +1133,6 @@ ArrayTestSuite.test("BridgedToObjC.Nonverbatim.RoundtripThroughSwiftArray") {
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Array and EvilCollection that changes its size while we are not looking
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let evilBoundsError = "EvilCollection: index out of range"
|
||||
|
||||
final class EvilCollection : Collection {
|
||||
init(_ growth: Int, boundsChecked: Bool) {
|
||||
self.growth = growth
|
||||
self.boundsChecked = boundsChecked
|
||||
}
|
||||
|
||||
var growth: Int
|
||||
var _count: Int = 20
|
||||
var boundsChecked: Bool
|
||||
|
||||
var startIndex : Int {
|
||||
_count += growth
|
||||
return 0
|
||||
}
|
||||
|
||||
var endIndex : Int {
|
||||
return _count
|
||||
}
|
||||
|
||||
subscript(i: Int) -> TestValueTy {
|
||||
if boundsChecked {
|
||||
precondition(i >= 0 && i < _count, evilBoundsError)
|
||||
}
|
||||
return TestValueTy(i)
|
||||
}
|
||||
}
|
||||
|
||||
for (step, evilBoundsCheck) in [ (1, true), (-1, false), (-1, true) ] {
|
||||
|
||||
let message = step < 0 && evilBoundsCheck
|
||||
? evilBoundsError
|
||||
: "invalid Collection: count differed in successive traversals"
|
||||
|
||||
let constructionMessage =
|
||||
/*_isStdlibInternalChecksEnabled() && !evilBoundsCheck && step <= 0
|
||||
? "_UnsafePartiallyInitializedContiguousArrayBuffer has no more capacity"
|
||||
:*/ message
|
||||
|
||||
// The invalid Collection error is a _debugPreconditon that will only fire
|
||||
// in a Debug assert configuration.
|
||||
let expectedToFail = (step < 0 && evilBoundsCheck) ||
|
||||
_isDebugAssertConfiguration()
|
||||
|
||||
let natureOfEvil = step > 0 ? "Growth" : "Shrinkage"
|
||||
let boundsChecked = evilBoundsCheck ? "BoundsChecked" : "NoBoundsCheck"
|
||||
let testPrefix = "MemorySafety/\(boundsChecked)/Evil\(natureOfEvil)"
|
||||
|
||||
let t = ArrayTestSuite.test("\(testPrefix)/Infrastructure")
|
||||
(evilBoundsCheck && _isDebugAssertConfiguration()
|
||||
? t.crashOutputMatches(evilBoundsError) : t)
|
||||
.code {
|
||||
let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
|
||||
let count0 = evil.count
|
||||
let count1 = evil.count
|
||||
expectNotEqual(count0, count1)
|
||||
if step > 0 {
|
||||
expectLE(count0, count1)
|
||||
}
|
||||
else {
|
||||
expectGE(count0, count1)
|
||||
}
|
||||
if evilBoundsCheck {
|
||||
expectCrashLater()
|
||||
}
|
||||
let x = evil[-1]
|
||||
_blackHole(x)
|
||||
}
|
||||
|
||||
let t2 = ArrayTestSuite.test("\(testPrefix)/Construction")
|
||||
(_isDebugAssertConfiguration() && expectedToFail
|
||||
? t2.crashOutputMatches(constructionMessage) : t2)
|
||||
.code {
|
||||
let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
|
||||
|
||||
if expectedToFail {
|
||||
expectCrashLater()
|
||||
}
|
||||
|
||||
let a = Array(evil)
|
||||
_blackHole(a)
|
||||
}
|
||||
|
||||
for (op, rangeMax) in ["Grow":0, "Shrink":200] {
|
||||
let t3 = ArrayTestSuite.test("\(testPrefix)/replaceSubrange/\(op)Unique")
|
||||
(_isDebugAssertConfiguration() ? t3.crashOutputMatches(message) : t3)
|
||||
.code {
|
||||
let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
|
||||
var a = Array((0..<200).lazy.map { TestValueTy($0) })
|
||||
if expectedToFail {
|
||||
expectCrashLater()
|
||||
}
|
||||
a.replaceSubrange(0..<rangeMax, with: evil)
|
||||
}
|
||||
|
||||
let t4 = ArrayTestSuite.test("\(testPrefix)/replaceSubrange/\(op)NonUnique")
|
||||
(_isDebugAssertConfiguration() ? t4.crashOutputMatches(message) : t4)
|
||||
.code {
|
||||
let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
|
||||
var a = Array((0..<200).lazy.map { TestValueTy($0) })
|
||||
var b = a
|
||||
if expectedToFail {
|
||||
expectCrashLater()
|
||||
}
|
||||
a.replaceSubrange(0..<rangeMax, with: evil)
|
||||
_fixLifetime(b)
|
||||
}
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("\(testPrefix)/SequenceMap")
|
||||
.skip(.custom(
|
||||
{ _isFastAssertConfiguration() },
|
||||
reason: "this trap is not guaranteed to happen in -Ounchecked"))
|
||||
.code {
|
||||
let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
|
||||
|
||||
if step < 0 {
|
||||
expectCrashLater()
|
||||
}
|
||||
let a = AnySequence(evil).map { $0 }
|
||||
_blackHole(a)
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("\(testPrefix)/CollectionMap")
|
||||
.code {
|
||||
let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
|
||||
|
||||
if expectedToFail {
|
||||
expectCrashLater()
|
||||
}
|
||||
|
||||
let a = evil.map { $0 }
|
||||
_blackHole(a)
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("\(testPrefix)/FilterAll")
|
||||
.code {
|
||||
let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
|
||||
|
||||
let a = evil.filter { _ in true }
|
||||
_blackHole(a)
|
||||
}
|
||||
|
||||
ArrayTestSuite.test("\(testPrefix)/FilterNone")
|
||||
.code {
|
||||
let evil = EvilCollection(step, boundsChecked: evilBoundsCheck)
|
||||
|
||||
let a = evil.filter { _ in false }
|
||||
_blackHole(a)
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Special cases and one-off tests.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
% for array_type in all_array_types:
|
||||
|
||||
ArrayTestSuite.test("${array_type}<Void>/map") {
|
||||
// This code used to crash because it generated an array of Void with
|
||||
// stride == 0.
|
||||
do {
|
||||
let input: ${array_type}<Void> = [ (), (), () ]
|
||||
let result = input.map { (_) -> Void in return () }
|
||||
expectEqual(3, result.count)
|
||||
}
|
||||
|
||||
do {
|
||||
let input: ${array_type}<OpaqueValue<Int>> = [
|
||||
OpaqueValue(10), OpaqueValue(20), OpaqueValue(30)
|
||||
]
|
||||
let result = input.map { (_) -> Void in return () }
|
||||
expectEqual(3, result.count)
|
||||
}
|
||||
}
|
||||
|
||||
% end
|
||||
|
||||
ArrayTestSuite.setUp {
|
||||
resetLeaksOfDictionaryKeysValues()
|
||||
resetLeaksOfObjCDictionaryKeysValues()
|
||||
@@ -1771,102 +1147,5 @@ ArrayTestSuite.tearDown {
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MutableCollectionType and RangeReplaceableCollectionType conformance tests.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
% for array_type in all_array_types:
|
||||
% collection_or_slice = 'Slice' if 'Slice' in array_type else 'Collection'
|
||||
|
||||
do {
|
||||
// `Array`, `ArraySlice`, and `ContiguousArrayBuffer` have no expectation of
|
||||
// failure for advancing their indexes "out of bounds", because they are just
|
||||
// `Int`.
|
||||
var resiliencyChecks = CollectionMisuseResiliencyChecks.all
|
||||
resiliencyChecks.creatingOutOfBoundsIndicesBehavior = .none
|
||||
|
||||
// Test MutableCollectionType conformance with value type elements.
|
||||
ArrayTestSuite.addRandomAccessMutableCollectionTests(
|
||||
makeCollection: { (elements: [OpaqueValue<Int>]) in
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValue: identity,
|
||||
extractValue: identity,
|
||||
makeCollectionOfEquatable: { (elements: [MinimalEquatableValue]) in
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValueIntoEquatable: identityEq,
|
||||
extractValueFromEquatable: identityEq,
|
||||
makeCollectionOfComparable: { (elements: [MinimalComparableValue]) in
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValueIntoComparable: identityComp,
|
||||
extractValueFromComparable: identityComp,
|
||||
resiliencyChecks: resiliencyChecks,
|
||||
withUnsafeMutableBufferPointerIsSupported: true,
|
||||
isFixedLengthCollection: false)
|
||||
|
||||
|
||||
// Test MutableCollectionType conformance with reference type elements.
|
||||
ArrayTestSuite.addRandomAccessMutableCollectionTests(
|
||||
makeCollection: { (elements: [LifetimeTracked]) in
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValue: { (element: OpaqueValue<Int>) in
|
||||
LifetimeTracked(element.value, identity: element.identity)
|
||||
},
|
||||
extractValue: { (element: LifetimeTracked) in
|
||||
OpaqueValue(element.value, identity: element.identity)
|
||||
},
|
||||
makeCollectionOfEquatable: { (elements: [MinimalEquatableValue]) in
|
||||
// FIXME: use LifetimeTracked.
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValueIntoEquatable: identityEq,
|
||||
extractValueFromEquatable: identityEq,
|
||||
makeCollectionOfComparable: { (elements: [MinimalComparableValue]) in
|
||||
// FIXME: use LifetimeTracked.
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValueIntoComparable: identityComp,
|
||||
extractValueFromComparable: identityComp,
|
||||
resiliencyChecks: resiliencyChecks,
|
||||
withUnsafeMutableBufferPointerIsSupported: true,
|
||||
isFixedLengthCollection: false)
|
||||
|
||||
|
||||
// Test RangeReplaceableCollectionType conformance with value type elements.
|
||||
ArrayTestSuite.addRandomAccessRangeReplaceable${collection_or_slice}Tests(
|
||||
makeCollection: { (elements: [OpaqueValue<Int>]) in
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValue: identity,
|
||||
extractValue: identity,
|
||||
makeCollectionOfEquatable: { (elements: [MinimalEquatableValue]) in
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValueIntoEquatable: identityEq,
|
||||
extractValueFromEquatable: identityEq,
|
||||
resiliencyChecks: resiliencyChecks)
|
||||
|
||||
|
||||
// Test RangeReplaceableCollectionType conformance with reference type elements.
|
||||
ArrayTestSuite.addRandomAccessRangeReplaceable${collection_or_slice}Tests(
|
||||
makeCollection: { (elements: [LifetimeTracked]) in
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValue: { (element: OpaqueValue<Int>) in LifetimeTracked(element.value) },
|
||||
extractValue: { (element: LifetimeTracked) in OpaqueValue(element.value) },
|
||||
makeCollectionOfEquatable: { (elements: [MinimalEquatableValue]) in
|
||||
// FIXME: use LifetimeTracked.
|
||||
return ${array_type}(elements)
|
||||
},
|
||||
wrapValueIntoEquatable: identityEq,
|
||||
extractValueFromEquatable: identityEq,
|
||||
resiliencyChecks: resiliencyChecks)
|
||||
}
|
||||
|
||||
% end
|
||||
|
||||
runAllTests()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user