github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/tools/blocksconvert/builder/series_test.go (about) 1 package builder 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "math/rand" 7 "os" 8 "sort" 9 "testing" 10 "time" 11 12 "github.com/prometheus/prometheus/pkg/labels" 13 "github.com/prometheus/prometheus/tsdb/chunks" 14 "github.com/stretchr/testify/require" 15 ) 16 17 type testSeries struct { 18 l labels.Labels 19 cs []chunks.Meta 20 samples uint64 21 minTime, maxTime int64 22 } 23 24 func TestSeries(t *testing.T) { 25 dir, err := ioutil.TempDir("", "series") 26 require.NoError(t, err) 27 t.Cleanup(func() { 28 _ = os.RemoveAll(dir) 29 }) 30 31 series := map[string]testSeries{} 32 33 r := rand.New(rand.NewSource(time.Now().UnixNano())) 34 35 const seriesCount = 100 36 for i := 0; i < seriesCount; i++ { 37 l := labels.Labels{labels.Label{Name: generateString(r), Value: generateString(r)}} 38 series[l.String()] = testSeries{ 39 l: l, 40 cs: []chunks.Meta{{Ref: r.Uint64(), MinTime: r.Int63(), MaxTime: r.Int63()}}, 41 samples: r.Uint64(), 42 minTime: r.Int63(), 43 maxTime: r.Int63(), 44 } 45 } 46 47 sl := newSeriesList(seriesCount/7, dir) 48 49 symbolsMap := map[string]bool{} 50 51 for _, s := range series { 52 require.NoError(t, sl.addSeries(s.l, s.cs, s.samples, s.minTime, s.maxTime)) 53 54 for _, l := range s.l { 55 symbolsMap[l.Name] = true 56 symbolsMap[l.Value] = true 57 } 58 } 59 require.NoError(t, sl.flushSeries()) 60 61 symbols := make([]string, 0, len(symbolsMap)) 62 for s := range symbolsMap { 63 symbols = append(symbols, s) 64 } 65 sort.Strings(symbols) 66 67 sit, err := sl.symbolsIterator() 68 require.NoError(t, err) 69 70 for _, exp := range symbols { 71 s, ok := sit.Next() 72 require.True(t, ok) 73 require.Equal(t, exp, s) 74 } 75 _, ok := sit.Next() 76 require.False(t, ok) 77 require.NoError(t, sit.Error()) 78 require.NoError(t, sit.Close()) 79 80 prevLabels := labels.Labels{} 81 82 rit, err := sl.seriesIterator() 83 require.NoError(t, err) 84 85 for len(series) > 0 { 86 s, ok := rit.Next() 87 require.True(t, ok) 88 89 es, ok := series[s.Metric.String()] 90 require.True(t, ok) 91 require.True(t, labels.Compare(prevLabels, s.Metric) < 0) 92 93 prevLabels = s.Metric 94 95 require.Equal(t, 0, labels.Compare(es.l, s.Metric)) 96 97 for ix, c := range es.cs { 98 require.True(t, ix < len(s.Chunks)) 99 require.Equal(t, c.Ref, s.Chunks[ix].Ref) 100 require.Equal(t, c.MinTime, s.Chunks[ix].MinTime) 101 require.Equal(t, c.MaxTime, s.Chunks[ix].MaxTime) 102 } 103 104 require.Equal(t, es.minTime, s.MinTime) 105 require.Equal(t, es.maxTime, s.MaxTime) 106 require.Equal(t, es.samples, s.Samples) 107 108 delete(series, s.Metric.String()) 109 } 110 111 _, ok = rit.Next() 112 require.False(t, ok) 113 require.NoError(t, rit.Error()) 114 require.NoError(t, rit.Close()) 115 } 116 117 func generateString(r *rand.Rand) string { 118 buf := bytes.Buffer{} 119 120 chars := "abcdefghijklmnopqrstuvxyzABCDEFGHIJKLMNOPQRSTUVXYZ01234567890_" 121 122 for l := 20 + r.Intn(100); l > 0; l-- { 123 buf.WriteByte(chars[r.Intn(len(chars))]) 124 } 125 126 return buf.String() 127 }