-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Scanner error mapping [ACT-630][ACT-865] (#126)
* Git clone step error mapping init. * feat: Introduce PatternErrorMatcher for error mapping * refactor: separate out error_matcher from steperror * fix: Add DetailedError to branch recommendation * fix: use nil instead of empty map * refactor: separate error mapping into its own package * Fixed missing space Co-authored-by: Krisztián Gödrei <[email protected]> Co-authored-by: Tamas Chrenoczy-Nagy <[email protected]>
- Loading branch information
1 parent
9876195
commit c33b9a8
Showing
6 changed files
with
789 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package errormapper | ||
|
||
import ( | ||
"regexp" | ||
|
||
"github.com/bitrise-io/bitrise-init/step" | ||
) | ||
|
||
const ( | ||
// UnknownParam ... | ||
UnknownParam = "::unknown::" | ||
// DetailedErrorRecKey ... | ||
DetailedErrorRecKey = "DetailedError" | ||
) | ||
|
||
// DetailedError ... | ||
type DetailedError struct { | ||
Title string | ||
Description string | ||
} | ||
|
||
// NewDetailedErrorRecommendation ... | ||
func NewDetailedErrorRecommendation(detailedError DetailedError) step.Recommendation { | ||
return step.Recommendation{ | ||
DetailedErrorRecKey: detailedError, | ||
} | ||
} | ||
|
||
// DetailedErrorBuilder ... | ||
type DetailedErrorBuilder = func(...string) DetailedError | ||
|
||
// GetParamAt ... | ||
func GetParamAt(index int, params []string) string { | ||
res := UnknownParam | ||
if index >= 0 && len(params) > index { | ||
res = params[index] | ||
} | ||
return res | ||
} | ||
|
||
// PatternToDetailedErrorBuilder ... | ||
type PatternToDetailedErrorBuilder map[string]DetailedErrorBuilder | ||
|
||
// PatternErrorMatcher ... | ||
type PatternErrorMatcher struct { | ||
DefaultBuilder DetailedErrorBuilder | ||
PatternToBuilder PatternToDetailedErrorBuilder | ||
} | ||
|
||
// Run ... | ||
func (m *PatternErrorMatcher) Run(msg string) step.Recommendation { | ||
for pattern, builder := range m.PatternToBuilder { | ||
re := regexp.MustCompile(pattern) | ||
if re.MatchString(msg) { | ||
// [search_string, match1, match2, ...] | ||
matches := re.FindStringSubmatch((msg)) | ||
// Drop the first item, which is always the search_string itself | ||
// [search_string] -> [] | ||
// [search_string, match1, ...] -> [match1, ...] | ||
params := matches[1:] | ||
detail := builder(params...) | ||
return NewDetailedErrorRecommendation(detail) | ||
} | ||
} | ||
|
||
detail := m.DefaultBuilder(msg) | ||
return NewDetailedErrorRecommendation(detail) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
package errormapper | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/bitrise-io/bitrise-init/step" | ||
) | ||
|
||
func Test_newDetailedErrorRecommendation(t *testing.T) { | ||
type args struct { | ||
detailedError DetailedError | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want step.Recommendation | ||
}{ | ||
{ | ||
name: "newDetailedErrorRecommendation with nil", | ||
args: args{ | ||
detailedError: DetailedError{ | ||
Title: "TestTitle", | ||
Description: "TestDesciption", | ||
}, | ||
}, | ||
want: step.Recommendation{ | ||
DetailedErrorRecKey: DetailedError{ | ||
Title: "TestTitle", | ||
Description: "TestDesciption", | ||
}, | ||
}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := NewDetailedErrorRecommendation(tt.args.detailedError); !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("newDetailedErrorRecommendation() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func Test_getParamAt(t *testing.T) { | ||
type args struct { | ||
index int | ||
params []string | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
want string | ||
}{ | ||
{ | ||
name: "getParamsAt(0, nil)", | ||
args: args{ | ||
index: 0, | ||
params: nil, | ||
}, | ||
want: UnknownParam, | ||
}, | ||
{ | ||
name: "getParamsAt(0, [])", | ||
args: args{ | ||
index: 0, | ||
params: []string{}, | ||
}, | ||
want: UnknownParam, | ||
}, | ||
{ | ||
name: "getParamsAt(-1, ['1', '2', '3', '4', '5'])", | ||
args: args{ | ||
index: -1, | ||
params: []string{"1", "2", "3", "4", "5"}, | ||
}, | ||
want: UnknownParam, | ||
}, | ||
{ | ||
name: "getParamsAt(5, ['1', '2', '3', '4', '5'])", | ||
args: args{ | ||
index: 5, | ||
params: []string{"1", "2", "3", "4", "5"}, | ||
}, | ||
want: UnknownParam, | ||
}, | ||
{ | ||
name: "getParamsAt(0, ['1', '2', '3', '4', '5'])", | ||
args: args{ | ||
index: 0, | ||
params: []string{"1", "2", "3", "4", "5"}, | ||
}, | ||
want: "1", | ||
}, | ||
{ | ||
name: "getParamsAt(4, ['1', '2', '3', '4', '5'])", | ||
args: args{ | ||
index: 4, | ||
params: []string{"1", "2", "3", "4", "5"}, | ||
}, | ||
want: "5", | ||
}, | ||
{ | ||
name: "getParamsAt(2, ['1', '2', '3', '4', '5'])", | ||
args: args{ | ||
index: 2, | ||
params: []string{"1", "2", "3", "4", "5"}, | ||
}, | ||
want: "3", | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := GetParamAt(tt.args.index, tt.args.params); got != tt.want { | ||
t.Errorf("getParamAt() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestPatternErrorMatcher_Run(t *testing.T) { | ||
type fields struct { | ||
defaultBuilder DetailedErrorBuilder | ||
patternToBuilder PatternToDetailedErrorBuilder | ||
} | ||
type args struct { | ||
msg string | ||
} | ||
tests := []struct { | ||
name string | ||
fields fields | ||
args args | ||
want step.Recommendation | ||
}{ | ||
{ | ||
name: "Run with defaultBuilder", | ||
fields: fields{ | ||
defaultBuilder: func(params ...string) DetailedError { | ||
return DetailedError{ | ||
Title: "T", | ||
Description: "D", | ||
} | ||
}, | ||
patternToBuilder: map[string]DetailedErrorBuilder{}, | ||
}, | ||
args: args{ | ||
msg: "Test", | ||
}, | ||
want: step.Recommendation{ | ||
DetailedErrorRecKey: DetailedError{ | ||
Title: "T", | ||
Description: "D", | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "Run with patternBuilder", | ||
fields: fields{ | ||
defaultBuilder: func(params ...string) DetailedError { | ||
return DetailedError{ | ||
Title: "DefaultTitle", | ||
Description: "DefaultDesc", | ||
} | ||
}, | ||
patternToBuilder: map[string]DetailedErrorBuilder{ | ||
"Test": func(params ...string) DetailedError { | ||
return DetailedError{ | ||
Title: "PatternTitle", | ||
Description: "PatternDesc", | ||
} | ||
}, | ||
}, | ||
}, | ||
args: args{ | ||
msg: "Test", | ||
}, | ||
want: step.Recommendation{ | ||
DetailedErrorRecKey: DetailedError{ | ||
Title: "PatternTitle", | ||
Description: "PatternDesc", | ||
}, | ||
}, | ||
}, | ||
{ | ||
name: "Run with patternBuilder with param", | ||
fields: fields{ | ||
defaultBuilder: func(params ...string) DetailedError { | ||
return DetailedError{ | ||
Title: "DefaultTitle", | ||
Description: "DefaultDesc", | ||
} | ||
}, | ||
patternToBuilder: map[string]DetailedErrorBuilder{ | ||
"Test (.+)!": func(params ...string) DetailedError { | ||
p := GetParamAt(0, params) | ||
return DetailedError{ | ||
Title: "PatternTitle", | ||
Description: fmt.Sprintf("PatternDesc: '%s'", p), | ||
} | ||
}, | ||
}, | ||
}, | ||
args: args{ | ||
msg: "Test WithPatternParam!", | ||
}, | ||
want: step.Recommendation{ | ||
DetailedErrorRecKey: DetailedError{ | ||
Title: "PatternTitle", | ||
Description: "PatternDesc: 'WithPatternParam'", | ||
}, | ||
}, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
m := &PatternErrorMatcher{ | ||
DefaultBuilder: tt.fields.defaultBuilder, | ||
PatternToBuilder: tt.fields.patternToBuilder, | ||
} | ||
if got := m.Run(tt.args.msg); !reflect.DeepEqual(got, tt.want) { | ||
t.Errorf("PatternErrorMatcher.Run() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.