diff --git a/storage/local/chunk/varbit.go b/storage/local/chunk/varbit.go index 2ec59efd34..2b13d57d9c 100644 --- a/storage/local/chunk/varbit.go +++ b/storage/local/chunk/varbit.go @@ -1040,7 +1040,7 @@ func (it *varbitChunkIterator) FindAtOrBefore(t model.Time) bool { prevT = model.Earliest prevV model.SampleValue ) - for it.Scan() && t.After(it.t) { + for it.Scan() && !t.Before(it.t) { prevT = it.t prevV = it.v // TODO(beorn7): If we are in a repeat, we could iterate forward diff --git a/storage/local/storage_test.go b/storage/local/storage_test.go index 2ff4c26861..da6d496493 100644 --- a/storage/local/storage_test.go +++ b/storage/local/storage_test.go @@ -980,6 +980,28 @@ func testValueAtOrBeforeTime(t *testing.T, encoding chunk.Encoding) { if expected.Value != actual.Value { t.Errorf("3.2. Got %v; want %v", actual.Value, expected.Value) } + + // #4 Query alternatingly exactly on and just between timestamps. + // Exposes issue #2965. + for i, expected := range samples { + i *= 2 + actual := it.ValueAtOrBeforeTime(expected.Timestamp) + if expected.Timestamp != actual.Timestamp { + t.Errorf("4.%d. Got %v; want %v", i, actual.Timestamp, expected.Timestamp) + } + if expected.Value != actual.Value { + t.Errorf("4.%d. Got %v; want %v", i, actual.Value, expected.Value) + } + + i++ + actual = it.ValueAtOrBeforeTime(expected.Timestamp + 1) + if expected.Timestamp != actual.Timestamp { + t.Errorf("4.%d. Got %v; want %v", i, actual.Timestamp, expected.Timestamp) + } + if expected.Value != actual.Value { + t.Errorf("4.%d. Got %v; want %v", i, actual.Value, expected.Value) + } + } } func TestValueAtTimeChunkType0(t *testing.T) {