From fdd4bbcd2c549ee9ea31f7b92eaa51a830f22552 Mon Sep 17 00:00:00 2001 From: kcmvp Date: Wed, 17 Jan 2024 11:11:59 +0800 Subject: [PATCH] #69: add test for intrnal/plugin --- cmd/action.go | 2 +- internal/plugin.go | 27 ++++---- internal/plugin_test.go | 142 ++++++++++++++++++++++++++++++---------- internal/project.go | 6 +- 4 files changed, 129 insertions(+), 48 deletions(-) diff --git a/cmd/action.go b/cmd/action.go index 3a52c9c..baa3d71 100644 --- a/cmd/action.go +++ b/cmd/action.go @@ -80,7 +80,7 @@ func execute(cmd *cobra.Command, arg string) error { if err == nil { return afterExecution(cmd, arg) } - return nil + return err } func validBuilderArgs() []string { diff --git a/internal/plugin.go b/internal/plugin.go index ecef8cc..b8550e7 100644 --- a/internal/plugin.go +++ b/internal/plugin.go @@ -4,16 +4,15 @@ import ( "encoding/json" "errors" "fmt" - "github.com/kcmvp/gob/shared" //nolint + "github.com/fatih/color" + "github.com/kcmvp/gob/shared" + "github.com/samber/lo" "io/fs" "os" "os/exec" "path/filepath" "regexp" "strings" - - "github.com/fatih/color" - "github.com/samber/lo" ) const modulePattern = `^[^@]+@?[^@\s]+$` @@ -110,10 +109,10 @@ func (plugin Plugin) Binary() string { } // install a plugin when it does not exist -func (plugin Plugin) install() error { +func (plugin Plugin) install() (string, error) { gopath := GoPath() if _, err := os.Stat(filepath.Join(gopath, plugin.Binary())); err == nil { - return nil + return "", nil } tempGoPath := temporaryGoPath() defer os.RemoveAll(tempGoPath) @@ -126,9 +125,9 @@ func (plugin Plugin) install() error { return pair }) if err := cmd.Run(); err != nil { - return errors.New(color.RedString(err.Error())) + return tempGoPath, errors.New(color.RedString(err.Error())) } - return filepath.WalkDir(tempGoPath, func(path string, d fs.DirEntry, err error) error { + return tempGoPath, filepath.WalkDir(tempGoPath, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } @@ -147,9 +146,15 @@ func (plugin Plugin) install() error { } func (plugin Plugin) Execute() error { - if err := plugin.install(); err != nil { + if _, err := plugin.install(); err != nil { return err } - exeCmd := exec.Command(plugin.Binary(), strings.Split(plugin.Args, " ")...) //nolint #gosec - return shared.StreamCmdOutput(exeCmd, filepath.Join(CurProject().Target(), fmt.Sprintf("%s.log", plugin.logName()))) + pCmd := exec.Command(plugin.Binary(), strings.Split(plugin.Args, " ")...) //nolint #gosec + if err := shared.StreamCmdOutput(pCmd, filepath.Join(CurProject().Target(), fmt.Sprintf("%s.log", plugin.logName()))); err != nil { + return err + } + if pCmd.ProcessState.ExitCode() != 0 { + return fmt.Errorf("faild %d", pCmd.ProcessState.ExitCode()) + } + return nil } diff --git a/internal/plugin_test.go b/internal/plugin_test.go index 289e26c..6397560 100644 --- a/internal/plugin_test.go +++ b/internal/plugin_test.go @@ -2,62 +2,112 @@ package internal import ( "encoding/json" + "fmt" "github.com/samber/lo" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" "github.com/tidwall/gjson" "os" "path/filepath" "testing" ) -func TestNewPlugin(t *testing.T) { +type InternalPluginTestSuit struct { + suite.Suite + testDir string + goPath string +} + +func (suite *InternalPluginTestSuit) SetupSuite() { + os.RemoveAll(suite.goPath) + os.RemoveAll(suite.testDir) + os.Setenv("PATH", fmt.Sprintf("%s%s%s", suite.goPath, string(os.PathListSeparator), os.Getenv("PATH"))) +} + +func (suite *InternalPluginTestSuit) TearDownSuite() { + os.RemoveAll(suite.goPath) + os.RemoveAll(suite.testDir) +} + +func TestInternalPluginSuite(t *testing.T) { + _, dir := TestCallee() + suite.Run(t, &InternalPluginTestSuit{ + goPath: GoPath(), + testDir: filepath.Join(CurProject().Target(), dir), + }) +} + +func (suite *InternalPluginTestSuit) TestNewPlugin() { tests := []struct { name string url string module string + logName string + binary string wantErr bool }{ - {"without version", - "github.com/golangci/golangci-lint/cmd/golangci-lint", - "github.com/golangci/golangci-lint", - false, + { + name: "without version", + url: "github.com/golangci/golangci-lint/cmd/golangci-lint", + module: "github.com/golangci/golangci-lint", + logName: "golangci-lint", + binary: "golangci-lint-v1.55.2", + wantErr: false, }, - {"laatest version", - "github.com/golangci/golangci-lint/cmd/golangci-lint@latest", - "github.com/golangci/golangci-lint", - false, + { + name: "laatest version", + url: "github.com/golangci/golangci-lint/cmd/golangci-lint@latest", + module: "github.com/golangci/golangci-lint", + logName: "golangci-lint", + binary: "golangci-lint-v1.55.2", + wantErr: false, }, - {"specific version", - "github.com/golangci/golangci-lint/cmd/golangci-lint@v1.1.1", - "github.com/golangci/golangci-lint", - false, + { + name: "specific version", + url: "github.com/golangci/golangci-lint/cmd/golangci-lint@v1.1.1", + module: "github.com/golangci/golangci-lint", + logName: "golangci-lint", + binary: "golangci-lint-v1.1.1", + wantErr: false, }, - {"has @ but no version", - "github.com/golangci/golangci-lint/cmd/golangci-lint@", - "github.com/golangci/golangci-lint", - true, + { + name: "has @ but no version", + url: "github.com/golangci/golangci-lint/cmd/golangci-lint@", + module: "github.com/golangci/golangci-lint", + logName: "", + binary: "-", + wantErr: true, }, - {"at the beginning of the url", - "@github.com/golangci/golangci-lint/cmd/golangci-lint", - "github.com/golangci/golangci-lint", - true, + { + name: "at the beginning of the url", + url: "@github.com/golangci/golangci-lint/cmd/golangci-lint", + module: "github.com/golangci/golangci-lint", + logName: "", + binary: "-", + wantErr: true, }, - {"multiple @", - "github.com/golangci/golangci-lint/cmd/golangci@-lint@v1", - "github.com/golangci/golangci-lint", - true, + { + name: "multiple @", + url: "github.com/golangci/golangci-lint/cmd/golangci@-lint@v1", + module: "github.com/golangci/golangci-lint", + logName: "", + binary: "-", + wantErr: true, }, - - // gotest.tools/gotestsum - {"gotestsum", - "gotest.tools/gotestsum", - "gotest.tools/gotestsum", - false, + { + name: "gotestsum", + url: "gotest.tools/gotestsum", + module: "gotest.tools/gotestsum", + logName: "gotestsum", + binary: "gotestsum-v1.11.0", + wantErr: false, }, } for _, test := range tests { - t.Run(test.name, func(t *testing.T) { + suite.T().Run(test.name, func(t *testing.T) { plugin, err := NewPlugin(test.url) + assert.Equal(t, plugin.logName(), test.logName) + assert.Equal(t, plugin.Binary(), test.binary) assert.True(t, test.wantErr == (err != nil)) if !test.wantErr { assert.Equal(t, test.module, plugin.module) @@ -67,11 +117,12 @@ func TestNewPlugin(t *testing.T) { } } -func TestUnmarshalJSON(t *testing.T) { +func (suite *InternalPluginTestSuit) TestUnmarshalJSON() { data, _ := os.ReadFile(filepath.Join(CurProject().Root(), "cmd", "resources", "config.json")) v := gjson.GetBytes(data, "plugins") var plugins []Plugin err := json.Unmarshal([]byte(v.Raw), &plugins) + t := suite.T() assert.NoError(t, err) assert.Equal(t, 2, len(plugins)) plugin, ok := lo.Find(plugins, func(plugin Plugin) bool { @@ -91,5 +142,30 @@ func TestUnmarshalJSON(t *testing.T) { assert.Equal(t, "gotestsum", plugin.Name()) assert.Equal(t, "gotest.tools/gotestsum", plugin.Module()) assert.Equal(t, "test", plugin.Alias) +} + +func (suite *InternalPluginTestSuit) TestInstallPlugin() { + t := suite.T() + plugin, err := NewPlugin("gotest.tools/gotestsum") + assert.NoError(t, err) + path, err := plugin.install() + assert.NoError(t, err) + assert.NoFileExistsf(t, path, "temporay go path should be deleted") + binary := filepath.Join(GoPath(), plugin.Binary()) + info1, err := os.Stat(binary) + assert.NoErrorf(t, err, "testsum should be installed successfully") + path, _ = plugin.install() + assert.NoFileExistsf(t, path, "temporay go path should be deleted") + info2, _ := os.Stat(binary) + assert.Equal(t, info1.ModTime(), info2.ModTime()) +} +func (suite *InternalPluginTestSuit) TestExecute() { + t := suite.T() + plugin, err := NewPlugin("golang.org/x/tools/cmd/guru@v0.17.0") + assert.NoError(t, err) + err = plugin.Execute() + assert.Error(t, err) + //'exit status 2' means the plugin is executed but no parameters, + assert.Equal(t, "exit status 2", err.Error()) } diff --git a/internal/project.go b/internal/project.go index 1670f3c..fc2b020 100644 --- a/internal/project.go +++ b/internal/project.go @@ -246,7 +246,7 @@ func (project *Project) SetupPlugin(plugin Plugin) { } _ = project.config().ReadInConfig() } - if err := plugin.install(); err != nil { + if _, err := plugin.install(); err != nil { color.Red("failed to install plugin %s: %s", plugin.name, err.Error()) } } @@ -283,7 +283,7 @@ func Version() string { }) { return fmt.Sprintf("%s@stage", tag) } - if output, err = exec.Command("git", "show", "--format=%cd", "--date=format:%Y/%m/%d", hash).CombinedOutput(); err == nil { + if output, err = exec.Command("git", "log", "--format=%ci -n 1", hash).CombinedOutput(); err == nil { return fmt.Sprintf("%s@%s", tag, strings.ReplaceAll(string(output), "\n", "")) } } @@ -298,7 +298,7 @@ func temporaryGoPath() string { func GoPath() string { if ok, method := TestCallee(); ok { dir := filepath.Join(os.TempDir(), method) - os.MkdirAll(dir, 0o700) //nolint + _ = os.MkdirAll(dir, os.ModePerm) //nolint return dir } return filepath.Join(os.Getenv("GOPATH"), "bin")