@@ -873,8 +873,7 @@ TEST(DbTest, history_length_adjustment_never_under_min)
873873    remove (dbname);
874874}
875875
876- TEST_F (
877-     OnDiskDbWithFileFixture, read_only_db_traverse_fail_upon_version_expiration)
876+ TEST_F (OnDiskDbWithFileFixture, read_only_db_traverse_as_version_expire)
878877{
879878    struct  TraverseMachinePruneHistory  final  : public TraverseMachine
880879    {
@@ -927,6 +926,12 @@ TEST_F(
927926        {
928927            return  std::make_unique<TraverseMachinePruneHistory>(*this );
929928        }
929+ 
930+         void  reset ()
931+         {
932+             path = Nibbles{};
933+             has_done_callback = false ;
934+         }
930935    };
931936
932937    EXPECT_EQ (db.get_history_length (), MPT_TEST_HISTORY_LENGTH);
@@ -942,24 +947,51 @@ TEST_F(
942947        root = db.upsert (std::move (root), std::move (ls), version);
943948    };
944949
945-     while  (version < MPT_TEST_HISTORY_LENGTH -  1 ) {
950+     while  (version < MPT_TEST_HISTORY_LENGTH) {
946951        upsert_once ();
947952        ++version;
948953    }
949954    //  traverse
950-     AsyncIOContext io_ctx{ReadOnlyOnDiskDbConfig{.dbname_paths  = {dbname}}};
951-     Db ro_db{io_ctx};
952955    TraverseMachinePruneHistory traverse_machine{upsert_once};
953-     auto  const  read_version = ro_db.get_earliest_version ();
954-     ASSERT_EQ (read_version, 0 );
955-     NodeCursor const  root_cursor{ro_db.load_root_for_version (read_version)};
956-     ASSERT_EQ (
957-         ro_db.traverse (root_cursor, traverse_machine, read_version), true );
958-     EXPECT_EQ (ro_db.get_earliest_version (), read_version);
959-     ++version;
960-     ASSERT_EQ (
961-         ro_db.traverse (root_cursor, traverse_machine, read_version), false );
962-     EXPECT_GT (ro_db.get_earliest_version (), read_version);
956+ 
957+     //  Helper to test both traverse APIs
958+     auto  test_traverse = [&](auto  &db, auto  traverse_fn) {
959+         traverse_machine.reset ();
960+         version = db.get_latest_version ();
961+         auto  const  latest_version = db.get_latest_version ();
962+         auto  const  earliest_version = db.get_earliest_version ();
963+         auto  root_cursor = db.find ({}, latest_version).value ();
964+         ASSERT_EQ (
965+             traverse_fn (root_cursor, traverse_machine, latest_version), true );
966+         EXPECT_EQ (traverse_machine.path .nibble_size (), 0u );
967+         EXPECT_EQ (db.get_earliest_version (), earliest_version);
968+ 
969+         //  traverse earliest will erase earliest version
970+         root_cursor = db.find ({}, earliest_version).value ();
971+         ++version;
972+         traverse_machine.reset ();
973+         ASSERT_EQ (
974+             traverse_fn (root_cursor, traverse_machine, earliest_version),
975+             false );
976+         EXPECT_GT (db.get_earliest_version (), earliest_version);
977+         EXPECT_EQ (traverse_machine.path .nibble_size (), 0u );
978+     };
979+ 
980+     {
981+         AsyncIOContext io_ctx{ReadOnlyOnDiskDbConfig{.dbname_paths  = {dbname}}};
982+         Db ro_db{io_ctx};
983+         //  Test both APIs
984+         test_traverse (ro_db, [&](auto  &&...args ) {
985+             return  ro_db.traverse_blocking (args...);
986+         });
987+         test_traverse (
988+             ro_db, [&](auto  &&...args ) { return  ro_db.traverse (args...); });
989+     }
990+     {
991+         RODb ro_db (ReadOnlyOnDiskDbConfig{.dbname_paths  = {dbname}});
992+         test_traverse (
993+             ro_db, [&](auto  &&...args ) { return  ro_db.traverse (args...); });
994+     }
963995}
964996
965997TEST_F (OnDiskDbWithFileFixture, benchmark_blocking_parallel_traverse)
@@ -1568,6 +1600,7 @@ TYPED_TEST(DbTraverseTest, trimmed_traverse)
15681600    //  Trimmed traversal
15691601    struct  TrimmedTraverse  : public  TraverseMachine 
15701602    {
1603+         unsigned  curr_level{0 };
15711604        size_t  &num_leaves;
15721605
15731606        TrimmedTraverse (size_t  &num_leaves)
@@ -1584,10 +1617,14 @@ TYPED_TEST(DbTraverseTest, trimmed_traverse)
15841617            if  (node.has_value ()) {
15851618                ++num_leaves;
15861619            }
1620+             ++curr_level;
15871621            return  true ;
15881622        }
15891623
1590-         virtual  void  up (unsigned  char  const , Node const  &) override  {}
1624+         virtual  void  up (unsigned  char  const , Node const  &) override 
1625+         {
1626+             --curr_level;
1627+         }
15911628
15921629        virtual  std::unique_ptr<TraverseMachine> clone () const  override 
15931630        {
@@ -1610,13 +1647,15 @@ TYPED_TEST(DbTraverseTest, trimmed_traverse)
16101647        TrimmedTraverse traverse{num_leaves};
16111648        ASSERT_TRUE (
16121649            this ->db .traverse (res_cursor.value (), traverse, this ->block_id ));
1650+         ASSERT_EQ (traverse.curr_level , 0 );
16131651        EXPECT_EQ (num_leaves, 2 );
16141652    }
16151653    {
16161654        size_t  num_leaves = 0 ;
16171655        TrimmedTraverse traverse{num_leaves};
16181656        ASSERT_TRUE (this ->db .traverse_blocking (
16191657            res_cursor.value (), traverse, this ->block_id ));
1658+         ASSERT_EQ (traverse.curr_level , 0 );
16201659        EXPECT_EQ (num_leaves, 2 );
16211660    }
16221661}
0 commit comments