From 1c75f4fcb8a94fc0d3c61da0dd54beba1da2c02e Mon Sep 17 00:00:00 2001 From: alanprot <alanprot@gmail.com> Date: Mon, 27 Jan 2025 15:11:23 -0800 Subject: [PATCH 1/4] Allowing to create Not/Regex/NotRegex matchers Signed-off-by: alanprot <alanprot@gmail.com> --- .github/workflows/ci.yml | 6 ++---- walk.go | 39 ++++++++++++++++++++++++++++++++++++--- walk_test.go | 14 +++++++++++--- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbb1d7f..ce5664d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,5 @@ jobs: with: go-version-file: .go-version cache: true - - name: Lint - uses: golangci/golangci-lint-action@v6.1.0 - with: - version: v1.59.0 + - name: Golangci-lint + uses: golangci/golangci-lint-action@v6.2.0 diff --git a/walk.go b/walk.go index 2426841..74ac07d 100644 --- a/walk.go +++ b/walk.go @@ -460,12 +460,45 @@ func (s *PromQLSmith) walkLabelMatchers() []*labels.Matcher { lbls = append(lbls, l) }) + valF := func(v string) string { + val := s.rnd.Float64() + switch { + case val > 0.95: + return "" + case val > 0.90: + return ".*" + case val > 0.85: + return ".+" + case val > 0.75: + return fmt.Sprintf(".*%v", v[len(v)/2:]) + default: + return fmt.Sprintf("%v.*", v[:len(v)/2]) + } + } + for i := 0; i < items; i++ { + var matcher *labels.Matcher + if lbls[orders[i]].Name == labels.MetricName { containsName = true + matcher = labels.MustNewMatcher(labels.MatchEqual, lbls[orders[i]].Name, lbls[orders[i]].Value) + } else { + res := s.rnd.Intn(4) + matchType := labels.MatchType(res) + switch matchType { + case labels.MatchEqual: + matcher = labels.MustNewMatcher(labels.MatchEqual, lbls[orders[i]].Name, lbls[orders[i]].Value) + case labels.MatchNotEqual: + matcher = labels.MustNewMatcher(labels.MatchNotEqual, lbls[orders[i]].Name, lbls[orders[i]].Value) + case labels.MatchRegexp: + matcher = labels.MustNewMatcher(labels.MatchRegexp, lbls[orders[i]].Name, valF(lbls[orders[i]].Value)) + case labels.MatchNotRegexp: + matcher = labels.MustNewMatcher(labels.MatchNotRegexp, lbls[orders[i]].Name, valF(lbls[orders[i]].Value)) + } } - matchers = append(matchers, labels.MustNewMatcher(labels.MatchEqual, lbls[orders[i]].Name, lbls[orders[i]].Value)) + + matchers = append(matchers, matcher) } if !containsName { @@ -482,8 +515,8 @@ func (s *PromQLSmith) walkLabelMatchers() []*labels.Matcher { return matchers } -// walkSelectors is similar to walkLabelMatchers, but used for generating various -// types of matchers more than simple equal matcher. +// walkSelectors is similar to walkLabelMatchers, but does not guarantee the equal +// matcher on the metric name func (s *PromQLSmith) walkSelectors() []*labels.Matcher { if len(s.seriesSet) == 0 { return nil diff --git a/walk_test.go b/walk_test.go index 37d1670..d61b35a 100644 --- a/walk_test.go +++ b/walk_test.go @@ -497,7 +497,7 @@ func TestWalkVectorSelector(t *testing.T) { require.True(t, ok) containsMetricName := false for _, matcher := range vs.LabelMatchers { - require.Equal(t, labels.MatchEqual, matcher.Type) + require.LessOrEqual(t, matcher.Type, 4) if matcher.Name == labels.MetricName { containsMetricName = true } @@ -509,7 +509,8 @@ func TestWalkLabelMatchers(t *testing.T) { rnd := rand.New(rand.NewSource(time.Now().Unix())) opts := []Option{WithEnableOffset(true), WithEnableAtModifier(true)} for i, tc := range []struct { - ss []labels.Labels + expectedMatchers int + ss []labels.Labels }{ { ss: nil, @@ -526,9 +527,16 @@ func TestWalkLabelMatchers(t *testing.T) { } { t.Run(fmt.Sprintf("test_case_%d", i), func(t *testing.T) { p := New(rnd, tc.ss, opts...) + labelNames := make(map[string]struct{}) + for _, s := range tc.ss { + s.Range(func(l labels.Label) { + labelNames[l.Name] = struct{}{} + }) + } matchers := p.walkLabelMatchers() for _, matcher := range matchers { - require.Equal(t, labels.MatchEqual, matcher.Type) + require.LessOrEqual(t, matcher.Type, 4) + require.Contains(t, labelNames, matcher.Name) } }) } From 7608ad20b7956eb3853d63a7103945b325bfcea1 Mon Sep 17 00:00:00 2001 From: alanprot <alanprot@gmail.com> Date: Mon, 27 Jan 2025 15:24:42 -0800 Subject: [PATCH 2/4] fix lint Signed-off-by: alanprot <alanprot@gmail.com> --- walk.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/walk.go b/walk.go index 74ac07d..e7b44d7 100644 --- a/walk.go +++ b/walk.go @@ -720,13 +720,6 @@ func keepValueTypes(input []parser.ValueType, keep []parser.ValueType) []parser. return out } -func min(a, b int) int { - if a > b { - return b - } - return a -} - // generate a non-zero float64 value randomly. func getNonZeroFloat64(rnd *rand.Rand) float64 { for { From f9908dc15a131f27f8eff759d912541f81c74506 Mon Sep 17 00:00:00 2001 From: alanprot <alanprot@gmail.com> Date: Mon, 27 Jan 2025 15:30:03 -0800 Subject: [PATCH 3/4] Adding != case Signed-off-by: alanprot <alanprot@gmail.com> --- walk.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/walk.go b/walk.go index e7b44d7..d493745 100644 --- a/walk.go +++ b/walk.go @@ -490,7 +490,11 @@ func (s *PromQLSmith) walkLabelMatchers() []*labels.Matcher { case labels.MatchEqual: matcher = labels.MustNewMatcher(labels.MatchEqual, lbls[orders[i]].Name, lbls[orders[i]].Value) case labels.MatchNotEqual: - matcher = labels.MustNewMatcher(labels.MatchNotEqual, lbls[orders[i]].Name, lbls[orders[i]].Value) + val := lbls[orders[i]].Value + if s.rnd.Float64() > 0.9 { + val = "" + } + matcher = labels.MustNewMatcher(labels.MatchNotEqual, lbls[orders[i]].Name, val) case labels.MatchRegexp: matcher = labels.MustNewMatcher(labels.MatchRegexp, lbls[orders[i]].Name, valF(lbls[orders[i]].Value)) case labels.MatchNotRegexp: From 3dda82ab3dc91751d56dbfa9cfc9c46081c0f174 Mon Sep 17 00:00:00 2001 From: alanprot <alanprot@gmail.com> Date: Mon, 27 Jan 2025 16:13:17 -0800 Subject: [PATCH 4/4] using ceil when discovering how many extra matcher will be added on walkLabelMatchers function Signed-off-by: alanprot <alanprot@gmail.com> --- walk.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/walk.go b/walk.go index d493745..06d5506 100644 --- a/walk.go +++ b/walk.go @@ -2,6 +2,7 @@ package promqlsmith import ( "fmt" + "math" "math/rand" "sort" "strings" @@ -452,7 +453,7 @@ func (s *PromQLSmith) walkLabelMatchers() []*labels.Matcher { } series := s.seriesSet[s.rnd.Intn(len(s.seriesSet))] orders := s.rnd.Perm(series.Len()) - items := s.rnd.Intn((series.Len() + 1) / 2) + items := s.rnd.Intn(int(math.Ceil(float64(series.Len()+1) / 2))) matchers := make([]*labels.Matcher, 0, items) containsName := false lbls := make([]labels.Label, 0, series.Len())