@@ -1222,6 +1222,12 @@ extension TestSuite {
1222
1222
return makeCollection ( elements. map ( wrapValue) )
1223
1223
}
1224
1224
1225
+ func makeWrappedCollectionWithEquatableElement(
1226
+ _ elements: [ MinimalEquatableValue ]
1227
+ ) -> CollectionWithEquatableElement {
1228
+ return makeCollectionOfEquatable ( elements. map ( wrapValueIntoEquatable) )
1229
+ }
1230
+
1225
1231
testNamePrefix += String ( describing: C . Type. self)
1226
1232
1227
1233
// FIXME: swift-3-indexing-model - add tests for the follow?
@@ -1254,6 +1260,149 @@ extension TestSuite {
1254
1260
}
1255
1261
}
1256
1262
1263
+ //===------------------------------------------------------------------===//
1264
+ // last(where:)
1265
+ //===------------------------------------------------------------------===//
1266
+
1267
+ let lastPerformanceTest = FindTest (
1268
+ expected: 3 ,
1269
+ element: 2020 ,
1270
+ sequence: [ 1010 , 2020 , 3030 , 2020 , 4040 ] ,
1271
+ expectedLeftoverSequence: [ 3030 , 2020 , 4040 ] )
1272
+
1273
+ self . test ( " \( testNamePrefix) .last(where:)/semantics " ) {
1274
+ for test in findLastTests {
1275
+ let c = makeWrappedCollectionWithEquatableElement ( test. sequence)
1276
+ let closureLifetimeTracker = LifetimeTracked ( 0 )
1277
+ let found = c. last ( where: {
1278
+ _blackHole ( closureLifetimeTracker)
1279
+ return $0 == wrapValueIntoEquatable ( test. element)
1280
+ } )
1281
+ expectEqual (
1282
+ test. expected == nil ? nil : wrapValueIntoEquatable ( test. element) ,
1283
+ found,
1284
+ stackTrace: SourceLocStack ( ) . with ( test. loc) )
1285
+ if let expectedIdentity = test. expected {
1286
+ expectEqual (
1287
+ expectedIdentity, extractValueFromEquatable ( found!) . identity,
1288
+ " last(where:) should find only the first element matching its predicate " )
1289
+ }
1290
+ }
1291
+ }
1292
+
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
+ //===------------------------------------------------------------------===//
1317
+ // lastIndex(of:)/lastIndex(where:)
1318
+ //===------------------------------------------------------------------===//
1319
+
1320
+ self . test ( " \( testNamePrefix) .lastIndex(of:)/semantics " ) {
1321
+ for test in findLastTests {
1322
+ let c = makeWrappedCollectionWithEquatableElement ( test. sequence)
1323
+ var result = c. lastIndex ( of: wrapValueIntoEquatable ( test. element) )
1324
+ expectType (
1325
+ Optional< CollectionWithEquatableElement . Index> . self ,
1326
+ & result)
1327
+ let zeroBasedIndex = result. map {
1328
+ numericCast ( c. distance ( from: c. startIndex, to: $0) ) as Int
1329
+ }
1330
+ expectEqual (
1331
+ test. expected,
1332
+ zeroBasedIndex,
1333
+ stackTrace: SourceLocStack ( ) . with ( test. loc) )
1334
+ }
1335
+ }
1336
+
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
+ self . test ( " \( testNamePrefix) .lastIndex(where:)/semantics " ) {
1360
+ for test in findLastTests {
1361
+ let closureLifetimeTracker = LifetimeTracked ( 0 )
1362
+ expectEqual ( 1 , LifetimeTracked . instances)
1363
+ let c = makeWrappedCollectionWithEquatableElement ( test. sequence)
1364
+ let result = c. lastIndex ( where: {
1365
+ ( candidate) in
1366
+ _blackHole ( closureLifetimeTracker)
1367
+ return
1368
+ extractValueFromEquatable ( candidate) . value == test. element. value
1369
+ } )
1370
+ let zeroBasedIndex = result. map {
1371
+ numericCast ( c. distance ( from: c. startIndex, to: $0) ) as Int
1372
+ }
1373
+ expectEqual (
1374
+ test. expected,
1375
+ zeroBasedIndex,
1376
+ stackTrace: SourceLocStack ( ) . with ( test. loc) )
1377
+ }
1378
+ }
1379
+
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
+
1257
1406
//===------------------------------------------------------------------===//
1258
1407
// removeLast()/slice
1259
1408
//===------------------------------------------------------------------===//
0 commit comments