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  }