Merge pull request #145 from CarlJi/1218
feature: add skipFile flag for profile API
This commit is contained in:
commit
0d9db7f7af
@ -56,6 +56,7 @@ goc profile --force
|
|||||||
Service: svrList,
|
Service: svrList,
|
||||||
Address: addrList,
|
Address: addrList,
|
||||||
CoverFilePatterns: coverFilePatterns,
|
CoverFilePatterns: coverFilePatterns,
|
||||||
|
SkipFilePatterns: skipFilePatterns,
|
||||||
}
|
}
|
||||||
res, err := cover.NewWorker(center).Profile(p)
|
res, err := cover.NewWorker(center).Profile(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -84,6 +85,7 @@ var (
|
|||||||
force bool // --force flag
|
force bool // --force flag
|
||||||
output string // --output flag
|
output string // --output flag
|
||||||
coverFilePatterns []string // --coverfile flag
|
coverFilePatterns []string // --coverfile flag
|
||||||
|
skipFilePatterns []string // --skipfile flag
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
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().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().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(&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())
|
addBasicFlags(profileCmd.Flags())
|
||||||
rootCmd.AddCommand(profileCmd)
|
rootCmd.AddCommand(profileCmd)
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 231 KiB |
@ -127,6 +127,18 @@ func TestClientAction(t *testing.T) {
|
|||||||
param: ProfileParam{CoverFilePatterns: []string{"b.go$"}},
|
param: ProfileParam{CoverFilePatterns: []string{"b.go$"}},
|
||||||
expected: "b/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 {
|
for _, tc := range tcs {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
@ -108,6 +108,7 @@ type ProfileParam struct {
|
|||||||
Service []string `form:"service" json:"service"`
|
Service []string `form:"service" json:"service"`
|
||||||
Address []string `form:"address" json:"address"`
|
Address []string `form:"address" json:"address"`
|
||||||
CoverFilePatterns []string `form:"coverfile" json:"coverfile"`
|
CoverFilePatterns []string `form:"coverfile" json:"coverfile"`
|
||||||
|
SkipFilePatterns []string `form:"skipfile" json:"skipfile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//listServices list all the registered services
|
//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 {
|
if err := cov.DumpProfile(merged, c.Writer); err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
@ -234,6 +243,31 @@ func filterProfile(coverFile []string, profiles []*cover.Profile) ([]*cover.Prof
|
|||||||
return out, nil
|
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) {
|
func (s *server) clear(c *gin.Context) {
|
||||||
var body ProfileParam
|
var body ProfileParam
|
||||||
if err := c.ShouldBind(&body); err != nil {
|
if err := c.ShouldBind(&body); err != nil {
|
||||||
|
@ -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 {
|
func stringifyCoverProfile(profiles []*cover.Profile) string {
|
||||||
res := make([]cover.Profile, 0, len(profiles))
|
res := make([]cover.Profile, 0, len(profiles))
|
||||||
for _, p := range profiles {
|
for _, p := range profiles {
|
||||||
|
@ -128,6 +128,26 @@ setup() {
|
|||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[[ "$output" == *"mode: count"* ]]
|
[[ "$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
|
wait $profile_pid
|
||||||
kill -9 $SAMPLE_PID
|
kill -9 $SAMPLE_PID
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user