@@ -110,6 +110,27 @@ public struct SuffixFromTest {
110
110
}
111
111
}
112
112
113
+ public struct FindLastTest {
114
+ public let expected : Int ?
115
+ public let comparisons : Int
116
+ public let element : MinimalEquatableValue
117
+ public let sequence : [ MinimalEquatableValue ]
118
+ public let loc : SourceLoc
119
+
120
+ public init (
121
+ expected: Int ? , comparisons: Int , element: Int , sequence: [ Int ] ,
122
+ file: String = #file, line: UInt = #line
123
+ ) {
124
+ self . expected = expected
125
+ self . comparisons = comparisons
126
+ self . element = MinimalEquatableValue ( element)
127
+ self . sequence = sequence. enumerated ( ) . map {
128
+ return MinimalEquatableValue ( $1, identity: $0)
129
+ }
130
+ self . loc = SourceLoc ( file, line, comment: " test data " )
131
+ }
132
+ }
133
+
113
134
public let subscriptRangeTests = [
114
135
// Slice an empty collection.
115
136
SubscriptRangeTest (
@@ -305,6 +326,68 @@ let removeFirstTests: [RemoveFirstNTest] = [
305
326
) ,
306
327
]
307
328
329
+ let findLastTests = [
330
+ FindLastTest (
331
+ expected: nil ,
332
+ comparisons: 0 ,
333
+ element: 42 ,
334
+ sequence: [ ] ) ,
335
+
336
+ FindLastTest (
337
+ expected: nil ,
338
+ comparisons: 1 ,
339
+ element: 42 ,
340
+ sequence: [ 1010 ] ) ,
341
+ FindLastTest (
342
+ expected: 0 ,
343
+ comparisons: 1 ,
344
+ element: 1010 ,
345
+ sequence: [ 1010 ] ) ,
346
+
347
+ FindLastTest (
348
+ expected: nil ,
349
+ comparisons: 2 ,
350
+ element: 42 ,
351
+ sequence: [ 1010 , 1010 ] ) ,
352
+ FindLastTest (
353
+ expected: 1 ,
354
+ comparisons: 1 ,
355
+ element: 1010 ,
356
+ sequence: [ 1010 , 1010 ] ) ,
357
+
358
+ FindLastTest (
359
+ expected: nil ,
360
+ comparisons: 4 ,
361
+ element: 42 ,
362
+ sequence: [ 1010 , 2020 , 3030 , 4040 ] ) ,
363
+ FindLastTest (
364
+ expected: 0 ,
365
+ comparisons: 4 ,
366
+ element: 1010 ,
367
+ sequence: [ 1010 , 2020 , 3030 , 4040 ] ) ,
368
+ FindLastTest (
369
+ expected: 1 ,
370
+ comparisons: 3 ,
371
+ element: 2020 ,
372
+ sequence: [ 1010 , 2020 , 3030 , 4040 ] ) ,
373
+ FindLastTest (
374
+ expected: 2 ,
375
+ comparisons: 2 ,
376
+ element: 3030 ,
377
+ sequence: [ 1010 , 2020 , 3030 , 4040 ] ) ,
378
+ FindLastTest (
379
+ expected: 3 ,
380
+ comparisons: 1 ,
381
+ element: 4040 ,
382
+ sequence: [ 1010 , 2020 , 3030 , 4040 ] ) ,
383
+
384
+ FindLastTest (
385
+ expected: 3 ,
386
+ comparisons: 2 ,
387
+ element: 2020 ,
388
+ sequence: [ 1010 , 2020 , 3030 , 2020 , 4040 ] ) ,
389
+ ]
390
+
308
391
extension Collection {
309
392
public func nthIndex( _ offset: Int ) -> Index {
310
393
return self . index ( self . startIndex, offsetBy: numericCast ( offset) )
@@ -1264,24 +1347,24 @@ extension TestSuite {
1264
1347
// last(where:)
1265
1348
//===------------------------------------------------------------------===//
1266
1349
1267
- let lastPerformanceTest = FindTest (
1268
- expected: 3 ,
1269
- element: 2020 ,
1270
- sequence: [ 1010 , 2020 , 3030 , 2020 , 4040 ] ,
1271
- expectedLeftoverSequence: [ 3030 , 2020 , 4040 ] )
1272
-
1273
1350
self . test ( " \( testNamePrefix) .last(where:)/semantics " ) {
1274
1351
for test in findLastTests {
1275
1352
let c = makeWrappedCollectionWithEquatableElement ( test. sequence)
1353
+ var closureCounter = 0
1276
1354
let closureLifetimeTracker = LifetimeTracked ( 0 )
1277
1355
let found = c. last ( where: {
1278
1356
_blackHole ( closureLifetimeTracker)
1357
+ closureCounter += 1
1279
1358
return $0 == wrapValueIntoEquatable ( test. element)
1280
1359
} )
1281
1360
expectEqual (
1282
1361
test. expected == nil ? nil : wrapValueIntoEquatable ( test. element) ,
1283
1362
found,
1284
1363
stackTrace: SourceLocStack ( ) . with ( test. loc) )
1364
+ expectEqual (
1365
+ test. comparisons,
1366
+ closureCounter,
1367
+ stackTrace: SourceLocStack ( ) . with ( test. loc) )
1285
1368
if let expectedIdentity = test. expected {
1286
1369
expectEqual (
1287
1370
expectedIdentity, extractValueFromEquatable ( found!) . identity,
@@ -1290,37 +1373,16 @@ extension TestSuite {
1290
1373
}
1291
1374
}
1292
1375
1293
- self . test ( " \( testNamePrefix) .last(where:)/performance " ) {
1294
- let test = lastPerformanceTest
1295
- let closureLifetimeTracker = LifetimeTracked ( 0 )
1296
- expectEqual ( 1 , LifetimeTracked . instances)
1297
- let c = makeCollectionOfEquatable ( test. sequence. map ( wrapValueIntoEquatable) )
1298
- var closureCounter = 0
1299
- let found = c. last ( where: {
1300
- ( candidate) in
1301
- _blackHole ( closureLifetimeTracker)
1302
- closureCounter += 1
1303
- return
1304
- extractValueFromEquatable ( candidate) . value == test. element. value
1305
- } )
1306
- expectEqual (
1307
- test. expected == nil ? nil : wrapValueIntoEquatable ( test. element) ,
1308
- found,
1309
- stackTrace: SourceLocStack ( ) . with ( test. loc) )
1310
- expectEqual (
1311
- 2 ,
1312
- closureCounter,
1313
- stackTrace: SourceLocStack ( ) . with ( test. loc) )
1314
- }
1315
-
1316
1376
//===------------------------------------------------------------------===//
1317
1377
// lastIndex(of:)/lastIndex(where:)
1318
1378
//===------------------------------------------------------------------===//
1319
1379
1320
1380
self . test ( " \( testNamePrefix) .lastIndex(of:)/semantics " ) {
1321
1381
for test in findLastTests {
1322
1382
let c = makeWrappedCollectionWithEquatableElement ( test. sequence)
1323
- var result = c. lastIndex ( of: wrapValueIntoEquatable ( test. element) )
1383
+ MinimalEquatableValue . timesEqualEqualWasCalled = 0
1384
+ let wrappedElement = wrapValueIntoEquatable ( test. element)
1385
+ var result = c. lastIndex ( of: wrappedElement)
1324
1386
expectType (
1325
1387
Optional< CollectionWithEquatableElement . Index> . self ,
1326
1388
& result)
@@ -1331,39 +1393,25 @@ extension TestSuite {
1331
1393
test. expected,
1332
1394
zeroBasedIndex,
1333
1395
stackTrace: SourceLocStack ( ) . with ( test. loc) )
1396
+ if wrappedElement is MinimalEquatableValue {
1397
+ expectEqual (
1398
+ test. comparisons,
1399
+ MinimalEquatableValue . timesEqualEqualWasCalled,
1400
+ stackTrace: SourceLocStack ( ) . with ( test. loc) )
1401
+ }
1334
1402
}
1335
1403
}
1336
1404
1337
- self . test ( " \( testNamePrefix) .lastIndex(of:)/performance " ) {
1338
- let test = lastPerformanceTest
1339
- let wrappedElement = wrapValueIntoEquatable ( test. element)
1340
- // Only test specialization when we can actually track calls to `==`
1341
- guard wrappedElement is MinimalEquatableValue else { return }
1342
-
1343
- let c = makeCollectionOfEquatable ( test. sequence. map ( wrapValueIntoEquatable) )
1344
- MinimalEquatableValue . timesEqualEqualWasCalled = 0
1345
- let result = c. lastIndex ( of: wrappedElement)
1346
- let zeroBasedIndex = result. map {
1347
- numericCast ( c. distance ( from: c. startIndex, to: $0) ) as Int
1348
- }
1349
- expectEqual (
1350
- test. expected,
1351
- zeroBasedIndex,
1352
- stackTrace: SourceLocStack ( ) . with ( test. loc) )
1353
- expectEqual (
1354
- 2 ,
1355
- MinimalEquatableValue . timesEqualEqualWasCalled,
1356
- stackTrace: SourceLocStack ( ) . with ( test. loc) )
1357
- }
1358
-
1359
1405
self . test ( " \( testNamePrefix) .lastIndex(where:)/semantics " ) {
1360
1406
for test in findLastTests {
1361
1407
let closureLifetimeTracker = LifetimeTracked ( 0 )
1362
1408
expectEqual ( 1 , LifetimeTracked . instances)
1363
1409
let c = makeWrappedCollectionWithEquatableElement ( test. sequence)
1410
+ var closureCounter = 0
1364
1411
let result = c. lastIndex ( where: {
1365
1412
( candidate) in
1366
1413
_blackHole ( closureLifetimeTracker)
1414
+ closureCounter += 1
1367
1415
return
1368
1416
extractValueFromEquatable ( candidate) . value == test. element. value
1369
1417
} )
@@ -1374,35 +1422,13 @@ extension TestSuite {
1374
1422
test. expected,
1375
1423
zeroBasedIndex,
1376
1424
stackTrace: SourceLocStack ( ) . with ( test. loc) )
1425
+ expectEqual (
1426
+ test. comparisons,
1427
+ closureCounter,
1428
+ stackTrace: SourceLocStack ( ) . with ( test. loc) )
1377
1429
}
1378
1430
}
1379
1431
1380
- self . test ( " \( testNamePrefix) .lastIndex(where:)/performance " ) {
1381
- let test = lastPerformanceTest
1382
- let closureLifetimeTracker = LifetimeTracked ( 0 )
1383
- expectEqual ( 1 , LifetimeTracked . instances)
1384
- let c = makeCollectionOfEquatable ( test. sequence. map ( wrapValueIntoEquatable) )
1385
- var closureCounter = 0
1386
- let result = c. lastIndex ( where: {
1387
- ( candidate) in
1388
- _blackHole ( closureLifetimeTracker)
1389
- closureCounter += 1
1390
- return
1391
- extractValueFromEquatable ( candidate) . value == test. element. value
1392
- } )
1393
- let zeroBasedIndex = result. map {
1394
- numericCast ( c. distance ( from: c. startIndex, to: $0) ) as Int
1395
- }
1396
- expectEqual (
1397
- test. expected,
1398
- zeroBasedIndex,
1399
- stackTrace: SourceLocStack ( ) . with ( test. loc) )
1400
- expectEqual (
1401
- 2 ,
1402
- closureCounter,
1403
- stackTrace: SourceLocStack ( ) . with ( test. loc) )
1404
- }
1405
-
1406
1432
//===------------------------------------------------------------------===//
1407
1433
// removeLast()/slice
1408
1434
//===------------------------------------------------------------------===//
0 commit comments