Skip to content

Commit 4466574

Browse files
author
Dave Abrahams
committed
[stdlib] index(...) tests => StdlibCollectionUnittest
Moving the ones that can be applied generally into the unit testing library.
1 parent 10bddb4 commit 4466574

File tree

8 files changed

+146
-130
lines changed

8 files changed

+146
-130
lines changed

stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb

Lines changed: 112 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -482,13 +482,20 @@ internal func _product<C1 : Collection, C2 : Collection>(
482482
checksAdded: Box<Set<String>> = Box([]),
483483
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
484484
outOfBoundsIndexOffset: Int = 1,
485-
outOfBoundsSubscriptOffset: Int = 1
485+
outOfBoundsSubscriptOffset: Int = 1,
486+
collectionIsBidirectional: Bool
486487
'''
488+
489+
import re
490+
forwardTestArgs = ',\n '.join(
491+
[ x.group(1) + ': ' + x.group(1)
492+
for x in re.finditer(r'([a-zA-Z0-9_]+):', testParams) ]
493+
).replace('testNamePrefix: ', '\n ')
487494
}%
488495
extension TestSuite {
489496
public func addCollectionTests<
490497
${testConstraints('Collection')}
491-
>(${testParams}) {
498+
>(${testParams} = false) {
492499
var testNamePrefix = testNamePrefix
493500

494501
if checksAdded.value.contains(#function) {
@@ -1150,30 +1157,19 @@ extension TestSuite {
11501157
}
11511158

11521159
//===------------------------------------------------------------------===//
1153-
1160+
self.addCommonTests(${forwardTestArgs})
11541161
} // addCollectionTests
11551162

11561163
public func addBidirectionalCollectionTests<
11571164
${testConstraints('BidirectionalCollection')}
1158-
>(${testParams}) {
1165+
>(${testParams} = true) {
11591166
var testNamePrefix = testNamePrefix
11601167
if checksAdded.value.contains(#function) {
11611168
return
11621169
}
11631170
checksAdded.value.insert(#function)
11641171

1165-
addCollectionTests(
1166-
testNamePrefix,
1167-
makeCollection: makeCollection,
1168-
wrapValue: wrapValue,
1169-
extractValue: extractValue,
1170-
makeCollectionOfEquatable: makeCollectionOfEquatable,
1171-
wrapValueIntoEquatable: wrapValueIntoEquatable,
1172-
extractValueFromEquatable: extractValueFromEquatable,
1173-
checksAdded: checksAdded,
1174-
resiliencyChecks: resiliencyChecks,
1175-
outOfBoundsIndexOffset: outOfBoundsIndexOffset,
1176-
outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset)
1172+
addCollectionTests(${forwardTestArgs})
11771173

11781174
func makeWrappedCollection(_ elements: [OpaqueValue<Int>]) -> C {
11791175
return makeCollection(elements.map(wrapValue))
@@ -1473,31 +1469,21 @@ extension TestSuite {
14731469

14741470
//===------------------------------------------------------------------===//
14751471

1472+
self.addCommonTests(${forwardTestArgs})
14761473
} // addBidirectionalCollectionTests
14771474

14781475
public func addRandomAccessCollectionTests<
14791476
${testConstraints('RandomAccessCollection')}
1480-
>(${testParams}) {
1477+
>(${testParams} = true) {
14811478
var testNamePrefix = testNamePrefix
14821479

14831480
if checksAdded.value.contains(#function) {
14841481
return
14851482
}
14861483
checksAdded.value.insert(#function)
14871484

1488-
addBidirectionalCollectionTests(
1489-
testNamePrefix,
1490-
makeCollection: makeCollection,
1491-
wrapValue: wrapValue,
1492-
extractValue: extractValue,
1493-
makeCollectionOfEquatable: makeCollectionOfEquatable,
1494-
wrapValueIntoEquatable: wrapValueIntoEquatable,
1495-
extractValueFromEquatable: extractValueFromEquatable,
1496-
checksAdded: checksAdded,
1497-
resiliencyChecks: resiliencyChecks,
1498-
outOfBoundsIndexOffset: outOfBoundsIndexOffset,
1499-
outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset)
1500-
1485+
addBidirectionalCollectionTests(${forwardTestArgs})
1486+
15011487
testNamePrefix += String(C.Type)
15021488

15031489
func makeWrappedCollection(_ elements: [OpaqueValue<Int>]) -> C {
@@ -1532,6 +1518,101 @@ extension TestSuite {
15321518
}
15331519
}
15341520

1535-
//===----------------------------------------------------------------------===//
1521+
//===------------------------------------------------------------------===//
1522+
self.addCommonTests(${forwardTestArgs})
15361523
} // addRandomAccessCollectionTests
1524+
1525+
% for Traversal in ['Forward', 'Bidirectional', 'RandomAccess']:
1526+
func addCommonTests<
1527+
${testConstraints(collectionForTraversal(Traversal))}
1528+
>(${testParams}) {
1529+
if checksAdded.value.contains(#function) {
1530+
return
1531+
}
1532+
checksAdded.value.insert(#function)
1533+
1534+
func toCollection(_ r: CountableRange<Int>) -> C {
1535+
return makeCollection(r.map { wrapValue(OpaqueValue($0)) })
1536+
}
1537+
1538+
self.test("\(testNamePrefix)/distance(from:to:)/semantics") {
1539+
let c = toCollection(0..<20)
1540+
for test in distanceFromToTests {
1541+
let d = c.distance(
1542+
from: c.nthIndex(test.startOffset), to: c.nthIndex(test.endOffset))
1543+
expectEqual(
1544+
numericCast(test.expectedDistance),
1545+
d, stackTrace: SourceLocStack().with(test.loc))
1546+
}
1547+
}
1548+
1549+
self.test("\(testNamePrefix)/index(_:stepsFrom: n)/semantics") {
1550+
for test in indexStepsFromTests.filter(
1551+
{$0.limit == nil && $0.distance >= 0}
1552+
) {
1553+
let c = toCollection(0..<10)
1554+
1555+
let new = c.index(
1556+
c.nthIndex(test.startOffset),
1557+
offsetBy: numericCast(test.distance))
1558+
1559+
// Since the `nthIndex(offset:)` method performs the same operation
1560+
// (i.e. adavances `c.startIndex` by `test.distance`, it would be
1561+
// silly to compare index values. Luckily the underlying collection
1562+
// contains exactly index offsets.
1563+
expectEqual(test.expectedOffset!, extractValue(c[new]).value,
1564+
stackTrace: SourceLocStack().with(test.loc))
1565+
}
1566+
}
1567+
1568+
if !collectionIsBidirectional {
1569+
self.test("\(testNamePrefix)/index(_:stepsFrom: -n)/semantics") {
1570+
for test in indexStepsFromTests.filter(
1571+
{$0.limit == nil && $0.distance < 0}
1572+
) {
1573+
let c = toCollection(0..<10)
1574+
let start = c.nthIndex(test.startOffset)
1575+
expectCrashLater()
1576+
_ = c.index(start, offsetBy: numericCast(test.distance))
1577+
}
1578+
}
1579+
self.test("\(testNamePrefix)/advance(by: -n, limitedBy:)/semantics") {
1580+
for test in indexStepsFromTests.filter(
1581+
{$0.limit != nil && $0.distance < 0}
1582+
) {
1583+
let c = toCollection(0..<10)
1584+
let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
1585+
let start = c.nthIndex(test.startOffset)
1586+
expectCrashLater()
1587+
_ = c.index(
1588+
start, offsetBy: numericCast(test.distance), limitedBy: limit)
1589+
}
1590+
}
1591+
}
1592+
1593+
self.test("\(testNamePrefix)/advance(by: n, limitedBy:)/semantics") {
1594+
for test in indexStepsFromTests.filter(
1595+
{$0.limit != nil && $0.distance >= 0}
1596+
) {
1597+
let c = toCollection(0..<20)
1598+
let limit = c.nthIndex(test.limit.unsafelyUnwrapped)
1599+
1600+
if !collectionIsBidirectional && test.distance < 0 {
1601+
expectCrashLater()
1602+
}
1603+
1604+
let new = c.index(
1605+
c.nthIndex(test.startOffset),
1606+
offsetBy: numericCast(test.distance),
1607+
limitedBy: limit)
1608+
if test.expectedOffset == nil {
1609+
expectEmpty(new)
1610+
} else {
1611+
expectEqual(c.nthIndex(test.expectedOffset!), new!,
1612+
stackTrace: SourceLocStack().with(test.loc))
1613+
}
1614+
}
1615+
}
1616+
}
1617+
% end
15371618
}

stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ extension TestSuite {
107107
outOfBoundsIndexOffset: Int = 1,
108108
outOfBoundsSubscriptOffset: Int = 1,
109109
withUnsafeMutableBufferPointerIsSupported: Bool,
110-
isFixedLengthCollection: Bool
110+
isFixedLengthCollection: Bool,
111+
collectionIsBidirectional: Bool = false
111112
) {
112113
var testNamePrefix = testNamePrefix
113114

@@ -127,7 +128,9 @@ extension TestSuite {
127128
checksAdded: checksAdded,
128129
resiliencyChecks: resiliencyChecks,
129130
outOfBoundsIndexOffset: outOfBoundsIndexOffset,
130-
outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset)
131+
outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
132+
collectionIsBidirectional: collectionIsBidirectional
133+
)
131134

132135
func makeWrappedCollection(_ elements: [OpaqueValue<Int>]) -> C {
133136
return makeCollection(elements.map(wrapValue))
@@ -642,7 +645,9 @@ self.test("\(testNamePrefix).sorted/${'Predicate' if predicate else 'WhereElemen
642645
outOfBoundsSubscriptOffset: outOfBoundsSubscriptOffset,
643646
withUnsafeMutableBufferPointerIsSupported:
644647
withUnsafeMutableBufferPointerIsSupported,
645-
isFixedLengthCollection: isFixedLengthCollection)
648+
isFixedLengthCollection: isFixedLengthCollection,
649+
collectionIsBidirectional: true
650+
)
646651

647652
addBidirectionalCollectionTests(
648653
testNamePrefix,

stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableCollectionType.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,8 @@ extension TestSuite {
444444

445445
checksAdded: Box<Set<String>> = Box([]),
446446
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
447-
outOfBoundsIndexOffset: Int = 1
447+
outOfBoundsIndexOffset: Int = 1,
448+
collectionIsBidirectional: Bool = false
448449
) {
449450
var testNamePrefix = testNamePrefix
450451

@@ -463,7 +464,9 @@ extension TestSuite {
463464
extractValueFromEquatable: extractValueFromEquatable,
464465
checksAdded: checksAdded,
465466
resiliencyChecks: resiliencyChecks,
466-
outOfBoundsIndexOffset: outOfBoundsIndexOffset)
467+
outOfBoundsIndexOffset: outOfBoundsIndexOffset,
468+
collectionIsBidirectional: collectionIsBidirectional
469+
)
467470

468471
func makeWrappedCollection(_ elements: [OpaqueValue<Int>]) -> C {
469472
return makeCollection(elements.map(wrapValue))
@@ -1189,7 +1192,9 @@ self.test("\(testNamePrefix).OperatorPlus") {
11891192
extractValueFromEquatable: extractValueFromEquatable,
11901193
checksAdded: checksAdded,
11911194
resiliencyChecks: resiliencyChecks,
1192-
outOfBoundsIndexOffset: outOfBoundsIndexOffset)
1195+
outOfBoundsIndexOffset: outOfBoundsIndexOffset,
1196+
collectionIsBidirectional: true
1197+
)
11931198

11941199
addBidirectionalCollectionTests(
11951200
testNamePrefix,

stdlib/private/StdlibCollectionUnittest/CheckRangeReplaceableSliceType.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ extension TestSuite {
3838

3939
checksAdded: Box<Set<String>> = Box([]),
4040
resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
41-
outOfBoundsIndexOffset: Int = 1
41+
outOfBoundsIndexOffset: Int = 1,
42+
collectionIsBidirectional: Bool = false
4243
) {
4344
var testNamePrefix = testNamePrefix
4445

@@ -58,7 +59,9 @@ extension TestSuite {
5859
extractValueFromEquatable: extractValueFromEquatable,
5960
checksAdded: checksAdded,
6061
resiliencyChecks: resiliencyChecks,
61-
outOfBoundsIndexOffset: outOfBoundsIndexOffset)
62+
outOfBoundsIndexOffset: outOfBoundsIndexOffset,
63+
collectionIsBidirectional: collectionIsBidirectional
64+
)
6265

6366
func makeWrappedCollection(_ elements: [OpaqueValue<Int>]) -> C {
6467
return makeCollection(elements.map(wrapValue))
@@ -192,7 +195,9 @@ extension TestSuite {
192195
extractValueFromEquatable: extractValueFromEquatable,
193196
checksAdded: checksAdded,
194197
resiliencyChecks: resiliencyChecks,
195-
outOfBoundsIndexOffset: outOfBoundsIndexOffset)
198+
outOfBoundsIndexOffset: outOfBoundsIndexOffset,
199+
collectionIsBidirectional: true
200+
)
196201

197202
addRangeReplaceableBidirectionalCollectionTests(
198203
testNamePrefix,

stdlib/public/core/BidirectionalCollection.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,11 @@ extension BidirectionalIndexable
163163
_ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
164164
) -> Index? {
165165
// FIXME: swift-3-indexing-model: range check i
166-
if n == 0 {
167-
return i
168-
}
169-
let i = i.advanced(by: n)
170-
if (n > 0) ? (i > limit) : (i < limit) {
166+
let l = i.distance(to: limit)
167+
if n > 0 ? l >= 0 && l < n : l <= 0 && l > n {
171168
return nil
172169
}
173-
return i
170+
return index(i, offsetBy: n)
174171
}
175172

176173
@warn_unused_result

stdlib/public/core/Collection.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -893,12 +893,11 @@ extension Indexable
893893
) -> Index? {
894894
_precondition(n >= 0,
895895
"Only BidirectionalCollections can be advanced by a negative amount")
896-
// FIXME: swift-3-indexing-model: range check i
897-
let i = i.advanced(by: n)
898-
if (i > limit) {
896+
let l = i.distance(to: limit)
897+
if l >= 0 && l < n {
899898
return nil
900899
}
901-
return i
900+
return index(i, offsetBy: n)
902901
}
903902

904903
@warn_unused_result

validation-test/stdlib/ExistentialCollection.swift.gyb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,8 @@ do {
451451
wrapValueIntoEquatable: identityEq,
452452
extractValueFromEquatable: identityEq,
453453
checksAdded: checksAdded,
454-
resiliencyChecks: CollectionMisuseResiliencyChecks.all
454+
resiliencyChecks: CollectionMisuseResiliencyChecks.all,
455+
collectionIsBidirectional: ${'false' if Traversal == 'Forward' else 'true'}
455456
)
456457
}
457458

0 commit comments

Comments
 (0)