@@ -13,6 +13,7 @@ import (
1313
1414const (
1515 storeKey1 = "store1"
16+ storeKey2 = "store2"
1617)
1718
1819// StorageTestSuite defines a reusable test suite for all storage backends.
@@ -1254,3 +1255,65 @@ func (s *StorageTestSuite) TestDatabaseRawImport() {
12541255 s .Require ().Equal ([]byte (fmt .Sprintf ("value%03d" , i )), val )
12551256 }
12561257}
1258+
1259+ // Verifies that ReverseIterator(nil, nil) is clamped to the caller's prefix
1260+ // via prefixEnd()/UpperBound and does **not** spill into the next module.
1261+ func (s * StorageTestSuite ) TestDatabaseReverseIteratorPrefixIsolation () {
1262+
1263+ db , err := s .NewDB (s .T ().TempDir (), s .Config )
1264+ s .Require ().NoError (err )
1265+ defer db .Close ()
1266+
1267+ // store1 : key000-key009
1268+ // store2 : key000-key009 (different prefix, same suffixes)
1269+ var (
1270+ keys1 , vals1 [][]byte
1271+ keys2 , vals2 [][]byte
1272+ )
1273+ for i := 0 ; i < 10 ; i ++ {
1274+ k := []byte (fmt .Sprintf ("key%03d" , i ))
1275+ v1 := []byte (fmt .Sprintf ("val1-%03d" , i ))
1276+ v2 := []byte (fmt .Sprintf ("val2-%03d" , i ))
1277+
1278+ keys1 = append (keys1 , k )
1279+ vals1 = append (vals1 , v1 )
1280+
1281+ keys2 = append (keys2 , k )
1282+ vals2 = append (vals2 , v2 )
1283+ }
1284+
1285+ s .Require ().NoError (DBApplyChangeset (db , 1 , storeKey1 , keys1 , vals1 ))
1286+ s .Require ().NoError (DBApplyChangeset (db , 1 , storeKey2 , keys2 , vals2 ))
1287+
1288+ // ---------- nil / nil reverse scan on store1 ----------
1289+ itr , err := db .ReverseIterator (storeKey1 , 1 , nil , nil )
1290+ s .Require ().NoError (err )
1291+ defer itr .Close ()
1292+
1293+ // We should see exactly the 10 keys from store1, in reverse order,
1294+ // and we should *never* see a key that belongs to store2.
1295+ expectedI := 9
1296+ count := 0
1297+ for ; itr .Valid (); itr .Next () {
1298+ wantKey := []byte (fmt .Sprintf ("key%03d" , expectedI ))
1299+ s .Require ().Equal (wantKey , itr .Key (), "unexpected key from iterator" )
1300+ s .Require ().Equal ([]byte (fmt .Sprintf ("val1-%03d" , expectedI )), itr .Value ())
1301+
1302+ s .Require ().NotContains (string (itr .Key ()), "val2-" )
1303+
1304+ expectedI --
1305+ count ++
1306+ }
1307+ s .Require ().Equal (10 , count , "iterator should yield exactly the 10 keys in store1" )
1308+ s .Require ().NoError (itr .Error ())
1309+
1310+ itr2 , err := db .ReverseIterator (storeKey2 , 1 , nil , nil )
1311+ s .Require ().NoError (err )
1312+ defer itr2 .Close ()
1313+
1314+ count = 0
1315+ for ; itr2 .Valid (); itr2 .Next () {
1316+ count ++
1317+ }
1318+ s .Require ().Equal (10 , count , "store2 should have its own 10 keys" )
1319+ }
0 commit comments