Files
swift-mirror/validation-test/stdlib/Arrays.swift.gyb
Jordan Rose bc83940301 Make pointer nullability explicit using Optional.
Implements SE-0055: https://github.com/apple/swift-evolution/blob/master/proposals/0055-optional-unsafe-pointers.md

- Add NULL as an extra inhabitant of Builtin.RawPointer (currently
  hardcoded to 0 rather than being target-dependent).
- Import non-object pointers as Optional/IUO when nullable/null_unspecified
  (like everything else).
- Change the type checker's *-to-pointer conversions to handle a layer of
  optional.
- Use 'AutoreleasingUnsafeMutablePointer<NSError?>?' as the type of error
  parameters exported to Objective-C.
- Drop NilLiteralConvertible conformance for all pointer types.
- Update the standard library and then all the tests.

I've decided to leave this commit only updating existing tests; any new
tests will come in the following commits. (That may mean some additional
implementation work to follow.)

The other major piece that's missing here is migration. I'm hoping we get
a lot of that with Swift 1.1's work for optional object references, but
I still need to investigate.
2016-04-11 20:06:38 -07:00

810 lines
23 KiB
Plaintext

// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: %S/../../utils/gyb %s -o %t/ArrayTraps.swift
// RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-build-swift %t/ArrayTraps.swift -o %t/a.out
//
// RUN: %S/../../utils/line-directive %t/ArrayTraps.swift -- %target-run %t/a.out
// REQUIRES: executable_test
import StdlibUnittest
import StdlibCollectionUnittest
//===--- struct MrMcRange -------------------------------------------------===//
// A wrapper around Range<Tracked> that allows us to detect when it is
// being treated as a Collection rather than merely a Sequence, which
// helps us to prove that an optimization is being used. In
// particular, when constructing a _ContiguousArrayBuffer from a
// Collection, the necessary storage should be pre-allocated.
struct MrMcRange : Collection {
static var timesStartIndexWasCalled = ResettableValue(0)
typealias Base = Range<Int>
init(_ base: Base) {
self.base = base
}
var startIndex: Int {
MrMcRange.timesStartIndexWasCalled.value += 1
return base.startIndex
}
var endIndex: Int {
return base.endIndex
}
subscript(i: Int) -> LifetimeTracked {
return LifetimeTracked(i)
}
var base: Base
}
let CopyToNativeArrayBufferTests = TestSuite("CopyToNativeArrayBufferTests")
CopyToNativeArrayBufferTests.test("Sequence._copyToNativeArrayBuffer()") {
let sequence: MinimalSequence<LifetimeTracked> =
MinimalSequence(elements: LifetimeTracked(10)..<LifetimeTracked(27))
let buffer = sequence._copyToNativeArrayBuffer()
expectEqualSequence(
Array(10..<27),
buffer.map { $0.value })
}
CopyToNativeArrayBufferTests.test("Collection._copyToNativeArrayBuffer()") {
let buffer = MrMcRange(3..<23)._copyToNativeArrayBuffer()
// 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).
expectNotEqual(0, MrMcRange.timesStartIndexWasCalled.value)
expectEqualSequence(
Array(3..<23),
buffer.map { $0.value })
}
%{
all_array_types = ['ContiguousArray', 'ArraySlice', 'Array']
}%
extension Array {
var identity: UnsafePointer<Void> {
return self._buffer.identity
}
}
extension ArraySlice {
var identity: UnsafePointer<Void> {
return self._buffer.identity
}
}
extension ContiguousArray {
var identity: UnsafePointer<Void> {
return self._buffer.identity
}
}
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 = [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 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) -> LifetimeTracked {
if boundsChecked {
precondition(i >= 0 && i < _count, evilBoundsError)
}
return LifetimeTracked(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 { 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 = 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
//===----------------------------------------------------------------------===//
// 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()