|
1 | 1 | use core::iter::TrustedLen; |
| 2 | +use core::panic::{AssertUnwindSafe, catch_unwind}; |
2 | 3 |
|
3 | 4 | use super::*; |
| 5 | +use crate::testing::crash_test::{CrashTestDummy, Panic}; |
4 | 6 | use crate::testing::macros::struct_with_counted_drop; |
5 | 7 |
|
6 | 8 | #[bench] |
@@ -1161,3 +1163,258 @@ fn issue_80303() { |
1161 | 1163 | assert_eq!(vda, vdb); |
1162 | 1164 | assert_eq!(hash_code(vda), hash_code(vdb)); |
1163 | 1165 | } |
| 1166 | + |
| 1167 | +#[test] |
| 1168 | +fn extract_if_test() { |
| 1169 | + let mut m: VecDeque<u32> = VecDeque::from([1, 2, 3, 4, 5, 6]); |
| 1170 | + let deleted = m.extract_if(|v| *v < 4).collect::<Vec<_>>(); |
| 1171 | + |
| 1172 | + assert_eq!(deleted, &[1, 2, 3]); |
| 1173 | + assert_eq!(m.into_iter().collect::<Vec<_>>(), &[4, 5, 6]); |
| 1174 | +} |
| 1175 | + |
| 1176 | +#[test] |
| 1177 | +fn drain_to_empty_test() { |
| 1178 | + let mut m: VecDeque<u32> = VecDeque::from([1, 2, 3, 4, 5, 6]); |
| 1179 | + let deleted = m.extract_if(|_| true).collect::<Vec<_>>(); |
| 1180 | + |
| 1181 | + assert_eq!(deleted, &[1, 2, 3, 4, 5, 6]); |
| 1182 | + assert_eq!(m.into_iter().collect::<Vec<_>>(), &[]); |
| 1183 | +} |
| 1184 | + |
| 1185 | +#[test] |
| 1186 | +fn extract_if_empty() { |
| 1187 | + let mut list: VecDeque<i32> = VecDeque::new(); |
| 1188 | + |
| 1189 | + { |
| 1190 | + let mut iter = list.extract_if(|_| true); |
| 1191 | + assert_eq!(iter.size_hint(), (0, Some(0))); |
| 1192 | + assert_eq!(iter.next(), None); |
| 1193 | + assert_eq!(iter.size_hint(), (0, Some(0))); |
| 1194 | + assert_eq!(iter.next(), None); |
| 1195 | + assert_eq!(iter.size_hint(), (0, Some(0))); |
| 1196 | + } |
| 1197 | + |
| 1198 | + assert_eq!(list.len(), 0); |
| 1199 | + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]); |
| 1200 | +} |
| 1201 | + |
| 1202 | +#[test] |
| 1203 | +fn extract_if_zst() { |
| 1204 | + let mut list: VecDeque<_> = [(), (), (), (), ()].into_iter().collect(); |
| 1205 | + let initial_len = list.len(); |
| 1206 | + let mut count = 0; |
| 1207 | + |
| 1208 | + { |
| 1209 | + let mut iter = list.extract_if(|_| true); |
| 1210 | + assert_eq!(iter.size_hint(), (0, Some(initial_len))); |
| 1211 | + while let Some(_) = iter.next() { |
| 1212 | + count += 1; |
| 1213 | + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); |
| 1214 | + } |
| 1215 | + assert_eq!(iter.size_hint(), (0, Some(0))); |
| 1216 | + assert_eq!(iter.next(), None); |
| 1217 | + assert_eq!(iter.size_hint(), (0, Some(0))); |
| 1218 | + } |
| 1219 | + |
| 1220 | + assert_eq!(count, initial_len); |
| 1221 | + assert_eq!(list.len(), 0); |
| 1222 | + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]); |
| 1223 | +} |
| 1224 | + |
| 1225 | +#[test] |
| 1226 | +fn extract_if_false() { |
| 1227 | + let mut list: VecDeque<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); |
| 1228 | + |
| 1229 | + let initial_len = list.len(); |
| 1230 | + let mut count = 0; |
| 1231 | + |
| 1232 | + { |
| 1233 | + let mut iter = list.extract_if(|_| false); |
| 1234 | + assert_eq!(iter.size_hint(), (0, Some(initial_len))); |
| 1235 | + for _ in iter.by_ref() { |
| 1236 | + count += 1; |
| 1237 | + } |
| 1238 | + assert_eq!(iter.size_hint(), (0, Some(0))); |
| 1239 | + assert_eq!(iter.next(), None); |
| 1240 | + assert_eq!(iter.size_hint(), (0, Some(0))); |
| 1241 | + } |
| 1242 | + |
| 1243 | + assert_eq!(count, 0); |
| 1244 | + assert_eq!(list.len(), initial_len); |
| 1245 | + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); |
| 1246 | +} |
| 1247 | + |
| 1248 | +#[test] |
| 1249 | +fn extract_if_true() { |
| 1250 | + let mut list: VecDeque<_> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_iter().collect(); |
| 1251 | + |
| 1252 | + let initial_len = list.len(); |
| 1253 | + let mut count = 0; |
| 1254 | + |
| 1255 | + { |
| 1256 | + let mut iter = list.extract_if(|_| true); |
| 1257 | + assert_eq!(iter.size_hint(), (0, Some(initial_len))); |
| 1258 | + while let Some(_) = iter.next() { |
| 1259 | + count += 1; |
| 1260 | + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); |
| 1261 | + } |
| 1262 | + assert_eq!(iter.size_hint(), (0, Some(0))); |
| 1263 | + assert_eq!(iter.next(), None); |
| 1264 | + assert_eq!(iter.size_hint(), (0, Some(0))); |
| 1265 | + } |
| 1266 | + |
| 1267 | + assert_eq!(count, initial_len); |
| 1268 | + assert_eq!(list.len(), 0); |
| 1269 | + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![]); |
| 1270 | +} |
| 1271 | + |
| 1272 | +#[test] |
| 1273 | +fn extract_if_complex() { |
| 1274 | + { |
| 1275 | + // [+xxx++++++xxxxx++++x+x++] |
| 1276 | + let mut list = [ |
| 1277 | + 1, 2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, |
| 1278 | + 39, |
| 1279 | + ] |
| 1280 | + .into_iter() |
| 1281 | + .collect::<VecDeque<_>>(); |
| 1282 | + |
| 1283 | + let removed = list.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>(); |
| 1284 | + assert_eq!(removed.len(), 10); |
| 1285 | + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); |
| 1286 | + |
| 1287 | + assert_eq!(list.len(), 14); |
| 1288 | + assert_eq!( |
| 1289 | + list.into_iter().collect::<Vec<_>>(), |
| 1290 | + vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] |
| 1291 | + ); |
| 1292 | + } |
| 1293 | + |
| 1294 | + { |
| 1295 | + // [xxx++++++xxxxx++++x+x++] |
| 1296 | + let mut list = |
| 1297 | + [2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36, 37, 39] |
| 1298 | + .into_iter() |
| 1299 | + .collect::<VecDeque<_>>(); |
| 1300 | + |
| 1301 | + let removed = list.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>(); |
| 1302 | + assert_eq!(removed.len(), 10); |
| 1303 | + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); |
| 1304 | + |
| 1305 | + assert_eq!(list.len(), 13); |
| 1306 | + assert_eq!( |
| 1307 | + list.into_iter().collect::<Vec<_>>(), |
| 1308 | + vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39] |
| 1309 | + ); |
| 1310 | + } |
| 1311 | + |
| 1312 | + { |
| 1313 | + // [xxx++++++xxxxx++++x+x] |
| 1314 | + let mut list = |
| 1315 | + [2, 4, 6, 7, 9, 11, 13, 15, 17, 18, 20, 22, 24, 26, 27, 29, 31, 33, 34, 35, 36] |
| 1316 | + .into_iter() |
| 1317 | + .collect::<VecDeque<_>>(); |
| 1318 | + |
| 1319 | + let removed = list.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>(); |
| 1320 | + assert_eq!(removed.len(), 10); |
| 1321 | + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); |
| 1322 | + |
| 1323 | + assert_eq!(list.len(), 11); |
| 1324 | + assert_eq!( |
| 1325 | + list.into_iter().collect::<Vec<_>>(), |
| 1326 | + vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35] |
| 1327 | + ); |
| 1328 | + } |
| 1329 | + |
| 1330 | + { |
| 1331 | + // [xxxxxxxxxx+++++++++++] |
| 1332 | + let mut list = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19] |
| 1333 | + .into_iter() |
| 1334 | + .collect::<VecDeque<_>>(); |
| 1335 | + |
| 1336 | + let removed = list.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>(); |
| 1337 | + assert_eq!(removed.len(), 10); |
| 1338 | + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); |
| 1339 | + |
| 1340 | + assert_eq!(list.len(), 10); |
| 1341 | + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); |
| 1342 | + } |
| 1343 | + |
| 1344 | + { |
| 1345 | + // [+++++++++++xxxxxxxxxx] |
| 1346 | + let mut list = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] |
| 1347 | + .into_iter() |
| 1348 | + .collect::<VecDeque<_>>(); |
| 1349 | + |
| 1350 | + let removed = list.extract_if(|x| *x % 2 == 0).collect::<Vec<_>>(); |
| 1351 | + assert_eq!(removed.len(), 10); |
| 1352 | + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); |
| 1353 | + |
| 1354 | + assert_eq!(list.len(), 10); |
| 1355 | + assert_eq!(list.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); |
| 1356 | + } |
| 1357 | +} |
| 1358 | + |
| 1359 | +#[test] |
| 1360 | +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] |
| 1361 | +fn extract_if_drop_panic_leak() { |
| 1362 | + let d0 = CrashTestDummy::new(0); |
| 1363 | + let d1 = CrashTestDummy::new(1); |
| 1364 | + let d2 = CrashTestDummy::new(2); |
| 1365 | + let d3 = CrashTestDummy::new(3); |
| 1366 | + let d4 = CrashTestDummy::new(4); |
| 1367 | + let d5 = CrashTestDummy::new(5); |
| 1368 | + let d6 = CrashTestDummy::new(6); |
| 1369 | + let d7 = CrashTestDummy::new(7); |
| 1370 | + let mut q = VecDeque::new(); |
| 1371 | + q.push_back(d3.spawn(Panic::Never)); |
| 1372 | + q.push_back(d4.spawn(Panic::Never)); |
| 1373 | + q.push_back(d5.spawn(Panic::Never)); |
| 1374 | + q.push_back(d6.spawn(Panic::Never)); |
| 1375 | + q.push_back(d7.spawn(Panic::Never)); |
| 1376 | + q.push_front(d2.spawn(Panic::Never)); |
| 1377 | + q.push_front(d1.spawn(Panic::InDrop)); |
| 1378 | + q.push_front(d0.spawn(Panic::Never)); |
| 1379 | + |
| 1380 | + catch_unwind(AssertUnwindSafe(|| q.extract_if(|_| true).for_each(drop))).unwrap_err(); |
| 1381 | + |
| 1382 | + assert_eq!(d0.dropped(), 1); |
| 1383 | + assert_eq!(d1.dropped(), 1); |
| 1384 | + assert_eq!(d2.dropped(), 0); |
| 1385 | + assert_eq!(d3.dropped(), 0); |
| 1386 | + assert_eq!(d4.dropped(), 0); |
| 1387 | + assert_eq!(d5.dropped(), 0); |
| 1388 | + assert_eq!(d6.dropped(), 0); |
| 1389 | + assert_eq!(d7.dropped(), 0); |
| 1390 | + drop(q); |
| 1391 | + assert_eq!(d2.dropped(), 1); |
| 1392 | + assert_eq!(d3.dropped(), 1); |
| 1393 | + assert_eq!(d4.dropped(), 1); |
| 1394 | + assert_eq!(d5.dropped(), 1); |
| 1395 | + assert_eq!(d6.dropped(), 1); |
| 1396 | + assert_eq!(d7.dropped(), 1); |
| 1397 | +} |
| 1398 | + |
| 1399 | +#[test] |
| 1400 | +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] |
| 1401 | +fn extract_if_pred_panic_leak() { |
| 1402 | + struct_with_counted_drop!(D(u32), DROPS); |
| 1403 | + |
| 1404 | + let mut q = VecDeque::new(); |
| 1405 | + q.push_back(D(3)); |
| 1406 | + q.push_back(D(4)); |
| 1407 | + q.push_back(D(5)); |
| 1408 | + q.push_back(D(6)); |
| 1409 | + q.push_back(D(7)); |
| 1410 | + q.push_front(D(2)); |
| 1411 | + q.push_front(D(1)); |
| 1412 | + q.push_front(D(0)); |
| 1413 | + |
| 1414 | + _ = catch_unwind(AssertUnwindSafe(|| { |
| 1415 | + q.extract_if(|item| if item.0 >= 2 { panic!() } else { true }).for_each(drop) |
| 1416 | + })); |
| 1417 | + |
| 1418 | + assert_eq!(DROPS.get(), 2); // 0 and 1 |
| 1419 | + assert_eq!(q.len(), 6); |
| 1420 | +} |
0 commit comments