Skip to content

Commit

Permalink
✨ match targets with version ranges correctly
Browse files Browse the repository at this point in the history
Signed-off-by: Pranav Gaikwad <[email protected]>
  • Loading branch information
pranavgaikwad committed Sep 25, 2023
1 parent dca2d15 commit 5f1acc6
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 1 deletion.
50 changes: 49 additions & 1 deletion engine/labels/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"regexp"
"strconv"
"strings"

"github.com/PaesslerAG/gval"
Expand Down Expand Up @@ -237,9 +238,56 @@ func tokenize(expr string) []string {

func contains(elem string, items []string) bool {
for _, item := range items {
if item == elem {
if labelValueMatches(item, elem) {
return true
}
}
return false
}

// labelValueMatches returns true when candidate matches with matchWith
// label value is divided into two parts - name and version
// version is absolute version or a range denoted by + or -
// returns true when names of values are equal and the version of
// candidate falls within the version range of matchWith
func labelValueMatches(matchWith string, candidate string) bool {
versionRegex := regexp.MustCompile(`(\d+)([\+-])?$`)
mMatch := versionRegex.FindStringSubmatch(matchWith)
cMatch := versionRegex.FindStringSubmatch(candidate)
if len(mMatch) != 3 {
return matchWith == candidate
}
mName, mVersion, mVersionRangeSymbol :=
versionRegex.ReplaceAllString(matchWith, ""), mMatch[1], mMatch[2]
if len(cMatch) != 3 {
// when no version on candidate, match for any version
return mName == candidate
}
cName, cVersion :=
versionRegex.ReplaceAllString(candidate, ""), cMatch[1]
if mName != cName {
return false
}
if mVersion == "" {
return mVersion == cVersion
}
if cVersion == "" {
return true
}
cVersionInt, err := strconv.ParseInt(cVersion, 10, 32)
if err != nil {
return mVersion == cVersion
}
mVersionInt, err := strconv.ParseInt(mVersion, 10, 32)
if err != nil {
return mVersion == cVersion
}
switch mVersionRangeSymbol {
case "+":
return cVersionInt >= mVersionInt
case "-":
return cVersionInt <= mVersionInt
default:
return cVersionInt == mVersionInt
}
}
83 changes: 83 additions & 0 deletions engine/labels/labels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,86 @@ func Test_ruleSelector_Matches(t *testing.T) {
})
}
}

func Test_labelValueMatches(t *testing.T) {
tests := []struct {
name string
candidate string
matchWith string
want bool
}{
{
name: "no version range test",
candidate: "eap",
matchWith: "eap",
want: true,
},
{
name: "name mismatch test",
candidate: "eap",
matchWith: "javaee",
want: false,
},
{
name: "absolute version test",
candidate: "eap6",
matchWith: "eap6",
want: true,
},
{
name: "version range test for '+'",
candidate: "eap6",
matchWith: "eap5+",
want: true,
},
{
name: "version range test for '+'",
candidate: "eap5",
matchWith: "eap5+",
want: true,
},
{
name: "version range test for '-'",
candidate: "eap7",
matchWith: "eap8-",
want: true,
},
{
name: "version range negative test for '-'",
candidate: "eap9",
matchWith: "eap8-",
want: false,
},
{
name: "version range negative test for '+'",
candidate: "eap7",
matchWith: "eap8+",
want: false,
},
{
name: "complex value version range test",
candidate: "Golang Version",
matchWith: "Golang Version11+",
want: true,
},
{
name: "match any version test",
candidate: "eap",
matchWith: "eap6+",
want: true,
},
{
name: "match any version test negative",
candidate: "eap6",
matchWith: "eap",
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := labelValueMatches(tt.matchWith, tt.candidate); got != tt.want {
t.Errorf("versionRangeMatches() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit 5f1acc6

Please sign in to comment.