diff --git a/cmd/segment-reaper/bitmask.go b/cmd/segment-reaper/bitmask.go index 3660b8304..3272f981a 100644 --- a/cmd/segment-reaper/bitmask.go +++ b/cmd/segment-reaper/bitmask.go @@ -74,12 +74,32 @@ func (bytes *bitArray) Count() int { // IsSequence returns true if mask has only tracked a correlative sequence of // indexes starting from index 0. func (bytes *bitArray) IsSequence() bool { - ones := bytes.Count() - zeros := 0 - for byteIndex := len(*bytes) - 1; byteIndex >= 0 && zeros%8 == 0; byteIndex-- { - zeros = bits.LeadingZeros8((*bytes)[byteIndex]) + // find the last byte of the sequence that contains some one + var i int + for i = len(*bytes) - 1; i >= 0; i-- { + zeros := bits.LeadingZeros8((*bytes)[i]) + if zeros == 8 { + continue + } + + ones := bits.OnesCount8((*bytes)[i]) + if zeros+ones != 8 { + // zeros and ones in this byte aren't in sequence + return false + } + + break } - return (zeros + ones) == len(*bytes)*8 + + // The rest of the bytes of the sequence must only contains ones + i-- + for ; i >= 0; i-- { + if (*bytes)[i] != 255 { + return false + } + } + + return true } // Length returns the current size of the array in bits. diff --git a/cmd/segment-reaper/bitmask_test.go b/cmd/segment-reaper/bitmask_test.go index 8e8c3cd61..eb7a0ed36 100644 --- a/cmd/segment-reaper/bitmask_test.go +++ b/cmd/segment-reaper/bitmask_test.go @@ -186,36 +186,6 @@ func TestBitmask(t *testing.T) { assert.True(t, ok) }) - t.Run("sequence started index 0", func(t *testing.T) { - var ( - numIndexes = rand.Intn(61) + 2 - bits bitArray - ) - - for i := 0; i < numIndexes; i++ { - err := bits.Set(i) - require.NoError(t, err, "Set") - } - - ok := bits.IsSequence() - assert.True(t, ok) - }) - - t.Run("sequence started other index than 0", func(t *testing.T) { - var ( - startIndex = rand.Intn(62) + 1 - bits bitArray - ) - - for i := startIndex; i < 64; i++ { - err := bits.Set(i) - require.NoError(t, err, "Set") - } - - ok := bits.IsSequence() - assert.False(t, ok) - }) - t.Run("no sequence", func(t *testing.T) { var bits bitArray @@ -250,7 +220,68 @@ func TestBitmask(t *testing.T) { assert.False(t, ok) }) + testCases := []struct { + name string + startIndex int + numIndexes int + isSequence bool + }{ + { + name: "sequence starts at index 0", + startIndex: 0, + numIndexes: rand.Intn(5000) + 1, + isSequence: true, + }, + { + name: "sequence starts at index 8 until index 15", + startIndex: 8, + numIndexes: 15, + isSequence: false, + }, + { + name: "sequence starts at index 8 until index 16", + startIndex: 8, + numIndexes: 16, + isSequence: false, + }, + { + name: "sequence starts at index 8 until index 17", + startIndex: 8, + numIndexes: 17, + isSequence: false, + }, + { + name: "sequence starts at index 8 until index 23", + startIndex: 8, + numIndexes: 23, + isSequence: false, + }, + { + name: "sequence starts at other index than 0", + startIndex: rand.Intn(1000) + 1, + numIndexes: rand.Intn(5000) + 1002, + isSequence: false, + }, + } + + for i := range testCases { + tc := testCases[i] + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + var bits bitArray + for i := tc.startIndex; i < tc.numIndexes; i++ { + err := bits.Set(i) + require.NoError(t, err, "Set") + } + + require.Equalf(t, tc.isSequence, bits.IsSequence(), + "startIndex: %d, numIndexes: %d", tc.startIndex, tc.numIndexes, + ) + }) + } }) + t.Run("Unset", func(t *testing.T) { t.Run("ok", func(t *testing.T) { var (