Signed-off-by: Tomasz Kopczynski <tomek@kopczynski.net.pl>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,134 @@ |
| 0 |
+package dockerfile |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "io/ioutil" |
|
| 4 |
+ "os" |
|
| 5 |
+ "strings" |
|
| 6 |
+ "testing" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/builder" |
|
| 9 |
+ "github.com/docker/docker/builder/dockerfile/parser" |
|
| 10 |
+ "github.com/docker/docker/pkg/archive" |
|
| 11 |
+ "github.com/docker/docker/pkg/reexec" |
|
| 12 |
+ "github.com/docker/engine-api/types" |
|
| 13 |
+ "github.com/docker/engine-api/types/container" |
|
| 14 |
+) |
|
| 15 |
+ |
|
| 16 |
+type dispatchTestCase struct {
|
|
| 17 |
+ name, dockerfile, expectedError string |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+func init() {
|
|
| 21 |
+ reexec.Init() |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func initDispatchTestCases() []dispatchTestCase {
|
|
| 25 |
+ dispatchTestCases := []dispatchTestCase{{
|
|
| 26 |
+ name: "copyEmptyWhitespace", |
|
| 27 |
+ dockerfile: `COPY |
|
| 28 |
+ quux \ |
|
| 29 |
+ bar`, |
|
| 30 |
+ expectedError: "COPY requires at least one argument", |
|
| 31 |
+ }, |
|
| 32 |
+ {
|
|
| 33 |
+ name: "ONBUILD forbidden FROM", |
|
| 34 |
+ dockerfile: "ONBUILD FROM scratch", |
|
| 35 |
+ expectedError: "FROM isn't allowed as an ONBUILD trigger", |
|
| 36 |
+ }, |
|
| 37 |
+ {
|
|
| 38 |
+ name: "ONBUILD forbidden MAINTAINER", |
|
| 39 |
+ dockerfile: "ONBUILD MAINTAINER docker.io", |
|
| 40 |
+ expectedError: "MAINTAINER isn't allowed as an ONBUILD trigger", |
|
| 41 |
+ }, |
|
| 42 |
+ {
|
|
| 43 |
+ name: "ARG two arguments", |
|
| 44 |
+ dockerfile: "ARG foo bar", |
|
| 45 |
+ expectedError: "ARG requires exactly one argument definition", |
|
| 46 |
+ }, |
|
| 47 |
+ {
|
|
| 48 |
+ name: "MAINTAINER unknown flag", |
|
| 49 |
+ dockerfile: "MAINTAINER --boo joe@example.com", |
|
| 50 |
+ expectedError: "Unknown flag: boo", |
|
| 51 |
+ }} |
|
| 52 |
+ |
|
| 53 |
+ return dispatchTestCases |
|
| 54 |
+} |
|
| 55 |
+ |
|
| 56 |
+func TestDispatch(t *testing.T) {
|
|
| 57 |
+ testCases := initDispatchTestCases() |
|
| 58 |
+ |
|
| 59 |
+ for _, testCase := range testCases {
|
|
| 60 |
+ executeTestCase(t, testCase) |
|
| 61 |
+ } |
|
| 62 |
+} |
|
| 63 |
+ |
|
| 64 |
+func executeTestCase(t *testing.T, testCase dispatchTestCase) {
|
|
| 65 |
+ contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test") |
|
| 66 |
+ defer cleanup() |
|
| 67 |
+ |
|
| 68 |
+ tarStream, err := archive.Tar(contextDir, archive.Uncompressed) |
|
| 69 |
+ |
|
| 70 |
+ if err != nil {
|
|
| 71 |
+ t.Fatalf("Error when creating tar stream: %s", err)
|
|
| 72 |
+ } |
|
| 73 |
+ |
|
| 74 |
+ defer func() {
|
|
| 75 |
+ if err = tarStream.Close(); err != nil {
|
|
| 76 |
+ t.Fatalf("Error when closing tar stream: %s", err)
|
|
| 77 |
+ } |
|
| 78 |
+ }() |
|
| 79 |
+ |
|
| 80 |
+ context, err := builder.MakeTarSumContext(tarStream) |
|
| 81 |
+ |
|
| 82 |
+ if err != nil {
|
|
| 83 |
+ t.Fatalf("Error when creating tar context: %s", err)
|
|
| 84 |
+ } |
|
| 85 |
+ |
|
| 86 |
+ defer func() {
|
|
| 87 |
+ if err = context.Close(); err != nil {
|
|
| 88 |
+ t.Fatalf("Error when closing tar context: %s", err)
|
|
| 89 |
+ } |
|
| 90 |
+ }() |
|
| 91 |
+ |
|
| 92 |
+ r := strings.NewReader(testCase.dockerfile) |
|
| 93 |
+ n, err := parser.Parse(r) |
|
| 94 |
+ |
|
| 95 |
+ if err != nil {
|
|
| 96 |
+ t.Fatalf("Error when parsing Dockerfile: %s", err)
|
|
| 97 |
+ } |
|
| 98 |
+ |
|
| 99 |
+ config := &container.Config{}
|
|
| 100 |
+ options := &types.ImageBuildOptions{}
|
|
| 101 |
+ |
|
| 102 |
+ b := &Builder{runConfig: config, options: options, Stdout: ioutil.Discard, context: context}
|
|
| 103 |
+ |
|
| 104 |
+ err = b.dispatch(0, n.Children[0]) |
|
| 105 |
+ |
|
| 106 |
+ if err == nil {
|
|
| 107 |
+ t.Fatalf("No error when executing test %s", testCase.name)
|
|
| 108 |
+ } |
|
| 109 |
+ |
|
| 110 |
+ if !strings.Contains(err.Error(), testCase.expectedError) {
|
|
| 111 |
+ t.Fatalf("Wrong error message. Should be \"%s\". Got \"%s\"", testCase.expectedError, err.Error())
|
|
| 112 |
+ } |
|
| 113 |
+ |
|
| 114 |
+} |
|
| 115 |
+ |
|
| 116 |
+// createTestTempDir creates a temporary directory for testing. |
|
| 117 |
+// It returns the created path and a cleanup function which is meant to be used as deferred call. |
|
| 118 |
+// When an error occurs, it terminates the test. |
|
| 119 |
+func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) {
|
|
| 120 |
+ path, err := ioutil.TempDir(dir, prefix) |
|
| 121 |
+ |
|
| 122 |
+ if err != nil {
|
|
| 123 |
+ t.Fatalf("Error when creating directory %s with prefix %s: %s", dir, prefix, err)
|
|
| 124 |
+ } |
|
| 125 |
+ |
|
| 126 |
+ return path, func() {
|
|
| 127 |
+ err = os.RemoveAll(path) |
|
| 128 |
+ |
|
| 129 |
+ if err != nil {
|
|
| 130 |
+ t.Fatalf("Error when removing directory %s: %s", path, err)
|
|
| 131 |
+ } |
|
| 132 |
+ } |
|
| 133 |
+} |
| ... | ... |
@@ -41,25 +41,6 @@ func (s *DockerSuite) TestBuildJSONEmptyRun(c *check.C) {
|
| 41 | 41 |
|
| 42 | 42 |
} |
| 43 | 43 |
|
| 44 |
-func (s *DockerSuite) TestBuildEmptyWhitespace(c *check.C) {
|
|
| 45 |
- name := "testbuildemptywhitespace" |
|
| 46 |
- |
|
| 47 |
- _, err := buildImage( |
|
| 48 |
- name, |
|
| 49 |
- ` |
|
| 50 |
- FROM busybox |
|
| 51 |
- COPY |
|
| 52 |
- quux \ |
|
| 53 |
- bar |
|
| 54 |
- `, |
|
| 55 |
- true) |
|
| 56 |
- |
|
| 57 |
- if err == nil {
|
|
| 58 |
- c.Fatal("no error when dealing with a COPY statement with no content on the same line")
|
|
| 59 |
- } |
|
| 60 |
- |
|
| 61 |
-} |
|
| 62 |
- |
|
| 63 | 44 |
func (s *DockerSuite) TestBuildShCmdJSONEntrypoint(c *check.C) {
|
| 64 | 45 |
name := "testbuildshcmdjsonentrypoint" |
| 65 | 46 |
|
| ... | ... |
@@ -3517,36 +3498,6 @@ func (s *DockerSuite) TestBuildOnBuildForbiddenChained(c *check.C) {
|
| 3517 | 3517 |
} |
| 3518 | 3518 |
} |
| 3519 | 3519 |
|
| 3520 |
-func (s *DockerSuite) TestBuildOnBuildForbiddenFrom(c *check.C) {
|
|
| 3521 |
- name := "testbuildonbuildforbiddenfrom" |
|
| 3522 |
- _, err := buildImage(name, |
|
| 3523 |
- `FROM busybox |
|
| 3524 |
- ONBUILD FROM scratch`, |
|
| 3525 |
- true) |
|
| 3526 |
- if err != nil {
|
|
| 3527 |
- if !strings.Contains(err.Error(), "FROM isn't allowed as an ONBUILD trigger") {
|
|
| 3528 |
- c.Fatalf("Wrong error %v, must be about FROM forbidden", err)
|
|
| 3529 |
- } |
|
| 3530 |
- } else {
|
|
| 3531 |
- c.Fatal("Error must not be nil")
|
|
| 3532 |
- } |
|
| 3533 |
-} |
|
| 3534 |
- |
|
| 3535 |
-func (s *DockerSuite) TestBuildOnBuildForbiddenMaintainer(c *check.C) {
|
|
| 3536 |
- name := "testbuildonbuildforbiddenmaintainer" |
|
| 3537 |
- _, err := buildImage(name, |
|
| 3538 |
- `FROM busybox |
|
| 3539 |
- ONBUILD MAINTAINER docker.io`, |
|
| 3540 |
- true) |
|
| 3541 |
- if err != nil {
|
|
| 3542 |
- if !strings.Contains(err.Error(), "MAINTAINER isn't allowed as an ONBUILD trigger") {
|
|
| 3543 |
- c.Fatalf("Wrong error %v, must be about MAINTAINER forbidden", err)
|
|
| 3544 |
- } |
|
| 3545 |
- } else {
|
|
| 3546 |
- c.Fatal("Error must not be nil")
|
|
| 3547 |
- } |
|
| 3548 |
-} |
|
| 3549 |
- |
|
| 3550 | 3520 |
// gh #2446 |
| 3551 | 3521 |
func (s *DockerSuite) TestBuildAddToSymlinkDest(c *check.C) {
|
| 3552 | 3522 |
testRequires(c, DaemonIsLinux) |
| ... | ... |
@@ -5914,22 +5865,6 @@ func (s *DockerSuite) TestBuildStartsFromOne(c *check.C) {
|
| 5914 | 5914 |
} |
| 5915 | 5915 |
} |
| 5916 | 5916 |
|
| 5917 |
-func (s *DockerSuite) TestBuildBadCmdFlag(c *check.C) {
|
|
| 5918 |
- name := "testbuildbadcmdflag" |
|
| 5919 |
- |
|
| 5920 |
- _, out, err := buildImageWithOut(name, ` |
|
| 5921 |
- FROM busybox |
|
| 5922 |
- MAINTAINER --boo joe@example.com`, false) |
|
| 5923 |
- if err == nil {
|
|
| 5924 |
- c.Fatal("Build should have failed")
|
|
| 5925 |
- } |
|
| 5926 |
- |
|
| 5927 |
- exp := "\nUnknown flag: boo\n" |
|
| 5928 |
- if !strings.Contains(out, exp) {
|
|
| 5929 |
- c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp)
|
|
| 5930 |
- } |
|
| 5931 |
-} |
|
| 5932 |
- |
|
| 5933 | 5917 |
func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) {
|
| 5934 | 5918 |
// Test to make sure the bad command is quoted with just "s and |
| 5935 | 5919 |
// not as a Go []string |
| ... | ... |
@@ -6584,23 +6519,6 @@ func (s *DockerSuite) TestBuildBuildTimeArgDefaultOverride(c *check.C) {
|
| 6584 | 6584 |
} |
| 6585 | 6585 |
} |
| 6586 | 6586 |
|
| 6587 |
-func (s *DockerSuite) TestBuildBuildTimeArgMultiArgsSameLine(c *check.C) {
|
|
| 6588 |
- testRequires(c, DaemonIsLinux) // Windows does not support ARG |
|
| 6589 |
- imgName := "bldargtest" |
|
| 6590 |
- envKey := "foo" |
|
| 6591 |
- envKey1 := "foo1" |
|
| 6592 |
- args := []string{}
|
|
| 6593 |
- dockerfile := fmt.Sprintf(`FROM busybox |
|
| 6594 |
- ARG %s %s`, envKey, envKey1) |
|
| 6595 |
- |
|
| 6596 |
- errStr := "ARG requires exactly one argument definition" |
|
| 6597 |
- if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err == nil {
|
|
| 6598 |
- c.Fatalf("build succeeded, expected to fail. Output: %v", out)
|
|
| 6599 |
- } else if !strings.Contains(out, errStr) {
|
|
| 6600 |
- c.Fatalf("Unexpected error. output: %q, expected error: %q", out, errStr)
|
|
| 6601 |
- } |
|
| 6602 |
-} |
|
| 6603 |
- |
|
| 6604 | 6587 |
func (s *DockerSuite) TestBuildBuildTimeArgUnconsumedArg(c *check.C) {
|
| 6605 | 6588 |
testRequires(c, DaemonIsLinux) // Windows does not support --build-arg |
| 6606 | 6589 |
imgName := "bldargtest" |