@@ -4,6 +4,7 @@ use std::{path::PathBuf, sync::Arc};
44use crate :: object_store:: { memory:: InMemory , path:: Path , ObjectStore } ;
55use futures:: executor:: block_on;
66use itertools:: Itertools ;
7+ use test_log:: test;
78use url:: Url ;
89
910use crate :: actions:: visitors:: AddVisitor ;
@@ -27,7 +28,7 @@ use crate::snapshot::LastCheckpointHint;
2728use crate :: utils:: test_utils:: { assert_batch_matches, Action } ;
2829use crate :: {
2930 DeltaResult , Engine as _, EngineData , Expression , FileMeta , PredicateRef , RowVisitor ,
30- StorageHandler , Table ,
31+ StorageHandler , Table , Version ,
3132} ;
3233use test_utils:: { compacted_log_path_for_versions, delta_path_for_version} ;
3334
@@ -1325,12 +1326,12 @@ fn test_create_checkpoint_stream_reads_checkpoint_file_and_returns_sidecar_batch
13251326 Ok ( ( ) )
13261327}
13271328
1328- fn test_compaction_listing (
1329+ fn create_segment_for (
13291330 commit_versions : & [ u64 ] ,
13301331 compaction_versions : & [ ( u64 , u64 ) ] ,
13311332 checkpoint_version : Option < u64 > ,
13321333 version_to_load : Option < u64 > ,
1333- ) {
1334+ ) -> LogSegment {
13341335 let mut paths: Vec < Path > = commit_versions
13351336 . iter ( )
13361337 . map ( |version| delta_path_for_version ( * version, "json" ) )
@@ -1347,10 +1348,46 @@ fn test_compaction_listing(
13471348 ) ) ;
13481349 }
13491350 let ( storage, log_root) = build_log_with_paths_and_checkpoint ( & paths, None ) ;
1350- let log_segment =
1351- LogSegment :: for_snapshot ( storage. as_ref ( ) , log_root. clone ( ) , None , version_to_load)
1352- . unwrap ( ) ;
1351+ LogSegment :: for_snapshot ( storage. as_ref ( ) , log_root. clone ( ) , None , version_to_load) . unwrap ( )
1352+ }
13531353
1354+ #[ test]
1355+ fn test_list_log_files_with_version ( ) -> DeltaResult < ( ) > {
1356+ let ( storage, log_root) = build_log_with_paths_and_checkpoint (
1357+ & [
1358+ delta_path_for_version ( 0 , "json" ) ,
1359+ delta_path_for_version ( 0 , "crc" ) ,
1360+ delta_path_for_version ( 1 , "json" ) ,
1361+ delta_path_for_version ( 1 , "crc" ) ,
1362+ delta_path_for_version ( 2 , "json" ) ,
1363+ ] ,
1364+ None ,
1365+ ) ;
1366+ let result = list_log_files_with_version ( storage. as_ref ( ) , & log_root, Some ( 0 ) , None ) ?;
1367+ let latest_crc = result. latest_crc_file . unwrap ( ) ;
1368+ assert_eq ! (
1369+ latest_crc. location. location. path( ) ,
1370+ "/_delta_log/00000000000000000001.crc" . to_string( )
1371+ ) ;
1372+ assert_eq ! ( latest_crc. version, 1 ) ;
1373+ assert_eq ! ( latest_crc. filename, "00000000000000000001.crc" . to_string( ) ) ;
1374+ assert_eq ! ( latest_crc. extension, "crc" . to_string( ) ) ;
1375+ assert_eq ! ( latest_crc. file_type, LogPathFileType :: Crc ) ;
1376+ Ok ( ( ) )
1377+ }
1378+
1379+ fn test_compaction_listing (
1380+ commit_versions : & [ u64 ] ,
1381+ compaction_versions : & [ ( u64 , u64 ) ] ,
1382+ checkpoint_version : Option < u64 > ,
1383+ version_to_load : Option < u64 > ,
1384+ ) {
1385+ let log_segment = create_segment_for (
1386+ commit_versions,
1387+ compaction_versions,
1388+ checkpoint_version,
1389+ version_to_load,
1390+ ) ;
13541391 let version_to_load = version_to_load. unwrap_or ( u64:: MAX ) ;
13551392 let checkpoint_cuttoff = checkpoint_version. map ( |v| v as i64 ) . unwrap_or ( -1 ) ;
13561393 let expected_commit_versions: Vec < & u64 > = commit_versions
@@ -1478,27 +1515,188 @@ fn test_compaction_starts_at_checkpoint() {
14781515 ) ;
14791516}
14801517
1518+ enum ExpectedFile {
1519+ Commit ( Version ) ,
1520+ Compaction ( Version , Version ) ,
1521+ }
1522+
1523+ fn test_commit_cover (
1524+ commit_versions : & [ u64 ] ,
1525+ compaction_versions : & [ ( u64 , u64 ) ] ,
1526+ checkpoint_version : Option < u64 > ,
1527+ version_to_load : Option < u64 > ,
1528+ expected_files : & [ ExpectedFile ] ,
1529+ ) {
1530+ let log_segment = create_segment_for (
1531+ commit_versions,
1532+ compaction_versions,
1533+ checkpoint_version,
1534+ version_to_load,
1535+ ) ;
1536+ let cover = log_segment. find_commit_cover ( ) ;
1537+ // our test-utils include "_delta_log" in the path, which is already in log_segment.log_root, so
1538+ // we don't use them. TODO: Unify this
1539+ let expected_locations = expected_files. iter ( ) . map ( |ef| match ef {
1540+ ExpectedFile :: Commit ( version) => log_segment
1541+ . log_root
1542+ . join ( & format ! ( "{version:020}.json" ) )
1543+ . expect ( "Couldn't join" ) ,
1544+ ExpectedFile :: Compaction ( lo, hi) => log_segment
1545+ . log_root
1546+ . join ( & format ! ( "{lo:020}.{hi:020}.compacted.json" ) )
1547+ . expect ( "Couldn't join" ) ,
1548+ } ) ;
1549+ assert_eq ! ( cover. len( ) , expected_locations. len( ) ) ;
1550+ for ( location, expected_location) in cover. iter ( ) . zip ( expected_locations) {
1551+ assert_eq ! ( location. location, expected_location) ;
1552+ }
1553+ }
1554+
14811555#[ test]
1482- fn test_list_log_files_with_version ( ) -> DeltaResult < ( ) > {
1483- let ( storage, log_root) = build_log_with_paths_and_checkpoint (
1556+ fn test_commit_cover_one_compaction ( ) {
1557+ test_commit_cover (
1558+ & [ 0 , 1 , 2 ] ,
1559+ & [ ( 1 , 2 ) ] ,
1560+ None , // checkpoint version
1561+ None , // version to load
1562+ & [ ExpectedFile :: Compaction ( 1 , 2 ) , ExpectedFile :: Commit ( 0 ) ] ,
1563+ ) ;
1564+ }
1565+
1566+ #[ test]
1567+ fn test_commit_cover_in_version_range ( ) {
1568+ test_commit_cover (
1569+ & [ 0 , 1 , 2 , 3 ] ,
1570+ & [ ( 1 , 2 ) ] ,
1571+ None , // checkpoint version
1572+ Some ( 2 ) , // version to load
1573+ & [ ExpectedFile :: Compaction ( 1 , 2 ) , ExpectedFile :: Commit ( 0 ) ] ,
1574+ ) ;
1575+ }
1576+
1577+ #[ test]
1578+ fn test_commit_cover_out_of_version_range ( ) {
1579+ test_commit_cover (
1580+ & [ 0 , 1 , 2 , 3 , 4 ] ,
1581+ & [ ( 1 , 3 ) ] ,
1582+ None , // checkpoint version
1583+ Some ( 2 ) , // version to load
14841584 & [
1485- delta_path_for_version ( 0 , "json" ) ,
1486- delta_path_for_version ( 0 , "crc" ) ,
1487- delta_path_for_version ( 1 , "json" ) ,
1488- delta_path_for_version ( 1 , "crc" ) ,
1489- delta_path_for_version ( 2 , "json" ) ,
1585+ ExpectedFile :: Commit ( 2 ) ,
1586+ ExpectedFile :: Commit ( 1 ) ,
1587+ ExpectedFile :: Commit ( 0 ) ,
14901588 ] ,
1491- None ,
14921589 ) ;
1493- let result = list_log_files_with_version ( storage. as_ref ( ) , & log_root, Some ( 0 ) , None ) ?;
1494- let latest_crc = result. latest_crc_file . unwrap ( ) ;
1495- assert_eq ! (
1496- latest_crc. location. location. path( ) ,
1497- "/_delta_log/00000000000000000001.crc" . to_string( )
1590+ }
1591+
1592+ #[ test]
1593+ fn test_commit_cover_multi_compaction ( ) {
1594+ test_commit_cover (
1595+ & [ 0 , 1 , 2 , 3 , 4 , 5 ] ,
1596+ & [ ( 1 , 2 ) , ( 3 , 5 ) ] ,
1597+ None , // checkpoint version
1598+ None , //version to load
1599+ & [
1600+ ExpectedFile :: Compaction ( 3 , 5 ) ,
1601+ ExpectedFile :: Compaction ( 1 , 2 ) ,
1602+ ExpectedFile :: Commit ( 0 ) ,
1603+ ] ,
1604+ ) ;
1605+ }
1606+
1607+ #[ test]
1608+ fn test_commit_cover_multi_compaction_one_out_of_range ( ) {
1609+ test_commit_cover (
1610+ & [ 0 , 1 , 2 , 3 , 4 , 5 ] ,
1611+ & [ ( 1 , 2 ) , ( 3 , 5 ) ] ,
1612+ None , // checkpoint version
1613+ Some ( 4 ) , // version to load
1614+ & [
1615+ ExpectedFile :: Commit ( 4 ) ,
1616+ ExpectedFile :: Commit ( 3 ) ,
1617+ ExpectedFile :: Compaction ( 1 , 2 ) ,
1618+ ExpectedFile :: Commit ( 0 ) ,
1619+ ] ,
1620+ ) ;
1621+ }
1622+
1623+ #[ test]
1624+ fn test_commit_cover_compaction_with_checkpoint ( ) {
1625+ test_commit_cover (
1626+ & [ 0 , 1 , 2 , 4 , 5 ] ,
1627+ & [ ( 1 , 2 ) , ( 4 , 5 ) ] ,
1628+ Some ( 3 ) , // checkpoint version
1629+ None , // version to load
1630+ & [ ExpectedFile :: Compaction ( 4 , 5 ) ] ,
1631+ ) ;
1632+ }
1633+
1634+ #[ test]
1635+ fn test_commit_cover_too_early_with_checkpoint ( ) {
1636+ test_commit_cover (
1637+ & [ 0 , 1 , 2 , 4 , 5 ] ,
1638+ & [ ( 1 , 2 ) ] ,
1639+ Some ( 3 ) , // checkpoint version
1640+ None , // version to load
1641+ & [ ExpectedFile :: Commit ( 5 ) , ExpectedFile :: Commit ( 4 ) ] ,
1642+ ) ;
1643+ }
1644+
1645+ #[ test]
1646+ fn test_commit_cover_starts_at_checkpoint ( ) {
1647+ test_commit_cover (
1648+ & [ 0 , 1 , 2 , 4 , 5 ] ,
1649+ & [ ( 3 , 5 ) ] ,
1650+ Some ( 3 ) , // checkpoint version
1651+ None , // version to load
1652+ & [ ExpectedFile :: Commit ( 5 ) , ExpectedFile :: Commit ( 4 ) ] ,
1653+ ) ;
1654+ }
1655+
1656+ #[ test]
1657+ fn test_commit_cover_wider_range ( ) {
1658+ test_commit_cover (
1659+ & Vec :: from_iter ( 0 ..20 ) ,
1660+ & [ ( 0 , 5 ) , ( 0 , 10 ) , ( 5 , 10 ) , ( 13 , 19 ) ] ,
1661+ None , // checkpoint version
1662+ None , // version to load
1663+ & [
1664+ ExpectedFile :: Compaction ( 13 , 19 ) ,
1665+ ExpectedFile :: Commit ( 12 ) ,
1666+ ExpectedFile :: Commit ( 11 ) ,
1667+ ExpectedFile :: Compaction ( 0 , 10 ) ,
1668+ ] ,
1669+ ) ;
1670+ }
1671+
1672+ #[ test]
1673+ fn test_commit_cover_no_compactions ( ) {
1674+ test_commit_cover (
1675+ & Vec :: from_iter ( 0 ..4 ) ,
1676+ & [ ] ,
1677+ None , // checkpoint version
1678+ None , // version to load
1679+ & [
1680+ ExpectedFile :: Commit ( 3 ) ,
1681+ ExpectedFile :: Commit ( 2 ) ,
1682+ ExpectedFile :: Commit ( 1 ) ,
1683+ ExpectedFile :: Commit ( 0 ) ,
1684+ ] ,
1685+ ) ;
1686+ }
1687+
1688+ #[ test]
1689+ fn test_commit_cover_minimal_overlap ( ) {
1690+ test_commit_cover (
1691+ & Vec :: from_iter ( 0 ..6 ) ,
1692+ & [ ( 0 , 2 ) , ( 2 , 5 ) ] ,
1693+ None , // checkpoint version
1694+ None , // version to load
1695+ & [
1696+ ExpectedFile :: Commit ( 5 ) ,
1697+ ExpectedFile :: Commit ( 4 ) ,
1698+ ExpectedFile :: Commit ( 3 ) ,
1699+ ExpectedFile :: Compaction ( 0 , 2 ) ,
1700+ ] ,
14981701 ) ;
1499- assert_eq ! ( latest_crc. version, 1 ) ;
1500- assert_eq ! ( latest_crc. filename, "00000000000000000001.crc" . to_string( ) ) ;
1501- assert_eq ! ( latest_crc. extension, "crc" . to_string( ) ) ;
1502- assert_eq ! ( latest_crc. file_type, LogPathFileType :: Crc ) ;
1503- Ok ( ( ) )
15041702}
0 commit comments