Fix bug where having one chunk can cause panic

When we have only one chunk that is out of range, then we are returning
it unpopulated (w/o calling `Chunk(ref)`). This would cause a panic
downstream.

Fixes: prometheus/prometheus#2629

Signed-off-by: Goutham Veeramachaneni <cs14btech11014@iith.ac.in>
pull/5805/head
Goutham Veeramachaneni 2017-05-03 22:45:28 +05:30
parent 085991c9da
commit 7bbbd55aad
No known key found for this signature in database
GPG Key ID: F1C217E8E9023CAD
2 changed files with 25 additions and 7 deletions

View File

@ -420,7 +420,7 @@ func (s *populatedChunkSeries) Next() bool {
continue continue
} }
if c.MinTime > s.maxt { if c.MinTime > s.maxt {
chks = chks[from+1 : i] chks = chks[:i]
break break
} }
c.Chunk, s.err = s.chunks.Chunk(c.Ref) c.Chunk, s.err = s.chunks.Chunk(c.Ref)
@ -428,6 +428,8 @@ func (s *populatedChunkSeries) Next() bool {
return false return false
} }
} }
chks = chks[from+1:]
if len(chks) == 0 { if len(chks) == 0 {
continue continue
} }

View File

@ -41,6 +41,12 @@ type mockSeries struct {
iterator func() SeriesIterator iterator func() SeriesIterator
} }
func newSeries(l map[string]string, s []sample) Series {
return &mockSeries{
labels: func() labels.Labels { return labels.FromMap(l) },
iterator: func() SeriesIterator { return newListSeriesIterator(s) },
}
}
func (m *mockSeries) Labels() labels.Labels { return m.labels() } func (m *mockSeries) Labels() labels.Labels { return m.labels() }
func (m *mockSeries) Iterator() SeriesIterator { return m.iterator() } func (m *mockSeries) Iterator() SeriesIterator { return m.iterator() }
@ -81,12 +87,6 @@ func (it *listSeriesIterator) Err() error {
} }
func TestMergedSeriesSet(t *testing.T) { func TestMergedSeriesSet(t *testing.T) {
newSeries := func(l map[string]string, s []sample) Series {
return &mockSeries{
labels: func() labels.Labels { return labels.FromMap(l) },
iterator: func() SeriesIterator { return newListSeriesIterator(s) },
}
}
cases := []struct { cases := []struct {
// The input sets in order (samples in series in b are strictly // The input sets in order (samples in series in b are strictly
@ -885,6 +885,22 @@ func TestPopulatedCSReturnsValidChunkSlice(t *testing.T) {
p.maxt = 9 p.maxt = 9
require.False(t, p.Next()) require.False(t, p.Next())
// Test the case where 1 chunk could cause an unpopulated chunk to be returned.
chunkMetas = [][]*ChunkMeta{
{
{MinTime: 1, MaxTime: 2, Ref: 1},
},
}
m = &mockChunkSeriesSet{l: lbls, cm: chunkMetas, i: -1}
p = &populatedChunkSeries{
set: m,
chunks: cr,
mint: 10,
maxt: 15,
}
require.False(t, p.Next())
return return
} }