From c06292af2f965d386e6639e7603489e83f452f0d Mon Sep 17 00:00:00 2001 From: beorn7 Date: Fri, 21 Jul 2017 16:25:24 +0200 Subject: [PATCH 1/2] Add test to expose #2965 --- storage/local/storage_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/storage/local/storage_test.go b/storage/local/storage_test.go index 2ff4c2686..da6d49649 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) { From ea5e7eafde8e65c3a394801e1b15378b1ef1f58e Mon Sep 17 00:00:00 2001 From: beorn7 Date: Fri, 21 Jul 2017 16:35:15 +0200 Subject: [PATCH 2/2] Fix #2965 We would overscan when hitting a value directly, interspersed with samples in between timestamps. Apparently, that happens rarely enough that it was only noticed recently. --- storage/local/chunk/varbit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/local/chunk/varbit.go b/storage/local/chunk/varbit.go index 2ec59efd3..2b13d57d9 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