Browse code

Reimplementing builder integration tests as unit tests

Signed-off-by: Tomasz Kopczynski <tomek@kopczynski.net.pl>

Tomasz Kopczynski authored on 2016/05/09 02:22:06
Showing 2 changed files
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"