diff --git a/storage/operation/reads_test.go b/storage/operation/reads_test.go index c790ace29e6..17b56b31255 100644 --- a/storage/operation/reads_test.go +++ b/storage/operation/reads_test.go @@ -61,6 +61,92 @@ func TestIterateKeysInPrefixRange(t *testing.T) { }) } +// Verify that when keys are prefixed by two prefixes,we can iterate with either first prefix or second prefix. +func TestIterateHierachicalPrefixes(t *testing.T) { + dbtest.RunWithStorages(t, func(t *testing.T, r storage.Reader, withWriter dbtest.WithWriter) { + keys := [][]byte{ + {0x09, 0x00, 0x00}, + {0x09, 0x00, 0xff}, + {0x09, 0x19, 0xff}, + {0x09, 0xff, 0x00}, + {0x09, 0xff, 0xff}, + {0x10, 0x00, 0x00}, + {0x10, 0x00, 0xff}, + {0x10, 0x19, 0x00}, + {0x10, 0x19, 0xff}, + {0x10, 0x20, 0x00}, + {0x10, 0x20, 0xff}, + {0x10, 0x21, 0x00}, + {0x10, 0x21, 0xff}, + {0x10, 0x22, 0x00}, + {0x10, 0x22, 0xff}, + {0x10, 0xff, 0x00}, + {0x10, 0xff, 0xff}, + {0x11, 0x00, 0x00}, + {0x11, 0x00, 0xff}, + {0x11, 0xff, 0x00}, + {0x11, 0xff, 0xff}, + {0x12, 0x00, 0x00}, + {0x12, 0x00, 0xff}, + {0x12, 0xff, 0x00}, + {0x12, 0xff, 0xff}, + } + + // Insert the keys and values into storage + require.NoError(t, withWriter(func(writer storage.Writer) error { + for _, key := range keys { + err := operation.Upsert(key, []byte{1})(writer) + if err != nil { + return err + } + } + return nil + })) + + // Test iteration with range of first prefixes (0x10 to 0x11) + firstPrefixRangeExpected := [][]byte{ + {0x10, 0x00, 0x00}, + {0x10, 0x00, 0xff}, + {0x10, 0x19, 0x00}, + {0x10, 0x19, 0xff}, + {0x10, 0x20, 0x00}, + {0x10, 0x20, 0xff}, + {0x10, 0x21, 0x00}, + {0x10, 0x21, 0xff}, + {0x10, 0x22, 0x00}, + {0x10, 0x22, 0xff}, + {0x10, 0xff, 0x00}, + {0x10, 0xff, 0xff}, + {0x11, 0x00, 0x00}, + {0x11, 0x00, 0xff}, + {0x11, 0xff, 0x00}, + {0x11, 0xff, 0xff}, + } + firstPrefixRangeActual := make([][]byte, 0) + err := operation.IterateKeysInPrefixRange([]byte{0x10}, []byte{0x11}, func(key []byte) error { + firstPrefixRangeActual = append(firstPrefixRangeActual, key) + return nil + })(r) + require.NoError(t, err, "iterate with range of first prefixes should not return an error") + require.Equal(t, firstPrefixRangeExpected, firstPrefixRangeActual, "iterated values for range of first prefixes should match expected values") + + // Test iteration with range of second prefixes (0x1020 to 0x1021) + secondPrefixRangeActual := make([][]byte, 0) + secondPrefixRangeExpected := [][]byte{ + {0x10, 0x20, 0x00}, + {0x10, 0x20, 0xff}, + {0x10, 0x21, 0x00}, + {0x10, 0x21, 0xff}, + } + err = operation.IterateKeysInPrefixRange([]byte{0x10, 0x20}, []byte{0x10, 0x21}, func(key []byte) error { + secondPrefixRangeActual = append(secondPrefixRangeActual, key) + return nil + })(r) + require.NoError(t, err, "iterate with range of second prefixes should not return an error") + require.Equal(t, secondPrefixRangeExpected, secondPrefixRangeActual, "iterated values for range of second prefixes should match expected values") + }) +} + func TestTraverse(t *testing.T) { dbtest.RunWithStorages(t, func(t *testing.T, r storage.Reader, withWriter dbtest.WithWriter) { keys := [][]byte{ @@ -112,6 +198,7 @@ func TestTraverse(t *testing.T) { }) } +// Verify traversing a subset of keys with only keys traversal func TestTraverseKeyOnly(t *testing.T) { dbtest.RunWithStorages(t, func(t *testing.T, r storage.Reader, withWriter dbtest.WithWriter) { keys := [][]byte{