Skip to content

Commit

Permalink
For unit test purposes, the function was split. Then, unit tests were…
Browse files Browse the repository at this point in the history
… added.
  • Loading branch information
nao1215 committed Sep 17, 2022
1 parent 126b067 commit b214c5f
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 3 deletions.
11 changes: 9 additions & 2 deletions cmd/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,19 @@ func remove(cmd *cobra.Command, args []string) int {
return 1
}

return removeLoop(gobin, force, args)
}

// GOOS is wrapper for runtime.GOOS variable. It's for unit test.
var GOOS = runtime.GOOS

func removeLoop(gobin string, force bool, target []string) int {
result := 0
for _, v := range args {
for _, v := range target {
// In Windows, $GOEXE is set to the ".exe" extension.
// The user-specified command name (arguments) may not have an extension.
execSuffix := os.Getenv("GOEXE")
if runtime.GOOS == "windows" && !strings.HasSuffix(v, execSuffix) {
if GOOS == "windows" && !strings.HasSuffix(v, execSuffix) {
v += execSuffix
}

Expand Down
193 changes: 192 additions & 1 deletion cmd/remove_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package cmd

import (
"bytes"
"go/build"
"io"
"os"
"runtime"
"strings"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/nao1215/gup/internal/file"
"github.com/nao1215/gup/internal/print"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -38,7 +41,7 @@ func Test_remove(t *testing.T) {
},
},
{
name: "GOBIN does not exist",
name: "delete taget binary does not exist",
args: args{
cmd: &cobra.Command{},
args: []string{"test"},
Expand Down Expand Up @@ -94,3 +97,191 @@ func Test_remove(t *testing.T) {
})
}
}

func Test_remove_gobin_is_empty(t *testing.T) {
t.Run("GOPATH and GOBIN", func(t *testing.T) {
oldGoBin := os.Getenv("GOBIN")
if err := os.Setenv("GOBIN", ""); err != nil {
t.Fatal(err)
}
defer func() {
if err := os.Setenv("GOBIN", oldGoBin); err != nil {
t.Fatal(err)
}
}()

if err := os.Setenv("GOPATH", ""); err != nil {
t.Fatal(err)
}
defer func() {
if err := os.Setenv("GOPATH", oldGoBin); err != nil {
t.Fatal(err)
}
}()

oldBuildGopath := build.Default.GOPATH
build.Default.GOPATH = ""
defer func() { build.Default.GOPATH = oldBuildGopath }()

orgStdout := print.Stdout
orgStderr := print.Stderr
pr, pw, err := os.Pipe()
if err != nil {
t.Fatal(err)
}
print.Stdout = pw
print.Stderr = pw

cmd := &cobra.Command{}
cmd.Flags().BoolP("force", "f", false, "Forcibly remove the file")
if got := remove(cmd, []string{"dummy"}); got != 1 {
t.Errorf("remove() = %v, want %v", got, 1)
}
pw.Close()
print.Stdout = orgStdout
print.Stderr = orgStderr

buf := bytes.Buffer{}
_, err = io.Copy(&buf, pr)
if err != nil {
t.Error(err)
}
defer pr.Close()
got := strings.Split(buf.String(), "\n")

if diff := cmp.Diff([]string{"gup:ERROR: $GOPATH is not set", ""}, got); diff != "" {
t.Errorf("value is mismatch (-want +got):\n%s", diff)
}
})
}

func Test_removeLoop(t *testing.T) {
type args struct {
gobin string
force bool
target []string
}
tests := []struct {
name string
args args
input string
want int
}{
{
name: "windows environment and suffix is mismatch",
args: args{
gobin: "./testdata/delete",
force: false,
target: []string{"posixer"},
},
input: "y",
want: 1,
},
{
name: "interactive question: input 'y'",
args: args{
gobin: "./testdata/delete",
force: false,
target: []string{"posixer"},
},
input: "y",
want: 0,
},
{
name: "delete cancel",
args: args{
gobin: "./testdata/delete",
force: false,
target: []string{"posixer"},
},
input: "n",
want: 0,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := os.MkdirAll("./testdata/delete", 0755); err != nil {
t.Fatal(err)
}

newFile, err := os.Create("./testdata/delete/posixer")
if err != nil {
t.Fatal(err)
}

oldFile, err := os.Open("./testdata/check_success/posixer")
if err != nil {
t.Fatal(err)
}

_, err = io.Copy(newFile, oldFile)
if err != nil {
t.Fatal(err)
}
defer func() {
os.Remove("./testdata/delete/posixer")
}()

funcDefer, err := mockStdin(t, tt.input)
if err != nil {
t.Fatal(err)
}
defer funcDefer()

if tt.name == "windows environment and suffix is mismatch" {
GOOS = "windows"
defer func() { GOOS = runtime.GOOS }()

if err := os.Setenv("GOEXE", ".exe"); err != nil {
t.Fatal(err)
}
defer func() {
if err := os.Setenv("GOEXE", ""); err != nil {
t.Fatal(err)
}
}()
}

if got := removeLoop(tt.args.gobin, tt.args.force, tt.args.target); got != tt.want {
t.Errorf("removeLoop() = %v, want %v", got, tt.want)
}

if tt.name == "delete cancel" && !file.IsFile("./testdata/delete/posixer") {
t.Errorf("input no, however posixer command is deleted")
}
})
}
}

// mockStdin is a helper function that lets the test pretend dummyInput as os.Stdin.
// It will return a function for `defer` to clean up after the test.
func mockStdin(t *testing.T, dummyInput string) (funcDefer func(), err error) {
t.Helper()

oldOsStdin := os.Stdin
tmpFile, err := os.CreateTemp(t.TempDir(), "morrigan_")

if err != nil {
return nil, err
}

content := []byte(dummyInput)

if _, err := tmpFile.Write(content); err != nil {
return nil, err
}

if _, err := tmpFile.Seek(0, 0); err != nil {
return nil, err
}

// Set stdin to the temp file
os.Stdin = tmpFile

return func() {
// clean up
os.Stdin = oldOsStdin
os.Remove(tmpFile.Name())
}, nil
}

0 comments on commit b214c5f

Please sign in to comment.