Browse code

Introduce `test-integration` target (and deprecate/freeze `test-integration-cli`)

This adds a new package `integration` where `engine` integration tests
should live. Those integration tests should not depends on any `cli`
components (except from the `dockerd` daemon for now — to actually
start a daemon).

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Vincent Demeester authored on 2017/05/24 05:32:34
Showing 8 changed files
... ...
@@ -160,6 +160,10 @@ it! Take a look at existing tests for inspiration. [Run the full test
160 160
 suite](https://docs.docker.com/opensource/project/test-and-docs/) on your branch before
161 161
 submitting a pull request.
162 162
 
163
+If your changes need integration tests, write them against the API. The `cli`
164
+integration tests are slowly either migrated to API tests or moved away as unit
165
+tests in `docker/cli` and end-to-end tests for docker.
166
+
163 167
 Update the documentation when creating or modifying features. Test your
164 168
 documentation changes for clarity, concision, and correctness, as well as a
165 169
 clean documentation build. See our contributors guide for [our style
... ...
@@ -154,8 +154,11 @@ test: build ## run the unit, integration and docker-py tests
154 154
 test-docker-py: build ## run the docker-py tests
155 155
 	$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary test-docker-py
156 156
 
157
-test-integration-cli: build ## run the integration tests
158
-	$(DOCKER_RUN_DOCKER) hack/make.sh build-integration-test-binary dynbinary test-integration-cli
157
+test-integration-cli: build ## (DEPRECATED) use test-integration
158
+	$(DOCKER_RUN_DOCKER) hack/make.sh build-integration-test-cli-binary dynbinary test-integration
159
+
160
+test-integration: build ## run the integration tests
161
+	$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary test-integration
159 162
 
160 163
 test-unit: build ## run the unit tests
161 164
 	$(DOCKER_RUN_DOCKER) hack/make.sh test-unit
... ...
@@ -60,6 +60,7 @@ DEFAULT_BUNDLES=(
60 60
 	dynbinary
61 61
 
62 62
 	test-unit
63
+	test-integration
63 64
 	test-integration-cli
64 65
 	test-docker-py
65 66
 
... ...
@@ -7,6 +7,25 @@ bundle_test_integration_cli() {
7 7
 	go_test_dir integration-cli $DOCKER_INTEGRATION_TESTS_VERIFIED
8 8
 }
9 9
 
10
+bundle_test_integration() {
11
+	TESTFLAGS="$TESTFLAGS -v -test.timeout=60m"
12
+	(
13
+		set -e
14
+		cd integration
15
+		INCBUILD="-i"
16
+		count=0
17
+		for flag in "${BUILDFLAGS[@]}"; do
18
+			if [ "${flag}" == ${INCBUILD} ]; then
19
+				unset BUILDFLAGS[${count}]
20
+				break
21
+			fi
22
+			count=$[ ${count} + 1 ]
23
+		done
24
+		echo go test -ldflags "$LDFLAGS" "${BUILDFLAGS[@]}" $TESTFLAGS ./...
25
+		go test -ldflags "$LDFLAGS" "${BUILDFLAGS[@]}" $TESTFLAGS ./...
26
+	)
27
+}
28
+
10 29
 # If $TESTFLAGS is set in the environment, it is passed as extra arguments to 'go test'.
11 30
 # You can use this to select certain tests to run, e.g.
12 31
 #
13 32
new file mode 100755
... ...
@@ -0,0 +1,28 @@
0
+#!/usr/bin/env bash
1
+set -e
2
+
3
+source hack/make/.integration-test-helpers
4
+
5
+# subshell so that we can export PATH without breaking other things
6
+(
7
+	bundle .integration-daemon-start
8
+
9
+	bundle .integration-daemon-setup
10
+
11
+	bundle_test_integration
12
+
13
+	bundle .integration-daemon-stop
14
+
15
+	if [ "$(go env GOOS)" != 'windows' ]
16
+	then
17
+		leftovers=$(ps -ax -o pid,cmd | awk '$2 == "docker-containerd-shim" && $4 ~ /.*\/bundles\/.*\/test-integration-cli/ { print $1 }')
18
+		if [ -n "$leftovers" ]
19
+		then
20
+			ps aux
21
+			kill -9 $leftovers 2> /dev/null
22
+			echo "!!!! WARNING you have left over shim(s), Cleanup your test !!!!"
23
+			exit 1
24
+		fi
25
+	fi
26
+
27
+) 2>&1 | tee -a "$DEST/test.log"
... ...
@@ -11,82 +11,6 @@ import (
11 11
 	"github.com/go-check/check"
12 12
 )
13 13
 
14
-func (s *DockerSuite) TestAPICreateWithNotExistImage(c *check.C) {
15
-	name := "test"
16
-	config := map[string]interface{}{
17
-		"Image":   "test456:v1",
18
-		"Volumes": map[string]struct{}{"/tmp": {}},
19
-	}
20
-
21
-	status, body, err := request.SockRequest("POST", "/containers/create?name="+name, config, daemonHost())
22
-	c.Assert(err, check.IsNil)
23
-	c.Assert(status, check.Equals, http.StatusNotFound)
24
-	expected := "No such image: test456:v1"
25
-	c.Assert(getErrorMessage(c, body), checker.Contains, expected)
26
-
27
-	config2 := map[string]interface{}{
28
-		"Image":   "test456",
29
-		"Volumes": map[string]struct{}{"/tmp": {}},
30
-	}
31
-
32
-	status, body, err = request.SockRequest("POST", "/containers/create?name="+name, config2, daemonHost())
33
-	c.Assert(err, check.IsNil)
34
-	c.Assert(status, check.Equals, http.StatusNotFound)
35
-	expected = "No such image: test456:latest"
36
-	c.Assert(getErrorMessage(c, body), checker.Equals, expected)
37
-
38
-	config3 := map[string]interface{}{
39
-		"Image": "sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa",
40
-	}
41
-
42
-	status, body, err = request.SockRequest("POST", "/containers/create?name="+name, config3, daemonHost())
43
-	c.Assert(err, check.IsNil)
44
-	c.Assert(status, check.Equals, http.StatusNotFound)
45
-	expected = "No such image: sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa"
46
-	c.Assert(getErrorMessage(c, body), checker.Equals, expected)
47
-
48
-}
49
-
50
-// Test for #25099
51
-func (s *DockerSuite) TestAPICreateEmptyEnv(c *check.C) {
52
-	name := "test1"
53
-	config := map[string]interface{}{
54
-		"Image": "busybox",
55
-		"Env":   []string{"", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
56
-		"Cmd":   []string{"true"},
57
-	}
58
-
59
-	status, body, err := request.SockRequest("POST", "/containers/create?name="+name, config, daemonHost())
60
-	c.Assert(err, check.IsNil)
61
-	c.Assert(status, check.Equals, http.StatusInternalServerError)
62
-	expected := "invalid environment variable:"
63
-	c.Assert(getErrorMessage(c, body), checker.Contains, expected)
64
-
65
-	name = "test2"
66
-	config = map[string]interface{}{
67
-		"Image": "busybox",
68
-		"Env":   []string{"=", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
69
-		"Cmd":   []string{"true"},
70
-	}
71
-	status, body, err = request.SockRequest("POST", "/containers/create?name="+name, config, daemonHost())
72
-	c.Assert(err, check.IsNil)
73
-	c.Assert(status, check.Equals, http.StatusInternalServerError)
74
-	expected = "invalid environment variable: ="
75
-	c.Assert(getErrorMessage(c, body), checker.Contains, expected)
76
-
77
-	name = "test3"
78
-	config = map[string]interface{}{
79
-		"Image": "busybox",
80
-		"Env":   []string{"=foo", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
81
-		"Cmd":   []string{"true"},
82
-	}
83
-	status, body, err = request.SockRequest("POST", "/containers/create?name="+name, config, daemonHost())
84
-	c.Assert(err, check.IsNil)
85
-	c.Assert(status, check.Equals, http.StatusInternalServerError)
86
-	expected = "invalid environment variable: =foo"
87
-	c.Assert(getErrorMessage(c, body), checker.Contains, expected)
88
-}
89
-
90 14
 func (s *DockerSuite) TestAPICreateWithInvalidHealthcheckParams(c *check.C) {
91 15
 	// test invalid Interval in Healthcheck: less than 0s
92 16
 	name := "test1"
93 17
new file mode 100644
... ...
@@ -0,0 +1,141 @@
0
+package container
1
+
2
+import (
3
+	"context"
4
+	"fmt"
5
+	"os"
6
+	"testing"
7
+
8
+	"strconv"
9
+
10
+	"github.com/docker/docker/api/types/container"
11
+	"github.com/docker/docker/api/types/network"
12
+	"github.com/docker/docker/client"
13
+	"github.com/docker/docker/integration-cli/environment"
14
+	"github.com/docker/docker/integration-cli/fixtures/load"
15
+	"github.com/stretchr/testify/require"
16
+)
17
+
18
+var (
19
+	testEnv *environment.Execution
20
+)
21
+
22
+func TestMain(m *testing.M) {
23
+	var err error
24
+	testEnv, err = environment.New()
25
+	if err != nil {
26
+		fmt.Println(err)
27
+		os.Exit(1)
28
+	}
29
+
30
+	if testEnv.LocalDaemon() {
31
+		fmt.Println("INFO: Testing against a local daemon")
32
+	} else {
33
+		fmt.Println("INFO: Testing against a remote daemon")
34
+	}
35
+
36
+	// TODO: ensure and protect images
37
+	res := m.Run()
38
+	os.Exit(res)
39
+}
40
+
41
+func TestAPICreateWithNotExistImage(t *testing.T) {
42
+	defer setupTest(t)()
43
+	clt := createClient(t)
44
+
45
+	testCases := []struct {
46
+		image         string
47
+		expectedError string
48
+	}{
49
+		{
50
+			image:         "test456:v1",
51
+			expectedError: "No such image: test456:v1",
52
+		},
53
+		{
54
+			image:         "test456",
55
+			expectedError: "No such image: test456",
56
+		},
57
+		{
58
+			image:         "sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa",
59
+			expectedError: "No such image: sha256:0cb40641836c461bc97c793971d84d758371ed682042457523e4ae701efeaaaa",
60
+		},
61
+	}
62
+
63
+	for index, tc := range testCases {
64
+		tc := tc
65
+		t.Run(strconv.Itoa(index), func(t *testing.T) {
66
+			t.Parallel()
67
+			_, err := clt.ContainerCreate(context.Background(),
68
+				&container.Config{
69
+					Image: tc.image,
70
+				},
71
+				&container.HostConfig{},
72
+				&network.NetworkingConfig{},
73
+				"foo",
74
+			)
75
+			require.Error(t, err)
76
+			require.Contains(t, err.Error(), tc.expectedError)
77
+		})
78
+	}
79
+}
80
+
81
+func TestAPICreateEmptyEnv(t *testing.T) {
82
+	defer setupTest(t)()
83
+	clt := createClient(t)
84
+
85
+	testCases := []struct {
86
+		env           string
87
+		expectedError string
88
+	}{
89
+		{
90
+			env:           "",
91
+			expectedError: "invalid environment variable:",
92
+		},
93
+		{
94
+			env:           "=",
95
+			expectedError: "invalid environment variable: =",
96
+		},
97
+		{
98
+			env:           "=foo",
99
+			expectedError: "invalid environment variable: =foo",
100
+		},
101
+	}
102
+
103
+	for index, tc := range testCases {
104
+		tc := tc
105
+		t.Run(strconv.Itoa(index), func(t *testing.T) {
106
+			t.Parallel()
107
+			_, err := clt.ContainerCreate(context.Background(),
108
+				&container.Config{
109
+					Image: "busybox",
110
+					Env:   []string{tc.env},
111
+				},
112
+				&container.HostConfig{},
113
+				&network.NetworkingConfig{},
114
+				"foo",
115
+			)
116
+			require.Error(t, err)
117
+			require.Contains(t, err.Error(), tc.expectedError)
118
+		})
119
+	}
120
+}
121
+
122
+func createClient(t *testing.T) client.APIClient {
123
+	clt, err := client.NewEnvClient()
124
+	require.NoError(t, err)
125
+	return clt
126
+}
127
+
128
+func setupTest(t *testing.T) func() {
129
+	if testEnv.DaemonPlatform() == "linux" {
130
+		images := []string{"busybox:latest", "hello-world:frozen", "debian:jessie"}
131
+		err := load.FrozenImagesLinux(testEnv.DockerBinary(), images...)
132
+		if err != nil {
133
+			t.Fatalf("%+v", err)
134
+		}
135
+		defer testEnv.ProtectImage(t, images...)
136
+	}
137
+	return func() {
138
+		testEnv.Clean(t, testEnv.DockerBinary())
139
+	}
140
+}
0 141
new file mode 100644
... ...
@@ -0,0 +1,3 @@
0
+// Package integration provides integrations tests for Moby (API).
1
+// These tests require a daemon (dockerd for now) to run.
2
+package integration