From b02d49c2be7a9ebd0c6ee03efeebff631939993a Mon Sep 17 00:00:00 2001 From: lyyyuna Date: Thu, 18 Jun 2020 16:20:54 +0800 Subject: [PATCH 1/4] enhance error handling --- cmd/build.go | 14 +++++------ cmd/build_test.go | 8 +++--- cmd/commonflags.go | 6 ++--- cmd/install.go | 10 ++++---- cmd/install_test.go | 13 ++++++---- cmd/list.go | 2 +- cmd/root.go | 9 +++++-- cmd/run.go | 9 +++++-- pkg/build/build.go | 35 ++++++++++++++++---------- pkg/build/build_test.go | 9 ++++--- pkg/build/errors.go | 1 + pkg/build/install.go | 19 +++++++++----- pkg/build/install_test.go | 5 ++-- pkg/build/tmpfolder.go | 25 +++++++++++++------ pkg/build/tmpfolder_test.go | 10 ++++---- pkg/cover/cover.go | 49 ++++++++++++++++++++++++++----------- 16 files changed, 143 insertions(+), 81 deletions(-) diff --git a/cmd/build.go b/cmd/build.go index 9bc6869..7bbec8f 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -17,7 +17,7 @@ package cmd import ( - "log" + log "github.com/sirupsen/logrus" "github.com/qiniu/goc/pkg/build" "github.com/qiniu/goc/pkg/cover" @@ -28,7 +28,7 @@ var buildCmd = &cobra.Command{ Use: "build", Short: "Do cover for all go files and execute go build command", Long: ` -First of all, this build command will copy the project code and its necessary dependencies to a temporary directory, then do cover for the target in this temporary directory, finally go build command will be executed and binaries generated to their original place. +Build command will copy the project code and its necessary dependencies to a temporary directory, then do cover for the target, binaries will be generated to their original place. `, Example: ` # Build the current binary with cover variables injected. The binary will be generated in the current folder. @@ -44,7 +44,7 @@ goc build --output /to/this/path goc build --buildflags="-ldflags '-extldflags -static' -tags='embed kodo'" `, Run: func(cmd *cobra.Command, args []string) { - runBuild() + runBuild(args) }, } @@ -52,14 +52,14 @@ var buildOutput string func init() { addBuildFlags(buildCmd.Flags()) - buildCmd.Flags().StringVar(&buildOutput, "output", "", "it forces build to write the resulting executable or object to the named output file or directory") + buildCmd.Flags().StringVar(&buildOutput, "output", "", "it forces build to write the resulting executable to the named output file") rootCmd.AddCommand(buildCmd) } -func runBuild() { - gocBuild, err := build.NewBuild(buildFlags, packages, buildOutput) +func runBuild(args []string) { + gocBuild, err := build.NewBuild(buildFlags, args, buildOutput) if err != nil { - log.Fatalf("Fail to NewBuild: %v", err) + log.Fatalf("Fail to build: %v", err) } // remove temporary directory if needed defer gocBuild.Clean() diff --git a/cmd/build_test.go b/cmd/build_test.go index db005d6..407f8e5 100644 --- a/cmd/build_test.go +++ b/cmd/build_test.go @@ -17,13 +17,14 @@ package cmd import ( - "github.com/stretchr/testify/assert" "os" "os/exec" "path/filepath" "strings" "testing" "time" + + "github.com/stretchr/testify/assert" ) var baseDir string @@ -42,8 +43,9 @@ func TestGeneratedBinary(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - buildFlags, packages, buildOutput = "", ".", "" - runBuild() + buildFlags, buildOutput = "", "" + args := []string{"."} + runBuild(args) obj := filepath.Join(".", "simple-project") fInfo, err := os.Lstat(obj) diff --git a/cmd/commonflags.go b/cmd/commonflags.go index f18f622..65a6bce 100644 --- a/cmd/commonflags.go +++ b/cmd/commonflags.go @@ -11,8 +11,8 @@ var ( mode string debugGoc bool buildFlags string - packages string - appArgs string + // packages string + appArgs string goRunExecFlag string goRunArguments string @@ -35,14 +35,12 @@ func addCommonFlags(cmdset *pflag.FlagSet) { func addBuildFlags(cmdset *pflag.FlagSet) { addCommonFlags(cmdset) - cmdset.StringVar(&packages, "packages", ".", "specify the package name, only . and ./... are supported") // bind to viper viper.BindPFlags(cmdset) } func addRunFlags(cmdset *pflag.FlagSet) { addBuildFlags(cmdset) - cmdset.Lookup("packages").Usage = "specify the package name, only ., ./... and *.go are supported" cmdset.StringVar(&appArgs, "appargs", "", "specify the application's arguments") cmdset.StringVar(&goRunExecFlag, "exec", "", "same as -exec flag in 'go run' command") cmdset.StringVar(&goRunArguments, "arguments", "", "same as 'arguments' in 'go run' command") diff --git a/cmd/install.go b/cmd/install.go index 028230f..be9b7c2 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -27,7 +27,7 @@ var installCmd = &cobra.Command{ Use: "install", Short: "Do cover for all go files and execute go install command", Long: ` -First of all, this install command will copy the project code and its necessary dependencies to a temporary directory, then do cover for the target in this temporary directory, finally go install command will be executed and binaries generated to their original place. +Install command will copy the project code and its necessary dependencies to a temporary directory, then do cover for the target, binaries will be generated to their original place. `, Example: ` # Install all binaries with cover variables injected. The binary will be installed in $GOPATH/bin or $HOME/go/bin if directory existed. @@ -40,7 +40,7 @@ goc install --center=http://127.0.0.1:7777 goc build --buildflags="-ldflags '-extldflags -static' -tags='embed kodo'" `, Run: func(cmd *cobra.Command, args []string) { - runInstall() + runInstall(args) }, } @@ -49,10 +49,10 @@ func init() { rootCmd.AddCommand(installCmd) } -func runInstall() { - gocBuild, err := build.NewInstall(buildFlags, packages) +func runInstall(args []string) { + gocBuild, err := build.NewInstall(buildFlags, args) if err != nil { - log.Fatalf("Fail to NewInstall: %v", err) + log.Fatalf("Fail to install: %v", err) } // remove temporary directory if needed defer gocBuild.Clean() diff --git a/cmd/install_test.go b/cmd/install_test.go index 150d098..a64a221 100644 --- a/cmd/install_test.go +++ b/cmd/install_test.go @@ -17,13 +17,14 @@ package cmd import ( - "github.com/stretchr/testify/assert" "os" "os/exec" "path/filepath" "strings" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestInstalledBinaryForMod(t *testing.T) { @@ -36,8 +37,9 @@ func TestInstalledBinaryForMod(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - buildFlags, packages, buildOutput = "", ".", "" - runInstall() + buildFlags, buildOutput = "", "" + args := []string{"."} + runInstall(args) obj := filepath.Join(gopath, "bin", "simple-project") fInfo, err := os.Lstat(obj) @@ -64,8 +66,9 @@ func TestInstalledBinaryForLegacy(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") - buildFlags, packages, buildOutput = "", ".", "" - runInstall() + buildFlags, buildOutput = "", "" + args := []string{"."} + runInstall(args) obj := filepath.Join(gopath, "bin", "simple_gopath_project") fInfo, err := os.Lstat(obj) diff --git a/cmd/list.go b/cmd/list.go index 194d486..5698596 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -42,6 +42,6 @@ goc list [flags] } func init() { - listCmd.Flags().StringVarP(¢er, "center", "", "http://127.0.0.1:7777", "cover profile host center") + addBasicFlags(listCmd.Flags()) rootCmd.AddCommand(listCmd) } diff --git a/cmd/root.go b/cmd/root.go index b0d50d1..09be748 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,7 +17,6 @@ package cmd import ( - "io/ioutil" "path/filepath" "runtime" "strconv" @@ -49,7 +48,13 @@ Find more information at: }) if debugGoc == false { // we only need log in debug mode - log.SetOutput(ioutil.Discard) + log.SetLevel(log.FatalLevel) + log.SetFormatter(&log.TextFormatter{ + DisableTimestamp: true, + CallerPrettyfier: func(f *runtime.Frame) (string, string) { + return "", "" + }, + }) } }, } diff --git a/cmd/run.go b/cmd/run.go index db65cd3..fe7ad4e 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -36,7 +36,10 @@ It is exactly behave as 'go run .' in addition of some internal goc features.`, goc run . `, Run: func(cmd *cobra.Command, args []string) { - gocBuild, _ := build.NewBuild(buildFlags, packages, buildOutput) + gocBuild, err := build.NewBuild(buildFlags, args, buildOutput) + if err != nil { + log.Fatalf("Fail to run: %v", err) + } gocBuild.GoRunExecFlag = goRunExecFlag gocBuild.GoRunArguments = goRunArguments defer gocBuild.Clean() @@ -53,7 +56,9 @@ goc run . // execute covers for the target source with original buildFlags and new GOPATH( tmp:original ) cover.Execute(buildFlags, gocBuild.NewGOPATH, gocBuild.TmpDir, mode, gocServer) - gocBuild.Run() + if err := gocBuild.Run(); err != nil { + log.Fatalln("Fail to run: %v", err) + } }, } diff --git a/pkg/build/build.go b/pkg/build/build.go index d8e2319..ec743a5 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -53,17 +53,23 @@ type Build struct { // NewBuild creates a Build struct which can build from goc temporary directory, // and generate binary in current working directory -func NewBuild(buildflags string, packages string, outputDir string) (*Build, error) { +func NewBuild(buildflags string, args []string, outputDir string) (*Build, error) { + if len(args) > 1 { + log.Errorln(ErrTooManyArgs) + return nil, ErrTooManyArgs + } // buildflags = buildflags + " -o " + outputDir b := &Build{ BuildFlags: buildflags, - Packages: packages, + Packages: strings.Join(args, " "), } if false == b.validatePackageForBuild() { log.Errorln(ErrWrongPackageTypeForBuild) return nil, ErrWrongPackageTypeForBuild } - b.MvProjectsToTmp() + if err := b.MvProjectsToTmp(); err != nil { + return nil, err + } dir, err := b.determineOutputDir(outputDir) b.Target = dir if err != nil { @@ -90,13 +96,13 @@ func (b *Build) Build() error { err := cmd.Start() if err != nil { log.Errorf("Fail to execute: %v. The error is: %v", cmd.Args, err) - return fmt.Errorf("fail to execute: %v: %w", cmd.Args, err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) } if err = cmd.Wait(); err != nil { log.Errorf("go build failed. The error is: %v", err) - return fmt.Errorf("go build faileds: %w", err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) } - log.Println("Go build exit successful.") + log.Infoln("Go build exit successful.") return nil } @@ -110,7 +116,7 @@ func (b *Build) determineOutputDir(outputDir string) (string, error) { curWorkingDir, err := os.Getwd() if err != nil { log.Errorf("Cannot get current working directory: %v", err) - return "", fmt.Errorf("cannot get current working directory: %w", err) + return "", err } if outputDir == "" { @@ -125,21 +131,21 @@ func (b *Build) determineOutputDir(outputDir string) (string, error) { abs, err := filepath.Abs(outputDir) if err != nil { log.Errorf("Fail to transform the path: %v to absolute path: %v", outputDir, err) - return "", fmt.Errorf("fail to transform the path %v to absolute path: %w", outputDir, err) + return "", err } return abs, nil } // validatePackageForBuild only allow . as package name func (b *Build) validatePackageForBuild() bool { - if b.Packages == "." { + if b.Packages == "." || b.Packages == "" { return true } return false } // Run excutes the main package in addition with the internal goc features -func (b *Build) Run() { +func (b *Build) Run() error { cmd := exec.Command("/bin/bash", "-c", "go run "+b.BuildFlags+" "+b.GoRunExecFlag+" "+b.Packages+" "+b.GoRunArguments) cmd.Dir = b.TmpWorkingDir @@ -148,16 +154,19 @@ func (b *Build) Run() { cmd.Env = append(os.Environ(), fmt.Sprintf("GOPATH=%v", b.NewGOPATH)) } - log.Printf("go build cmd is: %v", cmd.Args) + log.Infof("go build cmd is: %v", cmd.Args) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Start() if err != nil { - log.Fatalf("Fail to start command: %v. The error is: %v", cmd.Args, err) + log.Errorf("Fail to start command: %v. The error is: %v", cmd.Args, err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) } if err = cmd.Wait(); err != nil { - log.Fatalf("Fail to execute command: %v. The error is: %v", cmd.Args, err) + log.Errorf("Fail to go run: %v. The error is: %v", cmd.Args, err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) } + return nil } diff --git a/pkg/build/build_test.go b/pkg/build/build_test.go index fa25263..853978f 100644 --- a/pkg/build/build_test.go +++ b/pkg/build/build_test.go @@ -17,10 +17,11 @@ package build import ( - "github.com/stretchr/testify/assert" "os" "path/filepath" "testing" + + "github.com/stretchr/testify/assert" ) func TestInvalidPackage(t *testing.T) { @@ -32,7 +33,7 @@ func TestInvalidPackage(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - _, err := NewBuild("", "example.com/simple-project", "") + _, err := NewBuild("", []string{"example.com/simple-project"}, "") assert.Equal(t, err, ErrWrongPackageTypeForBuild, "the package name should be invalid") } @@ -44,8 +45,8 @@ func TestBasicBuildForModProject(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - buildFlags, packages, buildOutput := "", ".", "" - gocBuild, err := NewBuild(buildFlags, packages, buildOutput) + buildFlags, args, buildOutput := "", []string{"."}, "" + gocBuild, err := NewBuild(buildFlags, args, buildOutput) assert.Equal(t, err, nil, "should create temporary directory successfully") err = gocBuild.Build() diff --git a/pkg/build/errors.go b/pkg/build/errors.go index c46cec7..eef49b5 100644 --- a/pkg/build/errors.go +++ b/pkg/build/errors.go @@ -9,6 +9,7 @@ var ( ErrGocShouldExecInProject = errors.New("goc not executed in project directory") ErrWrongPackageTypeForInstall = errors.New("packages only support \".\" and \"./...\"") ErrWrongPackageTypeForBuild = errors.New("packages only support \".\"") + ErrTooManyArgs = errors.New("too many args") ErrWrongCallSequence = errors.New("function should be called in a specified sequence") ErrNoplaceToInstall = errors.New("no go env") ) diff --git a/pkg/build/install.go b/pkg/build/install.go index 5d20687..c6b9fa5 100644 --- a/pkg/build/install.go +++ b/pkg/build/install.go @@ -20,21 +20,28 @@ import ( "fmt" "os" "os/exec" + "strings" log "github.com/sirupsen/logrus" ) // NewInstall creates a Build struct which can install from goc temporary directory -func NewInstall(buildflags string, packages string) (*Build, error) { +func NewInstall(buildflags string, args []string) (*Build, error) { + if len(args) > 1 { + log.Errorf("Too many args") + return nil, ErrTooManyArgs + } b := &Build{ BuildFlags: buildflags, - Packages: packages, + Packages: strings.Join(args, " "), } if false == b.validatePackageForInstall() { log.Errorln(ErrWrongPackageTypeForInstall) return nil, ErrWrongPackageTypeForInstall } - b.MvProjectsToTmp() + if err := b.MvProjectsToTmp(); err != nil { + return nil, err + } return b, nil } @@ -61,18 +68,18 @@ func (b *Build) Install() error { err = cmd.Start() if err != nil { log.Errorf("Fail to execute: %v. The error is: %v", cmd.Args, err) - return fmt.Errorf("fail to execute: %v: %w", cmd.Args, err) + return err } if err = cmd.Wait(); err != nil { log.Errorf("go install failed. The error is: %v", err) - return fmt.Errorf("go install failed: %w", err) + return err } log.Infof("Go install successful. Binary installed in: %v", whereToInstall) return nil } func (b *Build) validatePackageForInstall() bool { - if b.Packages == "." || b.Packages == "./..." { + if b.Packages == "." || b.Packages == "" || b.Packages == "./..." { return true } return false diff --git a/pkg/build/install_test.go b/pkg/build/install_test.go index 9108b3f..8f08b71 100644 --- a/pkg/build/install_test.go +++ b/pkg/build/install_test.go @@ -1,10 +1,11 @@ package build import ( - "github.com/stretchr/testify/assert" "os" "path/filepath" "testing" + + "github.com/stretchr/testify/assert" ) func TestBasicInstallForModProject(t *testing.T) { @@ -15,7 +16,7 @@ func TestBasicInstallForModProject(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - buildFlags, packages := "", "." + buildFlags, packages := "", []string{"."} gocBuild, err := NewInstall(buildFlags, packages) assert.Equal(t, err, nil, "should create temporary directory successfully") diff --git a/pkg/build/tmpfolder.go b/pkg/build/tmpfolder.go index 166035e..f9f48a6 100644 --- a/pkg/build/tmpfolder.go +++ b/pkg/build/tmpfolder.go @@ -29,15 +29,24 @@ import ( "github.com/spf13/viper" ) -func (b *Build) MvProjectsToTmp() { +func (b *Build) MvProjectsToTmp() error { listArgs := []string{"-json"} if len(b.BuildFlags) != 0 { listArgs = append(listArgs, b.BuildFlags) } listArgs = append(listArgs, "./...") - b.Pkgs = cover.ListPackages(".", strings.Join(listArgs, " "), "") + var err error + b.Pkgs, err = cover.ListPackages(".", strings.Join(listArgs, " "), "") + if err != nil { + log.Errorln(err) + return err + } - b.mvProjectsToTmp() + err = b.mvProjectsToTmp() + if err != nil { + log.Errorf("Fail to move the project to temporary directory") + return err + } b.OriGOPATH = os.Getenv("GOPATH") if b.IsMod == true { b.NewGOPATH = "" @@ -53,8 +62,8 @@ func (b *Build) MvProjectsToTmp() { if b.Root == "" && b.IsMod == false { b.NewGOPATH = b.OriGOPATH } - log.Printf("New GOPATH: %v", b.NewGOPATH) - return + log.Infof("New GOPATH: %v", b.NewGOPATH) + return nil } func (b *Build) mvProjectsToTmp() error { @@ -84,7 +93,7 @@ func (b *Build) mvProjectsToTmp() error { b.TmpWorkingDir, err = b.getTmpwd() if err != nil { log.Errorf("fail to get workding directory in temporary directory: %v", err) - return fmt.Errorf("fail to get workding directory in temporary directory: %w", err) + return fmt.Errorf("getTmpwd failed with error: %w", err) } // issue #14 // if b.Root == "", then the project is non-standard project @@ -109,7 +118,7 @@ func TmpFolderName(path string) string { sum := sha256.Sum256([]byte(path)) h := fmt.Sprintf("%x", sum[:6]) - return "goc-" + h + return "goc-build-" + h } // traversePkgsList travse the Build.Pkgs list @@ -128,7 +137,7 @@ func (b *Build) traversePkgsList() (isMod bool, root string, err error) { isMod = true return } - log.Error("should not reach here") + log.Error(ErrShouldNotReached) err = ErrShouldNotReached return } diff --git a/pkg/build/tmpfolder_test.go b/pkg/build/tmpfolder_test.go index ed4f4b8..2021c78 100644 --- a/pkg/build/tmpfolder_test.go +++ b/pkg/build/tmpfolder_test.go @@ -39,7 +39,7 @@ func TestNewDirParseInLegacyProject(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") - b, _ := NewInstall("", ".") + b, _ := NewInstall("", []string{"."}) if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -48,7 +48,7 @@ func TestNewDirParseInLegacyProject(t *testing.T) { t.Fatalf("The New GOPATH is wrong. newgopath: %v, tmpdir: %v", b.NewGOPATH, b.TmpDir) } - b, _ = NewBuild("", ".", "") + b, _ = NewBuild("", []string{"."}, "") if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -67,7 +67,7 @@ func TestNewDirParseInModProject(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - b, _ := NewInstall("", ".") + b, _ := NewInstall("", []string{"."}) if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -76,7 +76,7 @@ func TestNewDirParseInModProject(t *testing.T) { t.Fatalf("The New GOPATH is wrong. newgopath: %v, tmpdir: %v", b.NewGOPATH, b.TmpDir) } - b, _ = NewBuild("", ".", "") + b, _ = NewBuild("", []string{"."}, "") if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -96,7 +96,7 @@ func TestLegacyProjectNotInGoPATH(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") - b, _ := NewBuild("", ".", "") + b, _ := NewBuild("", []string{"."}, "") if b.OriGOPATH != b.NewGOPATH { t.Fatalf("New GOPATH should be same with old GOPATH, for this kind of project. New: %v, old: %v", b.NewGOPATH, b.OriGOPATH) } diff --git a/pkg/cover/cover.go b/pkg/cover/cover.go index e28ae66..688095f 100644 --- a/pkg/cover/cover.go +++ b/pkg/cover/cover.go @@ -21,6 +21,7 @@ import ( "bytes" "crypto/sha256" "encoding/json" + "errors" "fmt" "io" "io/ioutil" @@ -37,6 +38,11 @@ import ( "github.com/sirupsen/logrus" ) +var ( + ErrCoverPkgFailed = errors.New("fail to inject code to project") + ErrCoverListFailed = errors.New("fail to list package dependencies") +) + // TestCover is a collection of all counters type TestCover struct { Mode string @@ -114,9 +120,10 @@ type PackageError struct { } //Execute execute go tool cover for all the .go files in the target folder -func Execute(args, newGopath, target, mode, center string) { +func Execute(args, newGopath, target, mode, center string) error { if !isDirExist(target) { - log.Fatalf("target directory %s not exist", target) + log.Errorf("Target directory %s not exist", target) + return ErrCoverPkgFailed } listArgs := []string{"-json"} @@ -124,7 +131,11 @@ func Execute(args, newGopath, target, mode, center string) { listArgs = append(listArgs, args) } listArgs = append(listArgs, "./...") - pkgs := ListPackages(target, strings.Join(listArgs, " "), newGopath) + pkgs, err := ListPackages(target, strings.Join(listArgs, " "), newGopath) + if err != nil { + log.Errorf("Fail to list all packages, the error: %v", err) + return err + } var seen = make(map[string]*PackageCover) var seenCache = make(map[string]*PackageCover) @@ -134,7 +145,8 @@ func Execute(args, newGopath, target, mode, center string) { // inject the main package mainCover, err := AddCounters(pkg, mode, newGopath) if err != nil { - log.Fatalf("failed to add counters for pkg %s, err: %v", pkg.ImportPath, err) + log.Errorf("failed to add counters for pkg %s, err: %v", pkg.ImportPath, err) + return ErrCoverPkgFailed } // new a testcover for this service @@ -158,7 +170,7 @@ func Execute(args, newGopath, target, mode, center string) { if hasInternalPath(dep) { //scan exist cache cover to tc.CacheCover if cache, ok := seenCache[dep]; ok { - log.Printf("cache cover exist: %s", cache.Package.ImportPath) + log.Infof("cache cover exist: %s", cache.Package.ImportPath) tc.CacheCover[cache.Package.Dir] = cache continue } @@ -166,7 +178,8 @@ func Execute(args, newGopath, target, mode, center string) { // add counter for internal package inPkgCover, err := AddCounters(depPkg, mode, newGopath) if err != nil { - log.Fatalf("failed to add counters for internal pkg %s, err: %v", depPkg.ImportPath, err) + log.Errorf("failed to add counters for internal pkg %s, err: %v", depPkg.ImportPath, err) + return ErrCoverPkgFailed } parentDir := getInternalParent(depPkg.Dir) parentImportPath := getInternalParent(depPkg.ImportPath) @@ -212,7 +225,8 @@ func Execute(args, newGopath, target, mode, center string) { packageCover, err := AddCounters(depPkg, mode, newGopath) if err != nil { - log.Fatalf("failed to add counters for pkg %s, err: %v", depPkg.ImportPath, err) + log.Errorf("failed to add counters for pkg %s, err: %v", depPkg.ImportPath, err) + return err } tc.DepsCover = append(tc.DepsCover, packageCover) seen[dep] = packageCover @@ -220,21 +234,25 @@ func Execute(args, newGopath, target, mode, center string) { } if errs := InjectCacheCounters(internalPkgCache, tc.CacheCover); len(errs) > 0 { - log.Fatalf("failed to inject cache counters for package: %s, err: %v", pkg.ImportPath, errs) + log.Errorf("failed to inject cache counters for package: %s, err: %v", pkg.ImportPath, errs) + return ErrCoverPkgFailed } // inject Http Cover APIs var httpCoverApis = fmt.Sprintf("%s/http_cover_apis_auto_generated.go", pkg.Dir) if err := InjectCountersHandlers(tc, httpCoverApis); err != nil { - log.Fatalf("failed to inject counters for package: %s, err: %v", pkg.ImportPath, err) + log.Errorf("failed to inject counters for package: %s, err: %v", pkg.ImportPath, err) + return ErrCoverPkgFailed } } } + + return nil } // ListPackages list all packages under specific via go list command // The argument newgopath is if you need to go list in a different GOPATH -func ListPackages(dir string, args string, newgopath string) map[string]*Package { +func ListPackages(dir string, args string, newgopath string) (map[string]*Package, error) { cmd := exec.Command("/bin/bash", "-c", "go list "+args) log.Printf("go list cmd is: %v", cmd.Args) cmd.Dir = dir @@ -243,7 +261,8 @@ func ListPackages(dir string, args string, newgopath string) map[string]*Package } out, err := cmd.CombinedOutput() if err != nil { - log.Fatalf("excute `go list -json ./...` command failed, err: %v, out: %v", err, string(out)) + log.Errorf("excute `go list -json ./...` command failed, err: %v, out: %v", err, string(out)) + return nil, ErrCoverListFailed } dec := json.NewDecoder(bytes.NewReader(out)) @@ -254,10 +273,12 @@ func ListPackages(dir string, args string, newgopath string) map[string]*Package if err == io.EOF { break } - log.Fatalf("reading go list output: %v", err) + log.Errorf("reading go list output: %v", err) + return nil, ErrCoverListFailed } if pkg.Error != nil { - log.Fatalf("list package %s failed with output: %v", pkg.ImportPath, pkg.Error) + log.Errorf("list package %s failed with output: %v", pkg.ImportPath, pkg.Error) + return nil, ErrCoverPkgFailed } // for _, err := range pkg.DepsErrors { @@ -266,7 +287,7 @@ func ListPackages(dir string, args string, newgopath string) map[string]*Package pkgs[pkg.ImportPath] = &pkg } - return pkgs + return pkgs, nil } // AddCounters add counters for all go files under the package From 2a8d444043bdbc9637b89f48ec073d4478a41a28 Mon Sep 17 00:00:00 2001 From: lyyyuna Date: Thu, 18 Jun 2020 16:26:06 +0800 Subject: [PATCH 2/4] fix ci --- cmd/run.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/run.go b/cmd/run.go index fe7ad4e..ef20668 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -57,7 +57,7 @@ goc run . cover.Execute(buildFlags, gocBuild.NewGOPATH, gocBuild.TmpDir, mode, gocServer) if err := gocBuild.Run(); err != nil { - log.Fatalln("Fail to run: %v", err) + log.Fatalf("Fail to run: %v", err) } }, } From 7916d1ee6887a3c7e898f75ce287953fa183f40c Mon Sep 17 00:00:00 2001 From: lyyyuna Date: Thu, 18 Jun 2020 17:03:14 +0800 Subject: [PATCH 3/4] get current working directory only once --- cmd/build.go | 12 ++++++--- cmd/build_test.go | 3 +-- cmd/install.go | 12 ++++++--- cmd/install_test.go | 6 ++--- cmd/run.go | 7 ++++- pkg/build/build.go | 45 ++++++++++---------------------- pkg/build/build_test.go | 6 ++--- pkg/build/errors.go | 3 ++- pkg/build/install.go | 8 +++--- pkg/build/install_test.go | 3 +-- pkg/build/legacy.go | 7 ----- pkg/build/run.go | 52 +++++++++++++++++++++++++++++++++++++ pkg/build/tmpfolder.go | 27 +++++-------------- pkg/build/tmpfolder_test.go | 14 ++++------ 14 files changed, 113 insertions(+), 92 deletions(-) create mode 100644 pkg/build/run.go diff --git a/cmd/build.go b/cmd/build.go index 7bbec8f..3a835c6 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -17,6 +17,8 @@ package cmd import ( + "os" + log "github.com/sirupsen/logrus" "github.com/qiniu/goc/pkg/build" @@ -44,7 +46,11 @@ goc build --output /to/this/path goc build --buildflags="-ldflags '-extldflags -static' -tags='embed kodo'" `, Run: func(cmd *cobra.Command, args []string) { - runBuild(args) + wd, err := os.Getwd() + if err != nil { + log.Fatalf("Fail to build: %v", err) + } + runBuild(args, wd) }, } @@ -56,8 +62,8 @@ func init() { rootCmd.AddCommand(buildCmd) } -func runBuild(args []string) { - gocBuild, err := build.NewBuild(buildFlags, args, buildOutput) +func runBuild(args []string, wd string) { + gocBuild, err := build.NewBuild(buildFlags, args, wd, buildOutput) if err != nil { log.Fatalf("Fail to build: %v", err) } diff --git a/cmd/build_test.go b/cmd/build_test.go index 407f8e5..dcf02f6 100644 --- a/cmd/build_test.go +++ b/cmd/build_test.go @@ -39,13 +39,12 @@ func TestGeneratedBinary(t *testing.T) { workingDir := filepath.Join(baseDir, "../tests/samples/simple_project") gopath := "" - os.Chdir(workingDir) os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") buildFlags, buildOutput = "", "" args := []string{"."} - runBuild(args) + runBuild(args, workingDir) obj := filepath.Join(".", "simple-project") fInfo, err := os.Lstat(obj) diff --git a/cmd/install.go b/cmd/install.go index be9b7c2..e173715 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -17,6 +17,8 @@ package cmd import ( + "os" + "github.com/qiniu/goc/pkg/build" "github.com/qiniu/goc/pkg/cover" log "github.com/sirupsen/logrus" @@ -40,7 +42,11 @@ goc install --center=http://127.0.0.1:7777 goc build --buildflags="-ldflags '-extldflags -static' -tags='embed kodo'" `, Run: func(cmd *cobra.Command, args []string) { - runInstall(args) + wd, err := os.Getwd() + if err != nil { + log.Fatalf("Fail to build: %v", err) + } + runInstall(args, wd) }, } @@ -49,8 +55,8 @@ func init() { rootCmd.AddCommand(installCmd) } -func runInstall(args []string) { - gocBuild, err := build.NewInstall(buildFlags, args) +func runInstall(args []string, wd string) { + gocBuild, err := build.NewInstall(buildFlags, args, wd) if err != nil { log.Fatalf("Fail to install: %v", err) } diff --git a/cmd/install_test.go b/cmd/install_test.go index a64a221..d18a674 100644 --- a/cmd/install_test.go +++ b/cmd/install_test.go @@ -33,13 +33,12 @@ func TestInstalledBinaryForMod(t *testing.T) { workingDir := filepath.Join(baseDir, "../tests/samples/simple_project") gopath := filepath.Join(baseDir, "../tests/samples/simple_project", "testhome") - os.Chdir(workingDir) os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") buildFlags, buildOutput = "", "" args := []string{"."} - runInstall(args) + runInstall(args, workingDir) obj := filepath.Join(gopath, "bin", "simple-project") fInfo, err := os.Lstat(obj) @@ -62,13 +61,12 @@ func TestInstalledBinaryForLegacy(t *testing.T) { workingDir := filepath.Join(baseDir, "../tests/samples/simple_gopath_project/src/qiniu.com/simple_gopath_project") gopath := filepath.Join(baseDir, "../tests/samples/simple_gopath_project") - os.Chdir(workingDir) os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") buildFlags, buildOutput = "", "" args := []string{"."} - runInstall(args) + runInstall(args, workingDir) obj := filepath.Join(gopath, "bin", "simple_gopath_project") fInfo, err := os.Lstat(obj) diff --git a/cmd/run.go b/cmd/run.go index ef20668..19d275a 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -20,6 +20,7 @@ import ( "fmt" "io/ioutil" "net" + "os" "github.com/qiniu/goc/pkg/build" "github.com/qiniu/goc/pkg/cover" @@ -36,7 +37,11 @@ It is exactly behave as 'go run .' in addition of some internal goc features.`, goc run . `, Run: func(cmd *cobra.Command, args []string) { - gocBuild, err := build.NewBuild(buildFlags, args, buildOutput) + wd, err := os.Getwd() + if err != nil { + log.Fatalf("Fail to build: %v", err) + } + gocBuild, err := build.NewBuild(buildFlags, args, buildOutput, wd) if err != nil { log.Fatalf("Fail to run: %v", err) } diff --git a/pkg/build/build.go b/pkg/build/build.go index ec743a5..3cb982d 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -32,6 +32,7 @@ type Build struct { Pkgs map[string]*cover.Package // Pkg list parsed from "go list -json ./..." command NewGOPATH string // the new GOPATH OriGOPATH string // the original GOPATH + WorkingDir string // the working directory TmpDir string // the temporary directory to build the project TmpWorkingDir string // the working directory in the temporary directory, which is corresponding to the current directory in the project directory IsMod bool // determine whether it is a Mod project @@ -53,15 +54,15 @@ type Build struct { // NewBuild creates a Build struct which can build from goc temporary directory, // and generate binary in current working directory -func NewBuild(buildflags string, args []string, outputDir string) (*Build, error) { - if len(args) > 1 { - log.Errorln(ErrTooManyArgs) - return nil, ErrTooManyArgs +func NewBuild(buildflags string, args []string, workingDir string, outputDir string) (*Build, error) { + if err := checkParameters(args, workingDir); err != nil { + return nil, err } // buildflags = buildflags + " -o " + outputDir b := &Build{ BuildFlags: buildflags, Packages: strings.Join(args, " "), + WorkingDir: workingDir, } if false == b.validatePackageForBuild() { log.Errorln(ErrWrongPackageTypeForBuild) @@ -113,20 +114,15 @@ func (b *Build) determineOutputDir(outputDir string) (string, error) { log.Errorf("Can only be called after Build.MvProjectsToTmp(): %v", ErrWrongCallSequence) return "", fmt.Errorf("can only be called after Build.MvProjectsToTmp(): %w", ErrWrongCallSequence) } - curWorkingDir, err := os.Getwd() - if err != nil { - log.Errorf("Cannot get current working directory: %v", err) - return "", err - } if outputDir == "" { - _, last := filepath.Split(curWorkingDir) + _, last := filepath.Split(b.WorkingDir) if b.IsMod { // in mod, special rule // replace "_" with "-" in the import path last = strings.ReplaceAll(last, "_", "-") } - return filepath.Join(curWorkingDir, last), nil + return filepath.Join(b.WorkingDir, last), nil } abs, err := filepath.Abs(outputDir) if err != nil { @@ -144,29 +140,14 @@ func (b *Build) validatePackageForBuild() bool { return false } -// Run excutes the main package in addition with the internal goc features -func (b *Build) Run() error { - cmd := exec.Command("/bin/bash", "-c", "go run "+b.BuildFlags+" "+b.GoRunExecFlag+" "+b.Packages+" "+b.GoRunArguments) - cmd.Dir = b.TmpWorkingDir - - if b.NewGOPATH != "" { - // Change to temp GOPATH for go install command - cmd.Env = append(os.Environ(), fmt.Sprintf("GOPATH=%v", b.NewGOPATH)) +func checkParameters(args []string, workingDir string) error { + if len(args) > 1 { + log.Errorln(ErrTooManyArgs) + return ErrTooManyArgs } - log.Infof("go build cmd is: %v", cmd.Args) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - err := cmd.Start() - if err != nil { - log.Errorf("Fail to start command: %v. The error is: %v", cmd.Args, err) - return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) + if workingDir == "" { + return ErrInvalidWorkingDir } - - if err = cmd.Wait(); err != nil { - log.Errorf("Fail to go run: %v. The error is: %v", cmd.Args, err) - return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) - } - return nil } diff --git a/pkg/build/build_test.go b/pkg/build/build_test.go index 853978f..fcc3142 100644 --- a/pkg/build/build_test.go +++ b/pkg/build/build_test.go @@ -29,11 +29,10 @@ func TestInvalidPackage(t *testing.T) { workingDir := filepath.Join(baseDir, "../../tests/samples/simple_project") gopath := "" - os.Chdir(workingDir) os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - _, err := NewBuild("", []string{"example.com/simple-project"}, "") + _, err := NewBuild("", []string{"example.com/simple-project"}, "", workingDir) assert.Equal(t, err, ErrWrongPackageTypeForBuild, "the package name should be invalid") } @@ -41,12 +40,11 @@ func TestBasicBuildForModProject(t *testing.T) { workingDir := filepath.Join(baseDir, "../tests/samples/simple_project") gopath := "" - os.Chdir(workingDir) os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") buildFlags, args, buildOutput := "", []string{"."}, "" - gocBuild, err := NewBuild(buildFlags, args, buildOutput) + gocBuild, err := NewBuild(buildFlags, args, buildOutput, workingDir) assert.Equal(t, err, nil, "should create temporary directory successfully") err = gocBuild.Build() diff --git a/pkg/build/errors.go b/pkg/build/errors.go index eef49b5..6359434 100644 --- a/pkg/build/errors.go +++ b/pkg/build/errors.go @@ -10,6 +10,7 @@ var ( ErrWrongPackageTypeForInstall = errors.New("packages only support \".\" and \"./...\"") ErrWrongPackageTypeForBuild = errors.New("packages only support \".\"") ErrTooManyArgs = errors.New("too many args") + ErrInvalidWorkingDir = errors.New("the working directory is invalid") ErrWrongCallSequence = errors.New("function should be called in a specified sequence") - ErrNoplaceToInstall = errors.New("no go env") + ErrNoplaceToInstall = errors.New("dont know where to install") ) diff --git a/pkg/build/install.go b/pkg/build/install.go index c6b9fa5..8546e46 100644 --- a/pkg/build/install.go +++ b/pkg/build/install.go @@ -26,14 +26,14 @@ import ( ) // NewInstall creates a Build struct which can install from goc temporary directory -func NewInstall(buildflags string, args []string) (*Build, error) { - if len(args) > 1 { - log.Errorf("Too many args") - return nil, ErrTooManyArgs +func NewInstall(buildflags string, args []string, workingDir string) (*Build, error) { + if err := checkParameters(args, workingDir); err != nil { + return nil, err } b := &Build{ BuildFlags: buildflags, Packages: strings.Join(args, " "), + WorkingDir: workingDir, } if false == b.validatePackageForInstall() { log.Errorln(ErrWrongPackageTypeForInstall) diff --git a/pkg/build/install_test.go b/pkg/build/install_test.go index 8f08b71..9b80bb1 100644 --- a/pkg/build/install_test.go +++ b/pkg/build/install_test.go @@ -12,12 +12,11 @@ func TestBasicInstallForModProject(t *testing.T) { workingDir := filepath.Join(baseDir, "../tests/samples/simple_project") gopath := filepath.Join(baseDir, "../tests/samples/simple_project", "testhome") - os.Chdir(workingDir) os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") buildFlags, packages := "", []string{"."} - gocBuild, err := NewInstall(buildFlags, packages) + gocBuild, err := NewInstall(buildFlags, packages, workingDir) assert.Equal(t, err, nil, "should create temporary directory successfully") err = gocBuild.Install() diff --git a/pkg/build/legacy.go b/pkg/build/legacy.go index 6627544..72f5c55 100644 --- a/pkg/build/legacy.go +++ b/pkg/build/legacy.go @@ -50,13 +50,6 @@ func (b *Build) cpLegacyProject() { // only cp dependency in root(current gopath), // skip deps in other GOPATHs func (b *Build) cpDepPackages(pkg *cover.Package, visited map[string]bool) { - /* - oriGOPATH := os.Getenv("GOPATH") - if oriGOPATH == "" { - oriGOPATH = filepath.Join(os.Getenv("HOME"), "go") - } - gopaths := strings.Split(oriGOPATH, ":") - */ gopath := pkg.Root for _, dep := range pkg.Deps { src := filepath.Join(gopath, "src", dep) diff --git a/pkg/build/run.go b/pkg/build/run.go new file mode 100644 index 0000000..43ca1a4 --- /dev/null +++ b/pkg/build/run.go @@ -0,0 +1,52 @@ +/* + Copyright 2020 Qiniu Cloud (qiniu.com) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package build + +import ( + "fmt" + "os" + "os/exec" + + log "github.com/sirupsen/logrus" +) + +// Run excutes the main package in addition with the internal goc features +func (b *Build) Run() error { + cmd := exec.Command("/bin/bash", "-c", "go run "+b.BuildFlags+" "+b.GoRunExecFlag+" "+b.Packages+" "+b.GoRunArguments) + cmd.Dir = b.TmpWorkingDir + + if b.NewGOPATH != "" { + // Change to temp GOPATH for go install command + cmd.Env = append(os.Environ(), fmt.Sprintf("GOPATH=%v", b.NewGOPATH)) + } + + log.Infof("go build cmd is: %v", cmd.Args) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Start() + if err != nil { + log.Errorf("Fail to start command: %v. The error is: %v", cmd.Args, err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) + } + + if err = cmd.Wait(); err != nil { + log.Errorf("Fail to go run: %v. The error is: %v", cmd.Args, err) + return fmt.Errorf("fail to execute: %v, err: %w", cmd.Args, err) + } + + return nil +} diff --git a/pkg/build/tmpfolder.go b/pkg/build/tmpfolder.go index f9f48a6..1f64fd5 100644 --- a/pkg/build/tmpfolder.go +++ b/pkg/build/tmpfolder.go @@ -67,17 +67,12 @@ func (b *Build) MvProjectsToTmp() error { } func (b *Build) mvProjectsToTmp() error { - path, err := os.Getwd() - if err != nil { - log.Errorf("Cannot get current working directory, the error is: %v", err) - return err - } - b.TmpDir = filepath.Join(os.TempDir(), TmpFolderName(path)) + b.TmpDir = filepath.Join(os.TempDir(), TmpFolderName(b.WorkingDir)) // Delete previous tmp folder and its content os.RemoveAll(b.TmpDir) // Create a new tmp folder - err = os.MkdirAll(filepath.Join(b.TmpDir, "src"), os.ModePerm) + err := os.MkdirAll(filepath.Join(b.TmpDir, "src"), os.ModePerm) if err != nil { log.Errorf("Fail to create the temporary build directory. The err is: %v", err) return err @@ -146,19 +141,13 @@ func (b *Build) traversePkgsList() (isMod bool, root string, err error) { // and store it in the Build.tmpWorkdingDir func (b *Build) getTmpwd() (string, error) { for _, pkg := range b.Pkgs { - path, err := os.Getwd() - if err != nil { - log.Errorf("cannot get current working directory: %v", err) - return "", fmt.Errorf("cannot get current working directory: %w", err) - } - index := -1 var parentPath string if b.IsMod == false { - index = strings.Index(path, pkg.Root) + index = strings.Index(b.WorkingDir, pkg.Root) parentPath = pkg.Root } else { - index = strings.Index(path, pkg.Module.Dir) + index = strings.Index(b.WorkingDir, pkg.Module.Dir) parentPath = pkg.Module.Dir } @@ -166,7 +155,7 @@ func (b *Build) getTmpwd() (string, error) { return "", ErrGocShouldExecInProject } // b.TmpWorkingDir = filepath.Join(b.TmpDir, path[len(parentPath):]) - return filepath.Join(b.TmpDir, path[len(parentPath):]), nil + return filepath.Join(b.TmpDir, b.WorkingDir[len(parentPath):]), nil } return "", ErrShouldNotReached @@ -177,16 +166,14 @@ func (b *Build) findWhereToInstall() (string, error) { return GOBIN, nil } - // old GOPATH dir - GOPATH := os.Getenv("GOPATH") if false == b.IsMod { if b.Root == "" { return "", ErrNoplaceToInstall } return filepath.Join(b.Root, "bin"), nil } - if GOPATH != "" { - return filepath.Join(strings.Split(GOPATH, ":")[0], "bin"), nil + if b.OriGOPATH != "" { + return filepath.Join(strings.Split(b.OriGOPATH, ":")[0], "bin"), nil } return filepath.Join(os.Getenv("HOME"), "go", "bin"), nil } diff --git a/pkg/build/tmpfolder_test.go b/pkg/build/tmpfolder_test.go index 2021c78..81df11c 100644 --- a/pkg/build/tmpfolder_test.go +++ b/pkg/build/tmpfolder_test.go @@ -34,12 +34,10 @@ func TestNewDirParseInLegacyProject(t *testing.T) { workingDir := filepath.Join(baseDir, "../../tests/samples/simple_gopath_project/src/qiniu.com/simple_gopath_project") gopath := filepath.Join(baseDir, "../../tests/samples/simple_gopath_project") - os.Chdir(workingDir) - os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") - b, _ := NewInstall("", []string{"."}) + b, _ := NewInstall("", []string{"."}, workingDir) if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -48,7 +46,7 @@ func TestNewDirParseInLegacyProject(t *testing.T) { t.Fatalf("The New GOPATH is wrong. newgopath: %v, tmpdir: %v", b.NewGOPATH, b.TmpDir) } - b, _ = NewBuild("", []string{"."}, "") + b, _ = NewBuild("", []string{"."}, "", workingDir) if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -62,12 +60,11 @@ func TestNewDirParseInModProject(t *testing.T) { workingDir := filepath.Join(baseDir, "../../tests/samples/simple_project") gopath := "" - os.Chdir(workingDir) fmt.Println(gopath) os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - b, _ := NewInstall("", []string{"."}) + b, _ := NewInstall("", []string{"."}, workingDir) if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -76,7 +73,7 @@ func TestNewDirParseInModProject(t *testing.T) { t.Fatalf("The New GOPATH is wrong. newgopath: %v, tmpdir: %v", b.NewGOPATH, b.TmpDir) } - b, _ = NewBuild("", []string{"."}, "") + b, _ = NewBuild("", []string{"."}, "", workingDir) if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -91,12 +88,11 @@ func TestLegacyProjectNotInGoPATH(t *testing.T) { workingDir := filepath.Join(baseDir, "../../tests/samples/simple_gopath_project/src/qiniu.com/simple_gopath_project") gopath := "" - os.Chdir(workingDir) fmt.Println(gopath) os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") - b, _ := NewBuild("", []string{"."}, "") + b, _ := NewBuild("", []string{"."}, "", workingDir) if b.OriGOPATH != b.NewGOPATH { t.Fatalf("New GOPATH should be same with old GOPATH, for this kind of project. New: %v, old: %v", b.NewGOPATH, b.OriGOPATH) } From 5892de106bae9ebda20d2dfba4b99b97c94cdb02 Mon Sep 17 00:00:00 2001 From: lyyyuna Date: Thu, 18 Jun 2020 18:08:48 +0800 Subject: [PATCH 4/4] fix unit test add test for cover package add unit test --- cmd/build_test.go | 2 +- cmd/root.go | 1 + cmd/run.go | 2 +- pkg/build/build.go | 2 ++ pkg/build/build_test.go | 54 ++++++++++++++++++++++++++++++++----- pkg/build/install_test.go | 26 +++++++++++++++--- pkg/build/tmpfolder.go | 3 ++- pkg/build/tmpfolder_test.go | 6 ++--- pkg/cover/cover_test.go | 38 ++++++++++++++++++++++++++ 9 files changed, 117 insertions(+), 17 deletions(-) diff --git a/cmd/build_test.go b/cmd/build_test.go index dcf02f6..9d46dee 100644 --- a/cmd/build_test.go +++ b/cmd/build_test.go @@ -46,7 +46,7 @@ func TestGeneratedBinary(t *testing.T) { args := []string{"."} runBuild(args, workingDir) - obj := filepath.Join(".", "simple-project") + obj := filepath.Join(workingDir, "simple-project") fInfo, err := os.Lstat(obj) assert.Equal(t, err, nil, "the binary should be generated.") assert.Equal(t, startTime.Before(fInfo.ModTime()), true, obj+"new binary should be generated, not the old one") diff --git a/cmd/root.go b/cmd/root.go index 09be748..3263c43 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -36,6 +36,7 @@ Find more information at: `, PersistentPreRun: func(cmd *cobra.Command, args []string) { log.SetReportCaller(true) + log.SetLevel(log.InfoLevel) log.SetFormatter(&log.TextFormatter{ FullTimestamp: true, CallerPrettyfier: func(f *runtime.Frame) (string, string) { diff --git a/cmd/run.go b/cmd/run.go index 19d275a..1dc28ae 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -41,7 +41,7 @@ goc run . if err != nil { log.Fatalf("Fail to build: %v", err) } - gocBuild, err := build.NewBuild(buildFlags, args, buildOutput, wd) + gocBuild, err := build.NewBuild(buildFlags, args, wd, buildOutput) if err != nil { log.Fatalf("Fail to run: %v", err) } diff --git a/pkg/build/build.go b/pkg/build/build.go index 3cb982d..53b8ce4 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -149,5 +149,7 @@ func checkParameters(args []string, workingDir string) error { if workingDir == "" { return ErrInvalidWorkingDir } + + log.Infof("Working directory: %v", workingDir) return nil } diff --git a/pkg/build/build_test.go b/pkg/build/build_test.go index fcc3142..82df7ea 100644 --- a/pkg/build/build_test.go +++ b/pkg/build/build_test.go @@ -17,6 +17,8 @@ package build import ( + "errors" + "fmt" "os" "path/filepath" "testing" @@ -32,21 +34,59 @@ func TestInvalidPackage(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - _, err := NewBuild("", []string{"example.com/simple-project"}, "", workingDir) - assert.Equal(t, err, ErrWrongPackageTypeForBuild, "the package name should be invalid") + _, err := NewBuild("", []string{"example.com/simple-project"}, workingDir, "") + if !assert.Equal(t, err, ErrWrongPackageTypeForBuild) { + assert.FailNow(t, "the package name should be invalid") + } } func TestBasicBuildForModProject(t *testing.T) { - workingDir := filepath.Join(baseDir, "../tests/samples/simple_project") + workingDir := filepath.Join(baseDir, "../../tests/samples/simple_project") gopath := "" os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") - + fmt.Println(workingDir) buildFlags, args, buildOutput := "", []string{"."}, "" - gocBuild, err := NewBuild(buildFlags, args, buildOutput, workingDir) - assert.Equal(t, err, nil, "should create temporary directory successfully") + gocBuild, err := NewBuild(buildFlags, args, workingDir, buildOutput) + if !assert.Equal(t, err, nil) { + assert.FailNow(t, "should create temporary directory successfully") + } err = gocBuild.Build() - assert.Equal(t, err, nil, "temporary directory should build successfully") + if !assert.Equal(t, err, nil) { + assert.FailNow(t, "temporary directory should build successfully") + } +} + +func TestCheckParameters(t *testing.T) { + err := checkParameters([]string{"aa", "bb"}, "aa") + assert.Equal(t, err, ErrTooManyArgs, "too many arguments should failed") + + err = checkParameters([]string{"aa"}, "") + assert.Equal(t, err, ErrInvalidWorkingDir, "empty working directory should failed") +} + +func TestDetermineOutputDir(t *testing.T) { + b := &Build{} + _, err := b.determineOutputDir("") + assert.Equal(t, errors.Is(err, ErrWrongCallSequence), true, "called before Build.MvProjectsToTmp() should fail") + + b.TmpDir = "fake" + _, err = b.determineOutputDir("xx") + assert.Equal(t, err, nil, "should return a directory") +} + +func TestInvalidPackageNameForBuild(t *testing.T) { + workingDir := filepath.Join(baseDir, "../../tests/samples/simple_project") + gopath := filepath.Join(baseDir, "../../tests/samples/simple_project", "testhome") + + os.Setenv("GOPATH", gopath) + os.Setenv("GO111MODULE", "on") + + buildFlags, packages := "", []string{"main.go"} + _, err := NewBuild(buildFlags, packages, workingDir, "") + if !assert.Equal(t, err, ErrWrongPackageTypeForBuild) { + assert.FailNow(t, "should not success with non . or ./... package") + } } diff --git a/pkg/build/install_test.go b/pkg/build/install_test.go index 9b80bb1..30e996b 100644 --- a/pkg/build/install_test.go +++ b/pkg/build/install_test.go @@ -9,16 +9,34 @@ import ( ) func TestBasicInstallForModProject(t *testing.T) { - workingDir := filepath.Join(baseDir, "../tests/samples/simple_project") - gopath := filepath.Join(baseDir, "../tests/samples/simple_project", "testhome") + workingDir := filepath.Join(baseDir, "../../tests/samples/simple_project") + gopath := filepath.Join(baseDir, "../../tests/samples/simple_project", "testhome") os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "on") buildFlags, packages := "", []string{"."} gocBuild, err := NewInstall(buildFlags, packages, workingDir) - assert.Equal(t, err, nil, "should create temporary directory successfully") + if !assert.Equal(t, err, nil) { + assert.FailNow(t, "should create temporary directory successfully") + } err = gocBuild.Install() - assert.Equal(t, err, nil, "temporary directory should build successfully") + if !assert.Equal(t, err, nil) { + assert.FailNow(t, "temporary directory should build successfully") + } +} + +func TestInvalidPackageNameForInstall(t *testing.T) { + workingDir := filepath.Join(baseDir, "../../tests/samples/simple_project") + gopath := filepath.Join(baseDir, "../../tests/samples/simple_project", "testhome") + + os.Setenv("GOPATH", gopath) + os.Setenv("GO111MODULE", "on") + + buildFlags, packages := "", []string{"main.go"} + _, err := NewInstall(buildFlags, packages, workingDir) + if !assert.Equal(t, err, ErrWrongPackageTypeForInstall) { + assert.FailNow(t, "should not success with non . or ./... package") + } } diff --git a/pkg/build/tmpfolder.go b/pkg/build/tmpfolder.go index 1f64fd5..5998ebd 100644 --- a/pkg/build/tmpfolder.go +++ b/pkg/build/tmpfolder.go @@ -36,7 +36,7 @@ func (b *Build) MvProjectsToTmp() error { } listArgs = append(listArgs, "./...") var err error - b.Pkgs, err = cover.ListPackages(".", strings.Join(listArgs, " "), "") + b.Pkgs, err = cover.ListPackages(b.WorkingDir, strings.Join(listArgs, " "), "") if err != nil { log.Errorln(err) return err @@ -81,6 +81,7 @@ func (b *Build) mvProjectsToTmp() error { // traverse pkg list to get project meta info b.IsMod, b.Root, err = b.traversePkgsList() + log.Infof("mod project? %v", b.IsMod) if errors.Is(err, ErrShouldNotReached) { return fmt.Errorf("mvProjectsToTmp with a empty project: %w", err) } diff --git a/pkg/build/tmpfolder_test.go b/pkg/build/tmpfolder_test.go index 81df11c..9373ac8 100644 --- a/pkg/build/tmpfolder_test.go +++ b/pkg/build/tmpfolder_test.go @@ -46,7 +46,7 @@ func TestNewDirParseInLegacyProject(t *testing.T) { t.Fatalf("The New GOPATH is wrong. newgopath: %v, tmpdir: %v", b.NewGOPATH, b.TmpDir) } - b, _ = NewBuild("", []string{"."}, "", workingDir) + b, _ = NewBuild("", []string{"."}, workingDir, "") if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -73,7 +73,7 @@ func TestNewDirParseInModProject(t *testing.T) { t.Fatalf("The New GOPATH is wrong. newgopath: %v, tmpdir: %v", b.NewGOPATH, b.TmpDir) } - b, _ = NewBuild("", []string{"."}, "", workingDir) + b, _ = NewBuild("", []string{"."}, workingDir, "") if -1 == strings.Index(b.TmpWorkingDir, b.TmpDir) { t.Fatalf("Directory parse error. newwd: %v, tmpdir: %v", b.TmpWorkingDir, b.TmpDir) } @@ -92,7 +92,7 @@ func TestLegacyProjectNotInGoPATH(t *testing.T) { os.Setenv("GOPATH", gopath) os.Setenv("GO111MODULE", "off") - b, _ := NewBuild("", []string{"."}, "", workingDir) + b, _ := NewBuild("", []string{"."}, workingDir, "") if b.OriGOPATH != b.NewGOPATH { t.Fatalf("New GOPATH should be same with old GOPATH, for this kind of project. New: %v, old: %v", b.NewGOPATH, b.OriGOPATH) } diff --git a/pkg/cover/cover_test.go b/pkg/cover/cover_test.go index 1113b87..098cc67 100644 --- a/pkg/cover/cover_test.go +++ b/pkg/cover/cover_test.go @@ -27,6 +27,7 @@ import ( log "github.com/sirupsen/logrus" + "github.com/otiai10/copy" "github.com/stretchr/testify/assert" ) @@ -304,3 +305,40 @@ func TestFindInternal(t *testing.T) { } } } + +func TestExecuteForSimpleModProject(t *testing.T) { + workingDir := "../../tests/samples/simple_project" + gopath := "" + + os.Setenv("GOPATH", gopath) + os.Setenv("GO111MODULE", "on") + + testDir := filepath.Join(os.TempDir(), "goc-build-test") + copy.Copy(workingDir, testDir) + + Execute("", gopath, testDir, "count", "http://127.0.0.1:7777") + + _, err := os.Lstat(filepath.Join(testDir, "http_cover_apis_auto_generated.go")) + if !assert.Equal(t, err, nil) { + assert.FailNow(t, "should generate http_cover_apis_auto_generated.go") + } +} + +func TestListPackagesForSimpleModProject(t *testing.T) { + workingDir := "../../tests/samples/simple_project" + gopath := "" + + os.Setenv("GOPATH", gopath) + os.Setenv("GO111MODULE", "on") + + pkgs, _ := ListPackages(workingDir, "-json ./...", "") + if !assert.Equal(t, len(pkgs), 1) { + assert.FailNow(t, "should only have one pkg") + } + if pkg, ok := pkgs["example.com/simple-project"]; ok { + assert.Equal(t, pkg.Module.Path, "example.com/simple-project") + } else { + assert.FailNow(t, "cannot get the pkg: example.com/simple-project") + } + +}