Merge pull request #145 from CarlJi/1218

feature: add skipFile flag for profile API
This commit is contained in:
qiniu-bot 2020-12-21 10:49:23 +08:00 committed by GitHub
commit 0d9db7f7af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 165 additions and 0 deletions

View File

@ -56,6 +56,7 @@ goc profile --force
Service: svrList,
Address: addrList,
CoverFilePatterns: coverFilePatterns,
SkipFilePatterns: skipFilePatterns,
}
res, err := cover.NewWorker(center).Profile(p)
if err != nil {
@ -84,6 +85,7 @@ var (
force bool // --force flag
output string // --output flag
coverFilePatterns []string // --coverfile flag
skipFilePatterns []string // --skipfile flag
)
func init() {
@ -92,6 +94,7 @@ func init() {
profileCmd.Flags().StringSliceVarP(&addrList, "address", "", nil, "address to fetch profile, see 'goc list' for all addresses.")
profileCmd.Flags().BoolVarP(&force, "force", "f", false, "force fetching all available profiles")
profileCmd.Flags().StringSliceVarP(&coverFilePatterns, "coverfile", "", nil, "only output coverage data of the files matching the patterns")
profileCmd.Flags().StringSliceVarP(&skipFilePatterns, "skipfile", "", nil, "skip the files matching the patterns when outputing coverage data")
addBasicFlags(profileCmd.Flags())
rootCmd.AddCommand(profileCmd)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 231 KiB

View File

@ -127,6 +127,18 @@ func TestClientAction(t *testing.T) {
param: ProfileParam{CoverFilePatterns: []string{"b.go$"}},
expected: "b/b.go",
},
{
name: "valid test with skipfile flag provided",
service: ServiceUnderTest{Name: "serviceOK", Address: profileSuccessMockSvr.URL},
param: ProfileParam{SkipFilePatterns: []string{"b.go$"}},
expected: "main.go",
},
{
name: "valid test with both skipfile and coverfile flags provided",
service: ServiceUnderTest{Name: "serviceOK", Address: profileSuccessMockSvr.URL},
param: ProfileParam{SkipFilePatterns: []string{"main.go"}, CoverFilePatterns: []string{".go$"}},
expected: "b.go",
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {

View File

@ -108,6 +108,7 @@ type ProfileParam struct {
Service []string `form:"service" json:"service"`
Address []string `form:"address" json:"address"`
CoverFilePatterns []string `form:"coverfile" json:"coverfile"`
SkipFilePatterns []string `form:"skipfile" json:"skipfile"`
}
//listServices list all the registered services
@ -209,6 +210,14 @@ func (s *server) profile(c *gin.Context) {
}
}
if len(body.SkipFilePatterns) > 0 {
merged, err = skipProfile(body.SkipFilePatterns, merged)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to skip profile based on the patterns: %v, error: %v", body.SkipFilePatterns, err)})
return
}
}
if err := cov.DumpProfile(merged, c.Writer); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
@ -234,6 +243,31 @@ func filterProfile(coverFile []string, profiles []*cover.Profile) ([]*cover.Prof
return out, nil
}
// skipProfile skips profiles of the packages matching the skipFile pattern
func skipProfile(skipFile []string, profiles []*cover.Profile) ([]*cover.Profile, error) {
var out = make([]*cover.Profile, 0)
for _, profile := range profiles {
var shouldSkip bool
for _, pattern := range skipFile {
matched, err := regexp.MatchString(pattern, profile.FileName)
if err != nil {
return nil, fmt.Errorf("filterProfile failed with pattern %s for profile %s, err: %v", pattern, profile.FileName, err)
}
if matched {
shouldSkip = true
break // no need to check again for the file
}
}
if !shouldSkip {
out = append(out, profile)
}
}
return out, nil
}
func (s *server) clear(c *gin.Context) {
var body ProfileParam
if err := c.ShouldBind(&body); err != nil {

View File

@ -421,6 +421,102 @@ func TestFilterProfile(t *testing.T) {
}
}
func TestSkipProfile(t *testing.T) {
var tcs = []struct {
name string
pattern []string
input []*cover.Profile
output []*cover.Profile
expectErr bool
}{
{
name: "normal path",
pattern: []string{"some/fancy/gopath", "a/fancy/gopath"},
input: []*cover.Profile{
{
FileName: "some/fancy/gopath/a.go",
},
{
FileName: "some/fancy/gopath/b/a.go",
},
{
FileName: "a/fancy/gopath/a.go",
},
{
FileName: "b/fancy/gopath/a.go",
},
{
FileName: "b/a/fancy/gopath/a.go",
},
},
output: []*cover.Profile{
{
FileName: "b/fancy/gopath/a.go",
},
},
},
{
name: "with regular expression",
pattern: []string{"fancy/gopath/a.go$", "^b/a/"},
input: []*cover.Profile{
{
FileName: "some/fancy/gopath/a.go",
},
{
FileName: "some/fancy/gopath/b/a.go",
},
{
FileName: "a/fancy/gopath/a.go",
},
{
FileName: "b/fancy/gopath/c/a.go",
},
{
FileName: "b/a/fancy/gopath/a.go",
},
},
output: []*cover.Profile{
{
FileName: "some/fancy/gopath/b/a.go",
},
{
FileName: "b/fancy/gopath/c/a.go",
},
},
},
{
name: "with invalid regular expression",
pattern: []string{"(?!a)"},
input: []*cover.Profile{
{
FileName: "some/fancy/gopath/a.go",
},
},
expectErr: true,
},
}
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
out, err := skipProfile(tc.pattern, tc.input)
if err != nil {
if !tc.expectErr {
t.Errorf("Unexpected error: %v", err)
}
return
}
if tc.expectErr {
t.Errorf("Expected an error, but got value %s", stringifyCoverProfile(out))
}
if !reflect.DeepEqual(out, tc.output) {
t.Errorf("Mismatched results. \nExpected: %s\nActual:%s", stringifyCoverProfile(tc.output), stringifyCoverProfile(out))
}
})
}
}
func stringifyCoverProfile(profiles []*cover.Profile) string {
res := make([]cover.Profile, 0, len(profiles))
for _, p := range profiles {

View File

@ -128,6 +128,26 @@ setup() {
[ "$status" -eq 0 ]
[[ "$output" == *"mode: count"* ]]
wait $profile_pid
kill -9 $SAMPLE_PID
}
@test "test goc profile with coverfile and skipfile flags" {
./simple-project 3>&- &
SAMPLE_PID=$!
sleep 2
wait_profile_backend "profile6" &
profile_pid=$!
run gocc profile --center=http://127.0.0.1:60001 --coverfile="a.go$,b.go$" --skipfile="b.go$" --debug --debugcisyncfile ci-sync.bak;
info $output
[ "$status" -eq 0 ]
[[ "$output" == *"mode: count"* ]]
[[ "$output" == *"a.go"* ]] # contains a.go file
[[ "$output" != *"b.go"* ]] # not contains b.go file
[[ "$output" != *"main.go"* ]] # not contains main.go file
wait $profile_pid
kill -9 $SAMPLE_PID
}