Skip to content

Commit

Permalink
Merge pull request #18 from gripmock/matches-bugfix
Browse files Browse the repository at this point in the history
bugfix matches
  • Loading branch information
rez1dent3 committed Jul 31, 2024
2 parents ab1a52d + bfe8d41 commit 697e755
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 7 deletions.
6 changes: 6 additions & 0 deletions matches_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ func TestMatches_Slices_OrderIgnore(t *testing.T) {

func TestMatches_RegularDigits(t *testing.T) {
require.True(t, deeply.Matches("[0-9]", 9))
require.True(t, deeply.Matches("^100[1-2]{2}\\d{0,3}$", 10012))

require.True(t, deeply.Matches(
map[any]any{"vint64": "^100[1-2]{2}\\d{0,3}$"},
map[any]any{"vint64": 10012},
))
}

//nolint:funlen
Expand Down
31 changes: 24 additions & 7 deletions ranker.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package deeply
import (
"reflect"
"regexp"

"github.com/spf13/cast"
)

// Ranker is a function type used to rank matches between two values.
Expand Down Expand Up @@ -42,6 +44,16 @@ func RankMatch(expect, actual any) float64 {
// rank is a function that ranks the matches between two strings.
//
// It compares two strings and returns a float64 representing the match score.
// The function first checks if the actual value is a boolean and returns 0 if it is.
// Then it converts the expected and actual values to strings. If the values are not
// strings or if there is an error converting them to strings, the function checks
// if the values are deeply equal and returns the corresponding match score.
// If the strings are equal, the function returns the full match score.
// Next, the function tries to compile the expected string as a regular expression
// and finds the first match in the actual string. If a match is found, the function
// calculates the match score based on the length of the match. If no match is found,
// the function calculates the match score based on the Levenshtein distance
// between the two strings.
//
// Parameters:
// - expect: The expected string.
Expand All @@ -50,15 +62,20 @@ func RankMatch(expect, actual any) float64 {
// Returns:
// - The match score between the expected and actual strings.
func rank(expect, actual interface{}) float64 {
// Check if the actual value is a boolean and return 0 if it is.
if _, ok := actual.(bool); ok {
return 0
}

// Convert the expected and actual values to strings.
var (
expectedStr, expectedStringOk = expect.(string)
actualStr, actualStringOk = actual.(string)
actualStr, actualStringErr = cast.ToStringE(actual)
)

// If the values are not strings, check if they are equal and return the
// corresponding match score.
if !expectedStringOk || !actualStringOk {
// If the values are not strings or if there is an error converting them to strings,
// check if the values are deeply equal and return the corresponding match score.
if !expectedStringOk || actualStringErr != nil {
if reflect.DeepEqual(expect, actual) {
return 1 // Full match.
}
Expand All @@ -72,15 +89,15 @@ func rank(expect, actual interface{}) float64 {
}

// Try to compile the expected string as a regular expression and find the
// first match in the actual string. Return the match score based on the
// length of the match.
// first match in the actual string. If a match is found, calculate the match
// score based on the length of the match.
compile, err := regexp.Compile(expectedStr)
if compile != nil && err == nil {
results := compile.FindStringIndex(actualStr)

// If a match is found, calculate the match score based on the length of
// the match.
if len(results) == 2 { //nolint:mnd
if len(results) == 2 && len(actualStr) > 0 { //nolint:mnd
return float64(results[1]-results[0]) / float64(len(actualStr))
}
}
Expand Down
10 changes: 10 additions & 0 deletions ranker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,13 @@ func TestRankMatch_Boundary(t *testing.T) {

require.Greater(t, deeply.RankMatch(map[string]interface{}{}, map[string]interface{}{}), 0.)
}

func TestRankMatch_RegularDigits(t *testing.T) {
require.Greater(t, deeply.RankMatch("[0-9]", 9), 0.)
require.Greater(t, deeply.RankMatch("^100[1-2]{2}\\d{0,3}$", 10012), .1)

require.Greater(t, deeply.RankMatch(
map[any]any{"vint64": "^100[1-2]{2}\\d{0,3}$"},
map[any]any{"vint64": 10012},
), 0.)
}

0 comments on commit 697e755

Please sign in to comment.