diff --git a/go.mod b/go.mod index 24feb09..a67ba6c 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,9 @@ go 1.16 require ( github.com/AlecAivazis/survey/v2 v2.2.12 + github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 github.com/go-test/deep v1.0.7 + github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 github.com/mitchellh/go-homedir v1.1.0 github.com/spf13/cobra v1.1.3 github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index ca68029..8b6bfe7 100644 --- a/go.sum +++ b/go.sum @@ -178,7 +178,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/src/cmd/remove/remove.go b/src/cmd/remove/remove.go index a8c807f..2b5aa1d 100644 --- a/src/cmd/remove/remove.go +++ b/src/cmd/remove/remove.go @@ -59,10 +59,5 @@ func run(ctx context.Context, name string, options options) error { container := yey.ContainerName(contexts.Path, context) - var removeOptions []docker.RemoveOption - if options.force { - removeOptions = append(removeOptions, docker.ForceRemove) - } - - return docker.Remove(ctx, container, removeOptions...) + return docker.Remove(ctx, container, docker.WithForceRemove(options.force)) } diff --git a/src/cmd/tidy/tidy.go b/src/cmd/tidy/tidy.go index 6162ac3..7d5758b 100644 --- a/src/cmd/tidy/tidy.go +++ b/src/cmd/tidy/tidy.go @@ -65,10 +65,5 @@ func run(ctx context.Context, options options) error { unreferencedContainers = append(unreferencedContainers, container) } - var removeOptions []docker.RemoveOption - if options.force { - removeOptions = append(removeOptions, docker.ForceRemove) - } - - return docker.RemoveMany(ctx, unreferencedContainers, removeOptions...) + return docker.RemoveMany(ctx, unreferencedContainers, docker.WithForceRemove(options.force)) } diff --git a/src/fixture_test.go b/src/fixture_test.go new file mode 100644 index 0000000..c05af28 --- /dev/null +++ b/src/fixture_test.go @@ -0,0 +1,75 @@ +package main + +import ( + "bytes" + "context" + "io" + "os" + "os/exec" + "testing" + + "github.com/Netflix/go-expect" + "github.com/hinshun/vt10x" + "github.com/stretchr/testify/require" +) + +var rootDir = "_test_assets_" + +type ConsoleTester struct { + c *expect.Console + r *require.Assertions +} + +func (ct ConsoleTester) ExpectString(value string) { + _, err := ct.c.ExpectString(value) + ct.r.NoError(err) +} + +func (ct ConsoleTester) ExpectEOF() { + _, err := ct.c.ExpectEOF() + ct.r.NoError(err) +} + +func (ct ConsoleTester) SendLine(value string) { + _, err := ct.c.SendLine(value) + ct.r.NoError(err) +} + +func ConsoleTest(t *testing.T, ctx context.Context, cmdArgs []string, test func(ct ConsoleTester)) ([]byte, error) { + t.Helper() + r := require.New(t) + + buf := new(bytes.Buffer) + console, _, err := vt10x.NewVT10XConsole(expect.WithStdout(buf)) + require.NoError(t, err) + ct := ConsoleTester{console, r} + + cmd := exec.CommandContext(ctx, cmdArgs[0], cmdArgs[1:]...) + cmd.Dir = rootDir + + pr, pw := io.Pipe() + tty := console.Tty() + + go func() { + r := io.TeeReader(pr, os.Stdout) + io.Copy(tty, r) + }() + + cmd.Stdout, cmd.Stderr, cmd.Stdin = pw, pw, console.Tty() + + donec := make(chan struct{}) + go func() { + defer close(donec) + if test != nil { + test(ct) + } + }() + + err = cmd.Run() + + // Close the slave end of the tty, and read the remaining bytes from the master end. + console.Tty().Close() + <-donec + + return buf.Bytes(), err +} diff --git a/src/internal/docker/cli.go b/src/internal/docker/cli.go index 7110ca1..92cdc5a 100644 --- a/src/internal/docker/cli.go +++ b/src/internal/docker/cli.go @@ -40,7 +40,11 @@ type removeOption struct { type RemoveOption func(ro *removeOption) -var ForceRemove RemoveOption = func(ro *removeOption) { ro.force = true } +func WithForceRemove(value bool) RemoveOption { + return func(ro *removeOption) { + ro.force = value + } +} func Remove(ctx context.Context, containerName string, options ...RemoveOption) error { status, err := getContainerStatus(ctx, containerName)