From 62db51d9799adf9643d99ab0f7cb9537e3295829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Mon, 24 May 2021 00:11:58 +0300 Subject: [PATCH] wip tests --- internal/cmd/cmd.go | 6 +-- internal/cmdrootfs/BUILD | 7 ++- internal/cmdrootfs/cmdrootfs.go | 44 ++++++++---------- internal/cmdrootfs/cmdrootfs_test.go | 69 +++++++++++++++++++++++++++- 4 files changed, 95 insertions(+), 31 deletions(-) diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 7d25064..874bfc6 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -7,9 +7,9 @@ import ( // BaseCommand provides common fields to all commands. type BaseCommand struct { - Stdin io.ReadCloser - Stdout io.WriteCloser - Stderr io.WriteCloser + Stdin io.Reader + Stdout io.Writer + Stderr io.Writer } // Init initializes BaseCommand with default arguments diff --git a/internal/cmdrootfs/BUILD b/internal/cmdrootfs/BUILD index d3637c5..87c0892 100644 --- a/internal/cmdrootfs/BUILD +++ b/internal/cmdrootfs/BUILD @@ -9,7 +9,6 @@ go_library( "//src/undocker/internal/cmd:go_default_library", "//src/undocker/rootfs:go_default_library", "@com_github_jessevdk_go_flags//:go_default_library", - "@com_github_ulikunitz_xz//:go_default_library", "@org_uber_go_multierr//:go_default_library", ], ) @@ -18,4 +17,10 @@ go_test( name = "go_default_test", srcs = ["cmdrootfs_test.go"], embed = [":go_default_library"], + deps = [ + "//src/undocker/internal/cmd:go_default_library", + "@com_github_jessevdk_go_flags//:go_default_library", + "@com_github_stretchr_testify//assert:go_default_library", + "@com_github_stretchr_testify//require:go_default_library", + ], ) diff --git a/internal/cmdrootfs/cmdrootfs.go b/internal/cmdrootfs/cmdrootfs.go index 04c27d4..15b2a7f 100644 --- a/internal/cmdrootfs/cmdrootfs.go +++ b/internal/cmdrootfs/cmdrootfs.go @@ -2,29 +2,31 @@ package cmdrootfs import ( "errors" + "fmt" "io" "os" goflags "github.com/jessevdk/go-flags" "github.com/motiejus/code/undocker/internal/cmd" "github.com/motiejus/code/undocker/rootfs" - "github.com/ulikunitz/xz" "go.uber.org/multierr" ) -// Command is "rootfs" command -type Command struct { - cmd.BaseCommand +type ( + rootfsFactory func(io.ReadSeeker) io.WriterTo - PositionalArgs struct { - Infile goflags.Filename `long:"infile" description:"Input tarball"` - Outfile string `long:"outfile" description:"Output path, stdout is '-'"` - } `positional-args:"yes" required:"yes"` + // Command is "rootfs" command + Command struct { + cmd.BaseCommand - Xz bool `short:"J" long:"xz" description:"create XZ archive"` + PositionalArgs struct { + Infile goflags.Filename `long:"infile" description:"Input tarball"` + Outfile string `long:"outfile" description:"Output path, stdout is '-'"` + } `positional-args:"yes" required:"yes"` - rootfsNew func(io.ReadSeeker) io.WriterTo -} + rootfsNew rootfsFactory + } +) // Execute executes rootfs Command func (c *Command) Execute(args []string) (err error) { @@ -42,25 +44,15 @@ func (c *Command) Execute(args []string) (err error) { defer func() { err = multierr.Append(err, rd.Close()) }() var out io.Writer - var outf *os.File if fname := string(c.PositionalArgs.Outfile); fname == "-" { - outf = os.Stdout + out = c.Stdout } else { - outf, err = os.Create(fname) + outf, err := os.Create(fname) if err != nil { - return err + return fmt.Errorf("create: %w", err) } - } - out = outf - defer func() { err = multierr.Append(err, outf.Close()) }() - - if c.Xz { - outz, err := xz.NewWriter(out) - if err != nil { - return err - } - defer func() { err = multierr.Append(err, outz.Close()) }() - out = outz + defer func() { err = multierr.Append(err, outf.Close()) }() + out = outf } if _, err := c.rootfsNew(rd).WriteTo(out); err != nil { diff --git a/internal/cmdrootfs/cmdrootfs_test.go b/internal/cmdrootfs/cmdrootfs_test.go index 903be9f..e008642 100644 --- a/internal/cmdrootfs/cmdrootfs_test.go +++ b/internal/cmdrootfs/cmdrootfs_test.go @@ -1,6 +1,73 @@ package cmdrootfs -import "testing" +import ( + "bytes" + "io" + "path/filepath" + "testing" + + goflags "github.com/jessevdk/go-flags" + "github.com/motiejus/code/undocker/internal/cmd" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) func TestExecute(t *testing.T) { + dir := t.TempDir() + + tests := []struct { + name string + in []byte + infile string + outfile string + want []byte + wantErr string + }{ + { + name: "ok passthrough via stdout", + in: []byte("foo"), + outfile: "-", + want: []byte("foo"), + }, + { + name: "ok passthrough via file", + in: []byte("foo"), + outfile: filepath.Join(dir, "t1.txt"), + want: []byte("foo"), + }, + { + name: "infile does not exist", + infile: filepath.Join(dir, "does", "not", "exist"), + wantErr: "open <...>/does/not/exist: enoent", + }, + { + name: "outpath dir not writable", + outfile: filepath.Join(dir, "does", "not", "exist"), + wantErr: "create: stat <...>/does/not/exist: enoent", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var stdout bytes.Buffer + c := &Command{BaseCommand: cmd.BaseCommand{Stdout: &stdout}} + c.PositionalArgs.Infile = goflags.Filename(tt.infile) + c.PositionalArgs.Outfile = tt.outfile + c.rootfsNew = func(r io.ReadSeeker) io.WriterTo { + return &passthrough{r} + } + + err := c.Execute(nil) + if tt.wantErr != "" { + assert.EqualError(t, err, tt.wantErr) + return + } + require.NoError(t, err) + assert.Equal(t, tt.want, stdout.Bytes()) + }) + } } + +type passthrough struct{ r io.Reader } + +func (p *passthrough) WriteTo(w io.Writer) (int64, error) { return io.Copy(w, p.r) }