diff --git a/cmd/build.go b/cmd/build.go index eb4a54b6..26b14bb0 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -78,6 +78,7 @@ func runBuild(args []string, wd string) { Mode: coverMode.String(), AgentPort: agentPort.String(), Center: center, + Singleton: singleton, IsMod: gocBuild.IsMod, ModRootPath: gocBuild.ModRootPath, OneMainPackage: true, // it is a go build diff --git a/cmd/commonflags.go b/cmd/commonflags.go index 9440276f..7f3a6d18 100644 --- a/cmd/commonflags.go +++ b/cmd/commonflags.go @@ -31,6 +31,7 @@ var ( debugGoc bool debugInCISyncFile string buildFlags string + singleton bool goRunExecFlag string goRunArguments string @@ -51,6 +52,7 @@ func addCommonFlags(cmdset *pflag.FlagSet) { addBasicFlags(cmdset) cmdset.Var(&coverMode, "mode", "coverage mode: set, count, atomic") cmdset.Var(&agentPort, "agentport", "a fixed port such as :8100 for registered service communicate with goc server. if not provided, using a random one") + cmdset.BoolVar(&singleton, "singleton", false, "singleton mode, not register to goc center") cmdset.StringVar(&buildFlags, "buildflags", "", "specify the build flags") // bind to viper viper.BindPFlags(cmdset) diff --git a/cmd/cover.go b/cmd/cover.go index dec4e5bf..133d39d2 100644 --- a/cmd/cover.go +++ b/cmd/cover.go @@ -38,22 +38,25 @@ goc cover --center=http://127.0.0.1:7777 --target=/path/to/target --mode=atomic `, Hidden: true, Run: func(cmd *cobra.Command, args []string) { - var buildFlags string - buildFlags = viper.GetString("buildflags") - - ci := &cover.CoverInfo{ - Args: buildFlags, - GoPath: "", - Target: target, - Mode: coverMode.String(), - AgentPort: agentPort.String(), - Center: center, - OneMainPackage: false, - } - _ = cover.Execute(ci) + runCover(target) }, } +func runCover(target string) { + buildFlags := viper.GetString("buildflags") + ci := &cover.CoverInfo{ + Args: buildFlags, + GoPath: "", + Target: target, + Mode: coverMode.String(), + AgentPort: agentPort.String(), + Center: center, + Singleton: singleton, + OneMainPackage: false, + } + _ = cover.Execute(ci) +} + func init() { coverCmd.Flags().StringVar(&target, "target", ".", "target folder to cover") addCommonFlags(coverCmd.Flags()) diff --git a/cmd/cover_test.go b/cmd/cover_test.go new file mode 100644 index 00000000..c97dbb17 --- /dev/null +++ b/cmd/cover_test.go @@ -0,0 +1,54 @@ +package cmd + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +var mainContent = []byte(`package main + +import ( + "fmt" +) + +func main() { + fmt.Println("hello world") +}`) + +var goModContent = []byte(`module example.com/simple-project + +go 1.11 +`) + +func TestCoverSuccess(t *testing.T) { + workingDir := filepath.Join(baseDir, "../tests/samples/tmp/project") + err := os.MkdirAll(workingDir, os.ModePerm) + assert.NoError(t, err) + defer os.RemoveAll(workingDir) + + err = writeFile(workingDir+"/main.go", mainContent) + assert.NoError(t, err) + err = writeFile(workingDir+"/go.mod", goModContent) + assert.NoError(t, err) + os.Setenv("GO111MODULE", "on") + + runCover(workingDir) + + _, err = os.Lstat(workingDir + "/http_cover_apis_auto_generated.go") + assert.Equal(t, err, nil, "the generate file should be generated.") +} + +func writeFile(name string, data []byte) error { + f, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return err + } + _, err = f.Write(data) + if err1 := f.Close(); err1 != nil && err == nil { + err = err1 + } + return err +} diff --git a/cmd/install.go b/cmd/install.go index 5d845695..edc3c575 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -71,6 +71,7 @@ func runInstall(args []string, wd string) { Mode: coverMode.String(), AgentPort: agentPort.String(), Center: center, + Singleton: singleton, IsMod: gocBuild.IsMod, ModRootPath: gocBuild.ModRootPath, OneMainPackage: false, diff --git a/cmd/run.go b/cmd/run.go index f78207cb..6fde9cee 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -70,6 +70,7 @@ goc run . [--buildflags] [--exec] [--arguments] Target: gocBuild.TmpDir, Mode: coverMode.String(), Center: gocServer, + Singleton: singleton, AgentPort: "", IsMod: gocBuild.IsMod, ModRootPath: gocBuild.ModRootPath, diff --git a/pkg/cover/cover.go b/pkg/cover/cover.go index 742e352a..2639ce2b 100644 --- a/pkg/cover/cover.go +++ b/pkg/cover/cover.go @@ -52,6 +52,7 @@ type TestCover struct { Mode string AgentPort string Center string // cover profile host center + Singleton bool MainPkgCover *PackageCover DepsCover []*PackageCover CacheCover map[string]*PackageCover @@ -139,6 +140,7 @@ type CoverInfo struct { Mode string AgentPort string Center string + Singleton bool } //Execute inject cover variables for all the .go files in the target folder @@ -150,6 +152,7 @@ func Execute(coverInfo *CoverInfo) error { mode := coverInfo.Mode agentPort := coverInfo.AgentPort center := coverInfo.Center + singleton := coverInfo.Singleton globalCoverVarImportPath := coverInfo.GlobalCoverVarImportPath if coverInfo.IsMod { @@ -187,6 +190,7 @@ func Execute(coverInfo *CoverInfo) error { Mode: mode, AgentPort: agentPort, Center: center, + Singleton: singleton, MainPkgCover: mainCover, GlobalCoverVarImportPath: globalCoverVarImportPath, } diff --git a/pkg/cover/instrument.go b/pkg/cover/instrument.go index 4719e8fd..a559fea2 100644 --- a/pkg/cover/instrument.go +++ b/pkg/cover/instrument.go @@ -131,11 +131,15 @@ func clearFileCover(counter []uint32) { } func registerHandlers() { + {{if .Singleton}} + ln, _, err := listen() + {{else}} ln, host, err := listen() + {{end}} if err != nil { log.Fatalf("listen failed, err:%v", err) } - + {{if not .Singleton}} profileAddr := "http://" + host if resp, err := registerSelf(profileAddr); err != nil { log.Fatalf("register address %v failed, err: %v, response: %v", profileAddr, err, string(resp)) @@ -157,6 +161,7 @@ func registerHandlers() { deregisterSelf(profileAddrs) } go watchSignal(fn) + {{end}} mux := http.NewServeMux() // Coverage reports the current code coverage as a fraction in the range [0, 1]. diff --git a/tests/build.bats b/tests/build.bats index 055d8c67..35d5d783 100755 --- a/tests/build.bats +++ b/tests/build.bats @@ -112,4 +112,17 @@ setup() { [ "$status" -eq 0 ] wait $profile_pid -} \ No newline at end of file +} + +@test "test basic goc build command with singleton" { + cd samples/run_for_several_seconds + + wait_profile_backend "build7" & + profile_pid=$! + + run gocc build --debug --singleton --debugcisyncfile ci-sync.bak; + info build7 output: $output + [ "$status" -eq 0 ] + + wait $profile_pid +}