blob: 6c5628684151af6c7d8fd8c1fc8d724bff52a329 [file] [log] [blame]
// RUN: %target-run-simple-swiftgyb
// REQUIRES: executable_test
import StdlibUnittest
import StdlibCollectionUnittest
let CopyToNativeArrayBufferTests = TestSuite("CopyToNativeArrayBufferTests")
CopyToNativeArrayBufferTests.test("Sequence._copyToContiguousArray()") {
do {
// Call from a static context.
let s =
MinimalSequence(elements: LifetimeTracked(10)..<LifetimeTracked(27))
expectEqual(0, s.timesMakeIteratorCalled.value)
let copy = s._copyToContiguousArray()
expectEqual(1, s.timesMakeIteratorCalled.value)
expectEqualSequence(
Array(10..<27),
copy.map { $0.value })
}
do {
// Call from a generic context.
let wrapped = MinimalSequence(elements: LifetimeTracked(10)..<LifetimeTracked(27))
let s = LoggingSequence(wrapping: wrapped)
expectEqual(0, wrapped.timesMakeIteratorCalled.value)
let copy = s._copyToContiguousArray()
expectEqual(1, wrapped.timesMakeIteratorCalled.value)
expectEqualSequence(
Array(10..<27),
copy.map { $0.value })
}
}
CopyToNativeArrayBufferTests.test("Collection._copyToContiguousArray()") {
// Check that collections are handled with the collection-specific API. This
// means that we are calling the right default implementation (one for
// collections, not the one for sequences).
do {
// Call from a static context.
let c =
DefaultedCollection(elements: LifetimeTracked(10)..<LifetimeTracked(27))
expectEqual(0, c.timesMakeIteratorCalled.value)
expectEqual(0, c.timesStartIndexCalled.value)
let copy = c._copyToContiguousArray()
expectEqual(0, c.timesMakeIteratorCalled.value)
expectNotEqual(0, c.timesStartIndexCalled.value)
expectEqualSequence(
Array(10..<27),
copy.map { $0.value })
}
do {
// Call from a generic context.
let wrapped =
DefaultedCollection(elements: LifetimeTracked(10)..<LifetimeTracked(27))
let s = LoggingSequence(wrapping: wrapped)
expectEqual(0, wrapped.timesMakeIteratorCalled.value)
expectEqual(0, wrapped.timesStartIndexCalled.value)
let copy = s._copyToContiguousArray()
expectEqual(0, wrapped.timesMakeIteratorCalled.value)
expectNotEqual(0, wrapped.timesStartIndexCalled.value)
expectEqualSequence(
Array(10..<27),
copy.map { $0.value })
}
}
%{
all_array_types = ['ContiguousArray', 'ArraySlice', 'Array']
}%
extension Array {
var identity: UnsafeRawPointer {
return self._buffer.identity
}
}
extension ArraySlice {
var identity: UnsafeRawPointer {
return self._buffer.identity
}
}
extension ContiguousArray {
var identity: UnsafeRawPointer {
return self._buffer.identity
}
}
var ArrayTestSuite = TestSuite("Array")
ArrayTestSuite.test("sizeof") {
var a = [ 10, 20, 30 ]
#if arch(i386) || arch(arm)
expectEqual(4, MemoryLayout._ofInstance(a).size)
#else
expectEqual(8, MemoryLayout._ofInstance(a).size)
#endif
}
ArrayTestSuite.test("valueDestruction") {
var a = [LifetimeTracked]()
for i in 100...110 {
a.append(LifetimeTracked(i))
}
}
//===----------------------------------------------------------------------===//
// Native array tests
// FIXME: incomplete.
//===----------------------------------------------------------------------===//
ArrayTestSuite.test("Native/count/empty") {
let a = [LifetimeTracked]()
expectEqual(0, a.count)
}
ArrayTestSuite.test("Native/count") {
let a = [ LifetimeTracked(10), LifetimeTracked(20), LifetimeTracked(30) ]
expectEqual(3, a.count)
}
ArrayTestSuite.test("Native/isEmpty/empty") {
let a = [LifetimeTracked]()
expectTrue(a.isEmpty)
}
ArrayTestSuite.test("Native/isEmpty") {
let a = [ LifetimeTracked(10), LifetimeTracked(20), LifetimeTracked(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}<LifetimeTracked>(repeating: LifetimeTracked(0), count: 0)
// Empty arrays all use the same buffer
expectEqual(arr0._buffer.identity, arr1._buffer.identity)
let arr2: ${array_type}<LifetimeTracked> = []
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
//===----------------------------------------------------------------------===//
// Array and EvilCollection that changes its size while we are not looking
//===----------------------------------------------------------------------===//
let evilBoundsError = "EvilCollection: index out of range"
final class EvilSequence : Sequence {
init(_ growth: Int) {
self.growth = growth
}
var growth: Int
var _count: Int = 20
var underestimatedCount: Int {
defer { _count += growth }
return _count
}
func makeIterator() -> AnyIterator<LifetimeTracked> {
var i = 0
return AnyIterator {
if i >= self._count { return nil }
let result = LifetimeTracked(i)
i += 1
return result
}
}
}
final class EvilCollection : Collection {
func index(after i: Int) -> Int {
return i + 1
}
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) -> LifetimeTracked {
if boundsChecked {
precondition(i >= 0 && i < _count, evilBoundsError)
}
return LifetimeTracked(i)
}
// Default implementation will call _failEarlyRangeCheck,
// passing in a startIndex that will grow _count faster than
// necessary.
func formIndex(after i: inout Int) {
i += 1
}
}
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)"
ArrayTestSuite.test("\(testPrefix)/Infrastructure/EvilSequence") {
let evil = EvilSequence(step)
let count0 = evil.underestimatedCount
let count1 = evil.underestimatedCount
expectNotEqual(count0, count1)
if step > 0 {
expectLE(count0, count1)
}
else {
expectGE(count0, count1)
}
}
let t1 = ArrayTestSuite.test("\(testPrefix)/Infrastructure/EvilCollection")
(evilBoundsCheck && _isDebugAssertConfiguration()
? t1.crashOutputMatches(evilBoundsError) : t1)
.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 { LifetimeTracked($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 { LifetimeTracked($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 = EvilSequence(step)
if step < 0 {
expectCrashLater()
}
let a = 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
//===----------------------------------------------------------------------===//
// MutableCollectionType and RangeReplaceableCollectionType conformance tests.
//===----------------------------------------------------------------------===//
% for array_type in all_array_types:
ArrayTestSuite.test("${array_type}/AssociatedTypes") {
typealias Collection = ${array_type}<OpaqueValue<Int>>
typealias CollectionSlice = ArraySlice<OpaqueValue<Int>>
expectCollectionAssociatedTypes(
collectionType: Collection.self,
iteratorType: IndexingIterator<Collection>.self,
subSequenceType: CollectionSlice.self,
indexType: Int.self,
indexDistanceType: Int.self,
indicesType: CountableRange<Int>.self)
}
% end
func ArraySliceWithNonZeroStartIndex<T>(_ elements: [T]) -> ArraySlice<T> {
var r = ArraySlice<T>(_startIndex: 1000)
r.append(contentsOf: elements)
expectEqual(1000, r.startIndex)
return r
}
% for array_type in all_array_types + ['ArraySliceWithNonZeroStartIndex']:
% 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.addMutableRandomAccessCollectionTests(
"${array_type}.",
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.addMutableRandomAccessCollectionTests(
"${array_type}.",
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.addRangeReplaceableRandomAccess${collection_or_slice}Tests(
"${array_type}.",
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.addRangeReplaceableRandomAccess${collection_or_slice}Tests(
"${array_type}.",
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()