@@ -1918,6 +1918,184 @@ func (s *testRegionCacheSuite) TestLocateBucket() {
19181918 }
19191919}
19201920
1921+ // TestBucketClampingToRegion tests that bucket boundaries exceeding region
1922+ // boundaries are clamped correctly.
1923+ func TestBucketClampingToRegion (t * testing.T ) {
1924+ tests := []struct {
1925+ name string
1926+ regionStart []byte
1927+ regionEnd []byte
1928+ bucketStart []byte
1929+ bucketEnd []byte
1930+ wantStart []byte
1931+ wantEnd []byte
1932+ shouldBeClamped bool
1933+ }{
1934+ {
1935+ name : "bucket within region - no clamping" ,
1936+ regionStart : []byte ("a" ),
1937+ regionEnd : []byte ("z" ),
1938+ bucketStart : []byte ("f" ),
1939+ bucketEnd : []byte ("m" ),
1940+ wantStart : []byte ("f" ),
1941+ wantEnd : []byte ("m" ),
1942+ shouldBeClamped : false ,
1943+ },
1944+ {
1945+ name : "bucket start before region - clamp start" ,
1946+ regionStart : []byte ("f" ),
1947+ regionEnd : []byte ("z" ),
1948+ bucketStart : []byte ("a" ), // Before region start
1949+ bucketEnd : []byte ("m" ),
1950+ wantStart : []byte ("f" ), // Clamped to region start
1951+ wantEnd : []byte ("m" ),
1952+ shouldBeClamped : true ,
1953+ },
1954+ {
1955+ name : "bucket end after region - clamp end" ,
1956+ regionStart : []byte ("a" ),
1957+ regionEnd : []byte ("m" ),
1958+ bucketStart : []byte ("f" ),
1959+ bucketEnd : []byte ("z" ), // After region end
1960+ wantStart : []byte ("f" ),
1961+ wantEnd : []byte ("m" ), // Clamped to region end
1962+ shouldBeClamped : true ,
1963+ },
1964+ {
1965+ name : "bucket exceeds both boundaries - clamp both" ,
1966+ regionStart : []byte ("f" ),
1967+ regionEnd : []byte ("m" ),
1968+ bucketStart : []byte ("a" ), // Before region start
1969+ bucketEnd : []byte ("z" ), // After region end
1970+ wantStart : []byte ("f" ), // Clamped to region start
1971+ wantEnd : []byte ("m" ), // Clamped to region end
1972+ shouldBeClamped : true ,
1973+ },
1974+ {
1975+ name : "empty region start - bucket start not clamped" ,
1976+ regionStart : []byte {}, // Beginning of keyspace
1977+ regionEnd : []byte ("m" ),
1978+ bucketStart : []byte ("a" ),
1979+ bucketEnd : []byte ("z" ),
1980+ wantStart : []byte ("a" ),
1981+ wantEnd : []byte ("m" ), // Only end clamped
1982+ shouldBeClamped : true ,
1983+ },
1984+ {
1985+ name : "empty region end - bucket end not clamped" ,
1986+ regionStart : []byte ("f" ),
1987+ regionEnd : []byte {}, // End of keyspace (infinity)
1988+ bucketStart : []byte ("a" ),
1989+ bucketEnd : []byte ("z" ),
1990+ wantStart : []byte ("f" ), // Only start clamped
1991+ wantEnd : []byte ("z" ),
1992+ shouldBeClamped : true ,
1993+ },
1994+ {
1995+ name : "bucket completely before region - fallback to region" ,
1996+ regionStart : []byte ("m" ),
1997+ regionEnd : []byte ("z" ),
1998+ bucketStart : []byte ("a" ),
1999+ bucketEnd : []byte ("f" ), // Ends before region starts
2000+ wantStart : []byte ("m" ), // Falls back to region boundaries
2001+ wantEnd : []byte ("z" ),
2002+ shouldBeClamped : true ,
2003+ },
2004+ {
2005+ name : "bucket with empty startKey - clamp to region start" ,
2006+ regionStart : []byte ("f" ),
2007+ regionEnd : []byte ("z" ),
2008+ bucketStart : []byte {}, // Beginning of keyspace
2009+ bucketEnd : []byte ("m" ),
2010+ wantStart : []byte ("f" ), // Clamped to region start
2011+ wantEnd : []byte ("m" ),
2012+ shouldBeClamped : true ,
2013+ },
2014+ {
2015+ name : "bucket with empty endKey - clamp to region end" ,
2016+ regionStart : []byte ("a" ),
2017+ regionEnd : []byte ("m" ),
2018+ bucketStart : []byte ("f" ),
2019+ bucketEnd : []byte {}, // End of keyspace (infinity)
2020+ wantStart : []byte ("f" ),
2021+ wantEnd : []byte ("m" ), // Clamped to region end
2022+ shouldBeClamped : true ,
2023+ },
2024+ {
2025+ name : "bucket with empty startKey and region with empty startKey - no start clamping" ,
2026+ regionStart : []byte {}, // Beginning of keyspace
2027+ regionEnd : []byte ("z" ),
2028+ bucketStart : []byte {}, // Beginning of keyspace
2029+ bucketEnd : []byte ("m" ),
2030+ wantStart : []byte {}, // No clamping needed
2031+ wantEnd : []byte ("m" ),
2032+ shouldBeClamped : false ,
2033+ },
2034+ {
2035+ name : "bucket with empty endKey and region with empty endKey - no end clamping" ,
2036+ regionStart : []byte ("a" ),
2037+ regionEnd : []byte {}, // End of keyspace (infinity)
2038+ bucketStart : []byte ("f" ),
2039+ bucketEnd : []byte {}, // End of keyspace (infinity)
2040+ wantStart : []byte ("f" ),
2041+ wantEnd : []byte {}, // No clamping needed
2042+ shouldBeClamped : false ,
2043+ },
2044+ {
2045+ name : "bucket spanning full keyspace - clamp to region" ,
2046+ regionStart : []byte ("f" ),
2047+ regionEnd : []byte ("m" ),
2048+ bucketStart : []byte {}, // Beginning of keyspace
2049+ bucketEnd : []byte {}, // End of keyspace (infinity)
2050+ wantStart : []byte ("f" ), // Clamped to region start
2051+ wantEnd : []byte ("m" ), // Clamped to region end
2052+ shouldBeClamped : true ,
2053+ },
2054+ {
2055+ name : "infinity region - no clamping needed" ,
2056+ regionStart : []byte {}, // Beginning of keyspace
2057+ regionEnd : []byte {}, // End of keyspace (infinity)
2058+ bucketStart : []byte ("a" ),
2059+ bucketEnd : []byte ("z" ),
2060+ wantStart : []byte ("a" ),
2061+ wantEnd : []byte ("z" ),
2062+ shouldBeClamped : false ,
2063+ },
2064+ }
2065+
2066+ for _ , tt := range tests {
2067+ t .Run (tt .name , func (t * testing.T ) {
2068+ loc := & KeyLocation {
2069+ Region : RegionVerID {id : 1 },
2070+ StartKey : tt .regionStart ,
2071+ EndKey : tt .regionEnd ,
2072+ }
2073+ bucket := & Bucket {
2074+ StartKey : tt .bucketStart ,
2075+ EndKey : tt .bucketEnd ,
2076+ }
2077+
2078+ result := loc .clampBucketToRegion (bucket )
2079+
2080+ if ! bytes .Equal (result .StartKey , tt .wantStart ) {
2081+ t .Errorf ("StartKey = %q, want %q" , result .StartKey , tt .wantStart )
2082+ }
2083+ if ! bytes .Equal (result .EndKey , tt .wantEnd ) {
2084+ t .Errorf ("EndKey = %q, want %q" , result .EndKey , tt .wantEnd )
2085+ }
2086+
2087+ // Verify that clamped bucket is different from original if clamping was expected
2088+ isSameBucket := result == bucket
2089+ if tt .shouldBeClamped && isSameBucket {
2090+ t .Error ("Expected bucket to be clamped (new object), but got same object" )
2091+ }
2092+ if ! tt .shouldBeClamped && ! isSameBucket {
2093+ t .Error ("Expected no clamping (same object), but got new object" )
2094+ }
2095+ })
2096+ }
2097+ }
2098+
19212099func (s * testRegionCacheSuite ) TestRemoveIntersectingRegions () {
19222100 // Split at "b", "c", "d", "e"
19232101 regions := s .cluster .AllocIDs (4 )
0 commit comments