diff --git a/builder/dockerfile/evaluator_test.go b/builder/dockerfile/evaluator_test.go new file mode 100644 index 0000000000..c1c9425087 --- /dev/null +++ b/builder/dockerfile/evaluator_test.go @@ -0,0 +1,134 @@ +package dockerfile + +import ( + "io/ioutil" + "os" + "strings" + "testing" + + "github.com/docker/docker/builder" + "github.com/docker/docker/builder/dockerfile/parser" + "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/pkg/reexec" + "github.com/docker/engine-api/types" + "github.com/docker/engine-api/types/container" +) + +type dispatchTestCase struct { + name, dockerfile, expectedError string +} + +func init() { + reexec.Init() +} + +func initDispatchTestCases() []dispatchTestCase { + dispatchTestCases := []dispatchTestCase{{ + name: "copyEmptyWhitespace", + dockerfile: `COPY + quux \ + bar`, + expectedError: "COPY requires at least one argument", + }, + { + name: "ONBUILD forbidden FROM", + dockerfile: "ONBUILD FROM scratch", + expectedError: "FROM isn't allowed as an ONBUILD trigger", + }, + { + name: "ONBUILD forbidden MAINTAINER", + dockerfile: "ONBUILD MAINTAINER docker.io", + expectedError: "MAINTAINER isn't allowed as an ONBUILD trigger", + }, + { + name: "ARG two arguments", + dockerfile: "ARG foo bar", + expectedError: "ARG requires exactly one argument definition", + }, + { + name: "MAINTAINER unknown flag", + dockerfile: "MAINTAINER --boo joe@example.com", + expectedError: "Unknown flag: boo", + }} + + return dispatchTestCases +} + +func TestDispatch(t *testing.T) { + testCases := initDispatchTestCases() + + for _, testCase := range testCases { + executeTestCase(t, testCase) + } +} + +func executeTestCase(t *testing.T, testCase dispatchTestCase) { + contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test") + defer cleanup() + + tarStream, err := archive.Tar(contextDir, archive.Uncompressed) + + if err != nil { + t.Fatalf("Error when creating tar stream: %s", err) + } + + defer func() { + if err = tarStream.Close(); err != nil { + t.Fatalf("Error when closing tar stream: %s", err) + } + }() + + context, err := builder.MakeTarSumContext(tarStream) + + if err != nil { + t.Fatalf("Error when creating tar context: %s", err) + } + + defer func() { + if err = context.Close(); err != nil { + t.Fatalf("Error when closing tar context: %s", err) + } + }() + + r := strings.NewReader(testCase.dockerfile) + n, err := parser.Parse(r) + + if err != nil { + t.Fatalf("Error when parsing Dockerfile: %s", err) + } + + config := &container.Config{} + options := &types.ImageBuildOptions{} + + b := &Builder{runConfig: config, options: options, Stdout: ioutil.Discard, context: context} + + err = b.dispatch(0, n.Children[0]) + + if err == nil { + t.Fatalf("No error when executing test %s", testCase.name) + } + + if !strings.Contains(err.Error(), testCase.expectedError) { + t.Fatalf("Wrong error message. Should be \"%s\". Got \"%s\"", testCase.expectedError, err.Error()) + } + +} + +// createTestTempDir creates a temporary directory for testing. +// It returns the created path and a cleanup function which is meant to be used as deferred call. +// When an error occurs, it terminates the test. +func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) { + path, err := ioutil.TempDir(dir, prefix) + + if err != nil { + t.Fatalf("Error when creating directory %s with prefix %s: %s", dir, prefix, err) + } + + return path, func() { + err = os.RemoveAll(path) + + if err != nil { + t.Fatalf("Error when removing directory %s: %s", path, err) + } + } +} diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 51ba75d3cf..9d1834256a 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -41,25 +41,6 @@ func (s *DockerSuite) TestBuildJSONEmptyRun(c *check.C) { } -func (s *DockerSuite) TestBuildEmptyWhitespace(c *check.C) { - name := "testbuildemptywhitespace" - - _, err := buildImage( - name, - ` - FROM busybox - COPY - quux \ - bar - `, - true) - - if err == nil { - c.Fatal("no error when dealing with a COPY statement with no content on the same line") - } - -} - func (s *DockerSuite) TestBuildShCmdJSONEntrypoint(c *check.C) { name := "testbuildshcmdjsonentrypoint" @@ -3517,36 +3498,6 @@ func (s *DockerSuite) TestBuildOnBuildForbiddenChained(c *check.C) { } } -func (s *DockerSuite) TestBuildOnBuildForbiddenFrom(c *check.C) { - name := "testbuildonbuildforbiddenfrom" - _, err := buildImage(name, - `FROM busybox - ONBUILD FROM scratch`, - true) - if err != nil { - if !strings.Contains(err.Error(), "FROM isn't allowed as an ONBUILD trigger") { - c.Fatalf("Wrong error %v, must be about FROM forbidden", err) - } - } else { - c.Fatal("Error must not be nil") - } -} - -func (s *DockerSuite) TestBuildOnBuildForbiddenMaintainer(c *check.C) { - name := "testbuildonbuildforbiddenmaintainer" - _, err := buildImage(name, - `FROM busybox - ONBUILD MAINTAINER docker.io`, - true) - if err != nil { - if !strings.Contains(err.Error(), "MAINTAINER isn't allowed as an ONBUILD trigger") { - c.Fatalf("Wrong error %v, must be about MAINTAINER forbidden", err) - } - } else { - c.Fatal("Error must not be nil") - } -} - // gh #2446 func (s *DockerSuite) TestBuildAddToSymlinkDest(c *check.C) { testRequires(c, DaemonIsLinux) @@ -5914,22 +5865,6 @@ func (s *DockerSuite) TestBuildStartsFromOne(c *check.C) { } } -func (s *DockerSuite) TestBuildBadCmdFlag(c *check.C) { - name := "testbuildbadcmdflag" - - _, out, err := buildImageWithOut(name, ` - FROM busybox - MAINTAINER --boo joe@example.com`, false) - if err == nil { - c.Fatal("Build should have failed") - } - - exp := "\nUnknown flag: boo\n" - if !strings.Contains(out, exp) { - c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp) - } -} - func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) { // Test to make sure the bad command is quoted with just "s and // not as a Go []string @@ -6584,23 +6519,6 @@ func (s *DockerSuite) TestBuildBuildTimeArgDefaultOverride(c *check.C) { } } -func (s *DockerSuite) TestBuildBuildTimeArgMultiArgsSameLine(c *check.C) { - testRequires(c, DaemonIsLinux) // Windows does not support ARG - imgName := "bldargtest" - envKey := "foo" - envKey1 := "foo1" - args := []string{} - dockerfile := fmt.Sprintf(`FROM busybox - ARG %s %s`, envKey, envKey1) - - errStr := "ARG requires exactly one argument definition" - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err == nil { - c.Fatalf("build succeeded, expected to fail. Output: %v", out) - } else if !strings.Contains(out, errStr) { - c.Fatalf("Unexpected error. output: %q, expected error: %q", out, errStr) - } -} - func (s *DockerSuite) TestBuildBuildTimeArgUnconsumedArg(c *check.C) { testRequires(c, DaemonIsLinux) // Windows does not support --build-arg imgName := "bldargtest"