Skip to content

Commit

Permalink
Merge pull request #183 from tonistiigi/dockerfile-tests
Browse files Browse the repository at this point in the history
frontend: add some dockerfile integration tests
  • Loading branch information
AkihiroSuda authored Dec 2, 2017
2 parents 31f3163 + 97b773a commit 9653c60
Show file tree
Hide file tree
Showing 38 changed files with 3,479 additions and 1 deletion.
124 changes: 124 additions & 0 deletions cmd/buildctl/build_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package main

import (
"bytes"
"context"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/containerd/containerd"
"github.com/containerd/containerd/fs/fstest"
"github.com/containerd/containerd/namespaces"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/util/testutil/integration"
"github.com/stretchr/testify/require"
)

func testBuildWithLocalFiles(t *testing.T, sb integration.Sandbox) {
t.Parallel()
dir, err := tmpdir(
fstest.CreateFile("foo", []byte("bar"), 0600),
)
require.NoError(t, err)
defer os.RemoveAll(dir)

st := llb.Image("busybox").
Run(llb.Shlex("sh -c 'echo -n bar > foo2'")).
Run(llb.Shlex("cmp -s /mnt/foo foo2"))

st.AddMount("/mnt", llb.Local("src"), llb.Readonly)

rdr, err := marshal(st.Root())
require.NoError(t, err)

cmd := sb.Cmd(fmt.Sprintf("build --no-progress --local src=%s", dir))
cmd.Stdin = rdr

err = cmd.Run()
require.NoError(t, err)
}

func testBuildLocalExporter(t *testing.T, sb integration.Sandbox) {
t.Parallel()
st := llb.Image("busybox").
Run(llb.Shlex("sh -c 'echo -n bar > /out/foo'"))

out := st.AddMount("/out", llb.Scratch())

rdr, err := marshal(out)
require.NoError(t, err)

tmpdir, err := ioutil.TempDir("", "buildkit-buildctl")
require.NoError(t, err)
defer os.RemoveAll(tmpdir)

cmd := sb.Cmd(fmt.Sprintf("build --no-progress --exporter=local --exporter-opt output=%s", tmpdir))
cmd.Stdin = rdr
err = cmd.Run()

require.NoError(t, err)

dt, err := ioutil.ReadFile(filepath.Join(tmpdir, "foo"))
require.NoError(t, err)
require.Equal(t, string(dt), "bar")
}

func testBuildContainerdExporter(t *testing.T, sb integration.Sandbox) {
t.Parallel()

var cdAddress string
if cd, ok := sb.(interface {
ContainerdAddress() string
}); !ok {
t.Skip("only for containerd worker")
} else {
cdAddress = cd.ContainerdAddress()
}

st := llb.Image("busybox").
Run(llb.Shlex("sh -c 'echo -n bar > /foo'"))

rdr, err := marshal(st.Root())
require.NoError(t, err)

cmd := sb.Cmd("build --no-progress --exporter=image --exporter-opt name=example.com/moby/imageexporter:test")
cmd.Stdin = rdr
err = cmd.Run()
require.NoError(t, err)

client, err := containerd.New(cdAddress)
require.NoError(t, err)
defer client.Close()

ctx := namespaces.WithNamespace(context.Background(), "buildkit")

_, err = client.ImageService().Get(ctx, "example.com/moby/imageexporter:test")
require.NoError(t, err)
}

func marshal(st llb.State) (io.Reader, error) {
def, err := st.Marshal()
if err != nil {
return nil, err
}
dt, err := def.ToPB().Marshal()
if err != nil {
return nil, err
}
return bytes.NewBuffer(dt), nil
}

func tmpdir(appliers ...fstest.Applier) (string, error) {
tmpdir, err := ioutil.TempDir("", "buildkit-buildctl")
if err != nil {
return "", err
}
if err := fstest.Apply(appliers...).Apply(tmpdir); err != nil {
return "", err
}
return tmpdir, nil
}
3 changes: 3 additions & 0 deletions cmd/buildctl/buildctl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,8 @@ import (
func TestCLIIntegration(t *testing.T) {
integration.Run(t, []integration.Test{
testDiskUsage,
testBuildWithLocalFiles,
testBuildLocalExporter,
testBuildContainerdExporter,
})
}
129 changes: 129 additions & 0 deletions frontend/dockerfile/dockerfile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package dockerfile

import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/containerd/containerd/fs/fstest"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/util/testutil/integration"
"github.com/stretchr/testify/require"
)

func TestIntegration(t *testing.T) {
integration.Run(t, []integration.Test{
testDockerfileDirs,
testDockerfileInvalidCommand,
})
}

func testDockerfileDirs(t *testing.T, sb integration.Sandbox) {
t.Parallel()
dockerfile := []byte(`
FROM busybox
COPY foo /foo2
COPY foo /
RUN echo -n bar > foo3
RUN test -f foo
RUN cmp -s foo foo2
RUN cmp -s foo foo3
`)

dir, err := tmpdir(
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("bar"), 0600),
)
require.NoError(t, err)
defer os.RemoveAll(dir)

args, trace := dfCmdArgs(dir, dir)
defer os.RemoveAll(trace)

cmd := sb.Cmd(args)
require.NoError(t, cmd.Run())

_, err = os.Stat(trace)
require.NoError(t, err)

// relative urls
args, trace = dfCmdArgs(".", ".")
defer os.RemoveAll(trace)

cmd = sb.Cmd(args)
cmd.Dir = dir
require.NoError(t, cmd.Run())

_, err = os.Stat(trace)
require.NoError(t, err)

// different context and dockerfile directories
dir1, err := tmpdir(
fstest.CreateFile("Dockerfile", dockerfile, 0600),
)
require.NoError(t, err)
defer os.RemoveAll(dir1)

dir2, err := tmpdir(
fstest.CreateFile("foo", []byte("bar"), 0600),
)
require.NoError(t, err)
defer os.RemoveAll(dir2)

args, trace = dfCmdArgs(dir2, dir1)
defer os.RemoveAll(trace)

cmd = sb.Cmd(args)
cmd.Dir = dir
require.NoError(t, cmd.Run())

_, err = os.Stat(trace)
require.NoError(t, err)

// TODO: test trace file output, cache hits, logs etc.
// TODO: output metadata about original dockerfile command in trace
}

func testDockerfileInvalidCommand(t *testing.T, sb integration.Sandbox) {
t.Parallel()
dockerfile := []byte(`
FROM busybox
RUN invalidcmd
`)

dir, err := tmpdir(
fstest.CreateFile("Dockerfile", dockerfile, 0600),
)
require.NoError(t, err)
defer os.RemoveAll(dir)

args, trace := dfCmdArgs(dir, dir)
defer os.RemoveAll(trace)

cmd := sb.Cmd(args)
stdout := new(bytes.Buffer)
cmd.Stderr = stdout
err = cmd.Run()
require.Error(t, err)
require.Contains(t, stdout.String(), "/bin/sh -c invalidcmd")
require.Contains(t, stdout.String(), "worker failed running")
}

func tmpdir(appliers ...fstest.Applier) (string, error) {
tmpdir, err := ioutil.TempDir("", "buildkit-dockerfile")
if err != nil {
return "", err
}
if err := fstest.Apply(appliers...).Apply(tmpdir); err != nil {
return "", err
}
return tmpdir, nil
}

func dfCmdArgs(ctx, dockerfile string) (string, string) {
traceFile := filepath.Join(os.TempDir(), "trace"+identity.NewID())
return fmt.Sprintf("build --no-progress --frontend dockerfile.v0 --local context=%s --local dockerfile=%s --trace=%s", ctx, dockerfile, traceFile), traceFile
}
11 changes: 10 additions & 1 deletion util/testutil/integration/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,14 @@ func (c *containerd) New() (sb Sandbox, cl func() error, err error) {
}
deferF.append(stop)

return &sandbox{address: builddSock, logs: logs}, cl, nil
return &cdsandbox{address: address, sandbox: sandbox{address: builddSock, logs: logs}}, cl, nil
}

type cdsandbox struct {
sandbox
address string
}

func (s *cdsandbox) ContainerdAddress() string {
return s.address
}
7 changes: 7 additions & 0 deletions util/testutil/integration/standalone.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"runtime"
"testing"
"time"

"github.com/google/shlex"
)

func init() {
Expand Down Expand Up @@ -59,6 +61,11 @@ func (sb *sandbox) PrintLogs(t *testing.T) {
}

func (sb *sandbox) Cmd(args ...string) *exec.Cmd {
if len(args) == 1 {
if split, err := shlex.Split(args[0]); err == nil {
args = split
}
}
cmd := exec.Command("buildctl", args...)
cmd.Env = append(cmd.Env, os.Environ()...)
cmd.Env = append(cmd.Env, "BUILDKIT_HOST="+sb.Address())
Expand Down
53 changes: 53 additions & 0 deletions vendor/github.com/containerd/containerd/fs/fstest/compare.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 9653c60

Please sign in to comment.