package gen import ( "fmt" "math" "strings" "testing" "time" "github.com/google/go-cmp/cmp" "github.com/influxdata/influxdb" "github.com/influxdata/influxdb/models" "github.com/influxdata/influxdb/tsdb" ) var ( org = influxdb.ID(0xff00ff00) bucket = influxdb.ID(0xcc00cc00) orgBucketID = tsdb.EncodeName(org, bucket) ) func sg(m, prefix, field string, counts ...int) SeriesGenerator { spec := TimeSequenceSpec{Count: 1, Start: time.Unix(0, 0), Delta: time.Second} ts := NewTimestampSequenceFromSpec(spec) vs := NewFloatConstantValuesSequence(1) vg := NewTimeFloatValuesSequence(spec.Count, ts, vs) return NewSeriesGenerator(orgBucketID, []byte(field), vg, NewTagsValuesSequenceCounts(m, field, prefix, counts)) } func tags(sb *strings.Builder, m, prefix, f string, vals []int) { sb.WriteByte(',') // max tag width tw := int(math.Ceil(math.Log10(float64(len(vals))))) tf := fmt.Sprintf("%s%%0%dd=value%%d", prefix, tw) tvs := make([]string, 0, len(vals)+2) tvs = append(tvs, fmt.Sprintf("%s=%s", models.MeasurementTagKey, m)) for i := range vals { tvs = append(tvs, fmt.Sprintf(tf, i, vals[i])) } tvs = append(tvs, fmt.Sprintf("%s=%s", models.FieldKeyTagKey, f)) sb.WriteString(strings.Join(tvs, ",")) } func line(name, prefix, field string, vals ...int) string { var sb strings.Builder sb.Write(orgBucketID[:]) tags(&sb, name, prefix, field, vals) sb.WriteString("#!~#") sb.WriteString(field) return sb.String() } func seriesGeneratorString(sg SeriesGenerator) []string { var lines []string for sg.Next() { lines = append(lines, fmt.Sprintf("%s#!~#%s", string(sg.Key()), string(sg.Field()))) } return lines } func TestNewMergedSeriesGenerator(t *testing.T) { tests := []struct { n string s []SeriesGenerator exp []string }{ { n: "single", s: []SeriesGenerator{ sg("cpu", "t", "f0", 2, 1), }, exp: []string{ line("cpu", "t", "f0", 0, 0), line("cpu", "t", "f0", 1, 0), }, }, { n: "multiple,interleaved", s: []SeriesGenerator{ sg("cpu", "t", "f0", 2, 1), sg("cpu", "t", "f1", 2, 1), }, exp: []string{ line("cpu", "t", "f0", 0, 0), line("cpu", "t", "f1", 0, 0), line("cpu", "t", "f0", 1, 0), line("cpu", "t", "f1", 1, 0), }, }, { n: "multiple,sequential", s: []SeriesGenerator{ sg("cpu", "t", "f0", 2), sg("cpu", "u", "f0", 2, 1), }, exp: []string{ line("cpu", "t", "f0", 0), line("cpu", "t", "f0", 1), line("cpu", "u", "f0", 0, 0), line("cpu", "u", "f0", 1, 0), }, }, { n: "multiple,sequential", s: []SeriesGenerator{ sg("m1", "t", "f0", 2, 1), sg("m0", "t", "f0", 2, 1), }, exp: []string{ line("m0", "t", "f0", 0, 0), line("m0", "t", "f0", 1, 0), line("m1", "t", "f0", 0, 0), line("m1", "t", "f0", 1, 0), }, }, { // ensure duplicates are removed n: "duplicates", s: []SeriesGenerator{ sg("cpu", "t", "f0", 2, 1), sg("cpu", "t", "f0", 2, 1), }, exp: []string{ line("cpu", "t", "f0", 0, 0), line("cpu", "t", "f0", 1, 0), }, }, { // ensure duplicates are removed, but non-dupes from same SeriesGenerator // are still included n: "duplicates,multiple,interleaved", s: []SeriesGenerator{ sg("cpu", "t", "f0", 2, 1), sg("cpu", "t", "f1", 2, 1), sg("cpu", "t", "f0", 2, 1), sg("cpu", "t", "f1", 3, 1), }, exp: []string{ line("cpu", "t", "f0", 0, 0), line("cpu", "t", "f1", 0, 0), line("cpu", "t", "f0", 1, 0), line("cpu", "t", "f1", 1, 0), line("cpu", "t", "f1", 2, 0), }, }, } for _, tt := range tests { t.Run(tt.n, func(t *testing.T) { sg := NewMergedSeriesGenerator(tt.s) if got := seriesGeneratorString(sg); !cmp.Equal(got, tt.exp) { t.Errorf("unpexected -got/+exp\n%s", cmp.Diff(got, tt.exp)) } }) } } func TestNewMergedSeriesGeneratorLimit(t *testing.T) { tests := []struct { n string s []SeriesGenerator lim int64 exp []string }{ { n: "single", s: []SeriesGenerator{ sg("cpu", "t", "f0", 4, 1), }, lim: 2, exp: []string{ line("cpu", "t", "f0", 0, 0), line("cpu", "t", "f0", 1, 0), }, }, { n: "multiple,interleaved", s: []SeriesGenerator{ sg("cpu", "t", "f0", 2, 1), sg("cpu", "t", "f1", 2, 1), }, lim: 3, exp: []string{ line("cpu", "t", "f0", 0, 0), line("cpu", "t", "f1", 0, 0), line("cpu", "t", "f0", 1, 0), }, }, { n: "multiple,sequential", s: []SeriesGenerator{ sg("cpu", "t", "f0", 2), sg("cpu", "u", "f0", 2, 1), }, lim: 2, exp: []string{ line("cpu", "t", "f0", 0), line("cpu", "t", "f0", 1), }, }, { n: "multiple,sequential", s: []SeriesGenerator{ sg("m1", "t", "f0", 2, 1), sg("m0", "t", "f0", 2, 1), }, lim: 4, exp: []string{ line("m0", "t", "f0", 0, 0), line("m0", "t", "f0", 1, 0), line("m1", "t", "f0", 0, 0), line("m1", "t", "f0", 1, 0), }, }, } for _, tt := range tests { t.Run(tt.n, func(t *testing.T) { sg := NewMergedSeriesGeneratorLimit(tt.s, tt.lim) if got := seriesGeneratorString(sg); !cmp.Equal(got, tt.exp) { t.Errorf("unpexected -got/+exp\n%s", cmp.Diff(got, tt.exp)) } }) } }