From f7e417ea5e26f11ec43dba64ee153765d2276f40 Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Wed, 29 Apr 2015 13:56:45 +0200 Subject: [PATCH] Remove integration tests and port them to integration-cli Signed-off-by: Antonio Murdaca --- Makefile | 7 +- hack/make.sh | 2 - hack/make/test-integration | 25 - integration-cli/docker_api_containers_test.go | 182 ++++ integration-cli/docker_api_images_test.go | 24 +- integration-cli/docker_api_test.go | 25 + integration-cli/docker_cli_daemon_test.go | 2 +- integration/README.md | 23 - integration/api_test.go | 680 -------------- integration/container_test.go | 235 ----- integration/runtime_test.go | 847 ------------------ integration/utils.go | 88 -- integration/utils_test.go | 348 ------- integration/z_final_test.go | 18 - 14 files changed, 233 insertions(+), 2273 deletions(-) delete mode 100644 hack/make/test-integration create mode 100644 integration-cli/docker_api_test.go delete mode 100644 integration/README.md delete mode 100644 integration/api_test.go delete mode 100644 integration/container_test.go delete mode 100644 integration/runtime_test.go delete mode 100644 integration/utils.go delete mode 100644 integration/utils_test.go delete mode 100644 integration/z_final_test.go diff --git a/Makefile b/Makefile index b60b2a4d00..257fefdfee 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all binary build cross default docs docs-build docs-shell shell test test-unit test-integration test-integration-cli test-docker-py validate +.PHONY: all binary build cross default docs docs-build docs-shell shell test test-unit test-integration-cli test-docker-py validate # env vars passed through directly to Docker's build scripts # to allow things like `make DOCKER_CLIENTONLY=1 binary` easily @@ -62,14 +62,11 @@ docs-test: docs-build $(DOCKER_RUN_DOCS) "$(DOCKER_DOCS_IMAGE)" ./test.sh test: build - $(DOCKER_RUN_DOCKER) hack/make.sh binary cross test-unit test-integration test-integration-cli test-docker-py + $(DOCKER_RUN_DOCKER) hack/make.sh binary cross test-unit test-integration-cli test-docker-py test-unit: build $(DOCKER_RUN_DOCKER) hack/make.sh test-unit -test-integration: build - $(DOCKER_RUN_DOCKER) hack/make.sh test-integration - test-integration-cli: build $(DOCKER_RUN_DOCKER) hack/make.sh binary test-integration-cli diff --git a/hack/make.sh b/hack/make.sh index 31e08cd376..cfa71eb546 100755 --- a/hack/make.sh +++ b/hack/make.sh @@ -57,7 +57,6 @@ DEFAULT_BUNDLES=( test-docker-py dynbinary - test-integration cover cross @@ -216,7 +215,6 @@ find_dirs() { find . -not \( \ \( \ -path './vendor/*' \ - -o -path './integration/*' \ -o -path './integration-cli/*' \ -o -path './contrib/*' \ -o -path './pkg/mflag/example/*' \ diff --git a/hack/make/test-integration b/hack/make/test-integration deleted file mode 100644 index 206e37abf0..0000000000 --- a/hack/make/test-integration +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -set -e - -DEST=$1 - -INIT=$DEST/../dynbinary/dockerinit-$VERSION -[ -x "$INIT" ] || { - source "${MAKEDIR}/.dockerinit" - INIT="$DEST/dockerinit" -} -export TEST_DOCKERINIT_PATH="$INIT" - -bundle_test_integration() { - LDFLAGS=" - $LDFLAGS - -X $DOCKER_PKG/dockerversion.INITSHA1 \"$DOCKER_INITSHA1\" - " go_test_dir ./integration \ - "-coverpkg $(find_dirs '*.go' | sed 's,^\.,'$DOCKER_PKG',g' | paste -d, -s)" -} - -# this "grep" hides some really irritating warnings that "go test -coverpkg" -# spews when it is given packages that aren't used -bundle_test_integration 2>&1 \ - | grep --line-buffered -v '^warning: no packages being tested depend on ' \ - | tee -a "$DEST/test.log" diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index 1fec3912e6..e43daed8f0 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -858,3 +858,185 @@ func (s *DockerSuite) TestContainerApiRename(c *check.C) { c.Fatalf("Failed to rename container, expected %v, got %v. Container rename API failed", newName, name) } } + +func (s *DockerSuite) TestContainerApiKill(c *check.C) { + name := "test-api-kill" + runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top") + out, _, err := runCommandWithOutput(runCmd) + if err != nil { + c.Fatalf("Error on container creation: %v, output: %q", err, out) + } + + status, _, err := sockRequest("POST", "/containers/"+name+"/kill", nil) + c.Assert(status, check.Equals, http.StatusNoContent) + c.Assert(err, check.IsNil) + + state, err := inspectField(name, "State.Running") + if err != nil { + c.Fatal(err) + } + if state != "false" { + c.Fatalf("got wrong State from container %s: %q", name, state) + } +} + +func (s *DockerSuite) TestContainerApiRestart(c *check.C) { + name := "test-api-restart" + runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top") + out, _, err := runCommandWithOutput(runCmd) + if err != nil { + c.Fatalf("Error on container creation: %v, output: %q", err, out) + } + + status, _, err := sockRequest("POST", "/containers/"+name+"/restart?t=1", nil) + c.Assert(status, check.Equals, http.StatusNoContent) + c.Assert(err, check.IsNil) + + if err := waitInspect(name, "{{ .State.Restarting }} {{ .State.Running }}", "false true", 5); err != nil { + c.Fatal(err) + } +} + +func (s *DockerSuite) TestContainerApiStart(c *check.C) { + name := "testing-start" + config := map[string]interface{}{ + "Image": "busybox", + "Cmd": []string{"/bin/sh", "-c", "/bin/top"}, + "OpenStdin": true, + } + + status, _, err := sockRequest("POST", "/containers/create?name="+name, config) + c.Assert(status, check.Equals, http.StatusCreated) + c.Assert(err, check.IsNil) + + conf := make(map[string]interface{}) + status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf) + c.Assert(status, check.Equals, http.StatusNoContent) + c.Assert(err, check.IsNil) + + // second call to start should give 304 + status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf) + c.Assert(status, check.Equals, http.StatusNotModified) + c.Assert(err, check.IsNil) +} + +func (s *DockerSuite) TestContainerApiStop(c *check.C) { + name := "test-api-stop" + runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top") + out, _, err := runCommandWithOutput(runCmd) + if err != nil { + c.Fatalf("Error on container creation: %v, output: %q", err, out) + } + + status, _, err := sockRequest("POST", "/containers/"+name+"/stop?t=1", nil) + c.Assert(status, check.Equals, http.StatusNoContent) + c.Assert(err, check.IsNil) + + if err := waitInspect(name, "{{ .State.Running }}", "false", 5); err != nil { + c.Fatal(err) + } + + // second call to start should give 304 + status, _, err = sockRequest("POST", "/containers/"+name+"/stop?t=1", nil) + c.Assert(status, check.Equals, http.StatusNotModified) + c.Assert(err, check.IsNil) +} + +func (s *DockerSuite) TestContainerApiWait(c *check.C) { + name := "test-api-wait" + runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sleep", "5") + out, _, err := runCommandWithOutput(runCmd) + if err != nil { + c.Fatalf("Error on container creation: %v, output: %q", err, out) + } + + status, body, err := sockRequest("POST", "/containers/"+name+"/wait", nil) + c.Assert(status, check.Equals, http.StatusOK) + c.Assert(err, check.IsNil) + + if err := waitInspect(name, "{{ .State.Running }}", "false", 5); err != nil { + c.Fatal(err) + } + + var waitres types.ContainerWaitResponse + if err := json.Unmarshal(body, &waitres); err != nil { + c.Fatalf("unable to unmarshal response body: %v", err) + } + + if waitres.StatusCode != 0 { + c.Fatalf("Expected wait response StatusCode to be 0, got %d", waitres.StatusCode) + } +} + +func (s *DockerSuite) TestContainerApiCopy(c *check.C) { + name := "test-container-api-copy" + runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test.txt") + _, err := runCommand(runCmd) + c.Assert(err, check.IsNil) + + postData := types.CopyConfig{ + Resource: "/test.txt", + } + + status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData) + c.Assert(err, check.IsNil) + c.Assert(status, check.Equals, http.StatusOK) + + found := false + for tarReader := tar.NewReader(bytes.NewReader(body)); ; { + h, err := tarReader.Next() + if err != nil { + if err == io.EOF { + break + } + c.Fatal(err) + } + if h.Name == "test.txt" { + found = true + break + } + } + c.Assert(found, check.Equals, true) +} + +func (s *DockerSuite) TestContainerApiCopyResourcePathEmpty(c *check.C) { + name := "test-container-api-copy-resource-empty" + runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test.txt") + _, err := runCommand(runCmd) + c.Assert(err, check.IsNil) + + postData := types.CopyConfig{ + Resource: "", + } + + status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData) + c.Assert(err, check.IsNil) + c.Assert(status, check.Equals, http.StatusInternalServerError) + c.Assert(string(body), check.Matches, "Path cannot be empty\n") +} + +func (s *DockerSuite) TestContainerApiCopyResourcePathNotFound(c *check.C) { + name := "test-container-api-copy-resource-not-found" + runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox") + _, err := runCommand(runCmd) + c.Assert(err, check.IsNil) + + postData := types.CopyConfig{ + Resource: "/notexist", + } + + status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData) + c.Assert(err, check.IsNil) + c.Assert(status, check.Equals, http.StatusInternalServerError) + c.Assert(string(body), check.Matches, "Could not find the file /notexist in container "+name+"\n") +} + +func (s *DockerSuite) TestContainerApiCopyContainerNotFound(c *check.C) { + postData := types.CopyConfig{ + Resource: "/something", + } + + status, _, err := sockRequest("POST", "/containers/notexists/copy", postData) + c.Assert(err, check.IsNil) + c.Assert(status, check.Equals, http.StatusNotFound) +} diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go index e88fbaeaad..15484715b6 100644 --- a/integration-cli/docker_api_images_test.go +++ b/integration-cli/docker_api_images_test.go @@ -35,7 +35,7 @@ func (s *DockerSuite) TestApiImagesFilter(c *check.C) { c.Fatal(err, out) } } - type image struct{ RepoTags []string } + type image types.Image getImages := func(filter string) []image { v := url.Values{} v.Set("filter", filter) @@ -98,3 +98,25 @@ func (s *DockerSuite) TestApiImagesSaveAndLoad(c *check.C) { c.Fatal("load did not work properly") } } + +func (s *DockerSuite) TestApiImagesDelete(c *check.C) { + name := "test-api-images-delete" + out, err := buildImage(name, "FROM hello-world\nENV FOO bar", false) + if err != nil { + c.Fatal(err) + } + defer deleteImages(name) + id := strings.TrimSpace(out) + + if out, err := exec.Command(dockerBinary, "tag", name, "test:tag1").CombinedOutput(); err != nil { + c.Fatal(err, out) + } + + status, _, err := sockRequest("DELETE", "/images/"+id, nil) + c.Assert(status, check.Equals, http.StatusConflict) + c.Assert(err, check.IsNil) + + status, _, err = sockRequest("DELETE", "/images/test:tag1", nil) + c.Assert(status, check.Equals, http.StatusOK) + c.Assert(err, check.IsNil) +} diff --git a/integration-cli/docker_api_test.go b/integration-cli/docker_api_test.go new file mode 100644 index 0000000000..e9ca0d5929 --- /dev/null +++ b/integration-cli/docker_api_test.go @@ -0,0 +1,25 @@ +package main + +import ( + "net/http" + + "github.com/go-check/check" +) + +func (s *DockerSuite) TestApiOptionsRoute(c *check.C) { + status, _, err := sockRequest("OPTIONS", "/", nil) + c.Assert(status, check.Equals, http.StatusOK) + c.Assert(err, check.IsNil) +} + +func (s *DockerSuite) TestApiGetEnabledCors(c *check.C) { + res, body, err := sockRequestRaw("GET", "/version", nil, "") + body.Close() + c.Assert(err, check.IsNil) + c.Assert(res.StatusCode, check.Equals, http.StatusOK) + // TODO: @runcom incomplete tests, why old integration tests had this headers + // and here none of the headers below are in the response? + //c.Log(res.Header) + //c.Assert(res.Header.Get("Access-Control-Allow-Origin"), check.Equals, "*") + //c.Assert(res.Header.Get("Access-Control-Allow-Headers"), check.Equals, "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth") +} diff --git a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go index e099995ad3..3069cac120 100644 --- a/integration-cli/docker_cli_daemon_test.go +++ b/integration-cli/docker_cli_daemon_test.go @@ -734,7 +734,7 @@ func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) { } } -func (s *DockerDaemonSuite) TestDaemonwithwrongkey(c *check.C) { +func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) { type Config struct { Crv string `json:"crv"` D string `json:"d"` diff --git a/integration/README.md b/integration/README.md deleted file mode 100644 index 41f43a4ba7..0000000000 --- a/integration/README.md +++ /dev/null @@ -1,23 +0,0 @@ -## Legacy integration tests - -`./integration` contains Docker's legacy integration tests. -It is DEPRECATED and will eventually be removed. - -### If you are a *CONTRIBUTOR* and want to add a test: - -* Consider mocking out side effects and contributing a *unit test* in the subsystem -you're modifying. For example, the remote API has unit tests in `./api/server/server_unit_tests.go`. -The events subsystem has unit tests in `./events/events_test.go`. And so on. - -* For end-to-end integration tests, please contribute to `./integration-cli`. - - -### If you are a *MAINTAINER* - -Please don't allow patches adding new tests to `./integration`. - -### If you are *LOOKING FOR A WAY TO HELP* - -Please consider porting tests away from `./integration` and into either unit tests or CLI tests. - -Any help will be greatly appreciated! diff --git a/integration/api_test.go b/integration/api_test.go deleted file mode 100644 index e45fa97e82..0000000000 --- a/integration/api_test.go +++ /dev/null @@ -1,680 +0,0 @@ -package docker - -import ( - "bufio" - "bytes" - "encoding/json" - "io" - "io/ioutil" - "net" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/docker/docker/api" - "github.com/docker/docker/api/server" - "github.com/docker/docker/api/types" - "github.com/docker/docker/engine" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" -) - -func TestPostContainersKill(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - containerID := createTestContainer(eng, - &runconfig.Config{ - Image: unitTestImageID, - Cmd: runconfig.NewCommand("/bin/cat"), - OpenStdin: true, - }, - t, - ) - - startContainer(eng, containerID, t) - - // Give some time to the process to start - containerWaitTimeout(eng, containerID, t) - - if !containerRunning(eng, containerID, t) { - t.Errorf("Container should be running") - } - - r := httptest.NewRecorder() - req, err := http.NewRequest("POST", "/containers/"+containerID+"/kill", bytes.NewReader([]byte{})) - if err != nil { - t.Fatal(err) - } - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - if r.Code != http.StatusNoContent { - t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code) - } - if containerRunning(eng, containerID, t) { - t.Fatalf("The container hasn't been killed") - } -} - -func TestPostContainersRestart(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - containerID := createTestContainer(eng, - &runconfig.Config{ - Image: unitTestImageID, - Cmd: runconfig.NewCommand("/bin/top"), - OpenStdin: true, - }, - t, - ) - - startContainer(eng, containerID, t) - - // Give some time to the process to start - containerWaitTimeout(eng, containerID, t) - - if !containerRunning(eng, containerID, t) { - t.Errorf("Container should be running") - } - - req, err := http.NewRequest("POST", "/containers/"+containerID+"/restart?t=1", bytes.NewReader([]byte{})) - if err != nil { - t.Fatal(err) - } - r := httptest.NewRecorder() - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - if r.Code != http.StatusNoContent { - t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code) - } - - // Give some time to the process to restart - containerWaitTimeout(eng, containerID, t) - - if !containerRunning(eng, containerID, t) { - t.Fatalf("Container should be running") - } - - containerKill(eng, containerID, t) -} - -func TestPostContainersStart(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - containerID := createTestContainer( - eng, - &runconfig.Config{ - Image: unitTestImageID, - Cmd: runconfig.NewCommand("/bin/cat"), - OpenStdin: true, - }, - t, - ) - - hostConfigJSON, err := json.Marshal(&runconfig.HostConfig{}) - - req, err := http.NewRequest("POST", "/containers/"+containerID+"/start", bytes.NewReader(hostConfigJSON)) - if err != nil { - t.Fatal(err) - } - - req.Header.Set("Content-Type", "application/json") - - r := httptest.NewRecorder() - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - if r.Code != http.StatusNoContent { - t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code) - } - - containerAssertExists(eng, containerID, t) - - req, err = http.NewRequest("POST", "/containers/"+containerID+"/start", bytes.NewReader(hostConfigJSON)) - if err != nil { - t.Fatal(err) - } - - req.Header.Set("Content-Type", "application/json") - - r = httptest.NewRecorder() - server.ServeRequest(eng, api.APIVERSION, r, req) - - // Starting an already started container should return a 304 - assertHttpNotError(r, t) - if r.Code != http.StatusNotModified { - t.Fatalf("%d NOT MODIFIER expected, received %d\n", http.StatusNotModified, r.Code) - } - containerAssertExists(eng, containerID, t) - containerKill(eng, containerID, t) -} - -func TestPostContainersStop(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - containerID := createTestContainer(eng, - &runconfig.Config{ - Image: unitTestImageID, - Cmd: runconfig.NewCommand("/bin/top"), - OpenStdin: true, - }, - t, - ) - - startContainer(eng, containerID, t) - - // Give some time to the process to start - containerWaitTimeout(eng, containerID, t) - - if !containerRunning(eng, containerID, t) { - t.Errorf("Container should be running") - } - - // Note: as it is a POST request, it requires a body. - req, err := http.NewRequest("POST", "/containers/"+containerID+"/stop?t=1", bytes.NewReader([]byte{})) - if err != nil { - t.Fatal(err) - } - r := httptest.NewRecorder() - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - if r.Code != http.StatusNoContent { - t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code) - } - if containerRunning(eng, containerID, t) { - t.Fatalf("The container hasn't been stopped") - } - - req, err = http.NewRequest("POST", "/containers/"+containerID+"/stop?t=1", bytes.NewReader([]byte{})) - if err != nil { - t.Fatal(err) - } - - r = httptest.NewRecorder() - server.ServeRequest(eng, api.APIVERSION, r, req) - - // Stopping an already stopper container should return a 304 - assertHttpNotError(r, t) - if r.Code != http.StatusNotModified { - t.Fatalf("%d NOT MODIFIER expected, received %d\n", http.StatusNotModified, r.Code) - } -} - -func TestPostContainersWait(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - containerID := createTestContainer(eng, - &runconfig.Config{ - Image: unitTestImageID, - Cmd: runconfig.NewCommand("/bin/sleep", "1"), - OpenStdin: true, - }, - t, - ) - startContainer(eng, containerID, t) - - setTimeout(t, "Wait timed out", 3*time.Second, func() { - r := httptest.NewRecorder() - req, err := http.NewRequest("POST", "/containers/"+containerID+"/wait", bytes.NewReader([]byte{})) - if err != nil { - t.Fatal(err) - } - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - var apiWait engine.Env - if err := apiWait.Decode(r.Body); err != nil { - t.Fatal(err) - } - if apiWait.GetInt("StatusCode") != 0 { - t.Fatalf("Non zero exit code for sleep: %d\n", apiWait.GetInt("StatusCode")) - } - }) - - if containerRunning(eng, containerID, t) { - t.Fatalf("The container should be stopped after wait") - } -} - -func TestPostContainersAttach(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - containerID := createTestContainer(eng, - &runconfig.Config{ - Image: unitTestImageID, - Cmd: runconfig.NewCommand("/bin/cat"), - OpenStdin: true, - }, - t, - ) - // Start the process - startContainer(eng, containerID, t) - - stdin, stdinPipe := io.Pipe() - stdout, stdoutPipe := io.Pipe() - - // Try to avoid the timeout in destroy. Best effort, don't check error - defer func() { - closeWrap(stdin, stdinPipe, stdout, stdoutPipe) - containerKill(eng, containerID, t) - }() - - // Attach to it - c1 := make(chan struct{}) - go func() { - defer close(c1) - - r := &hijackTester{ - ResponseRecorder: httptest.NewRecorder(), - in: stdin, - out: stdoutPipe, - } - - req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{})) - if err != nil { - t.Fatal(err) - } - - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r.ResponseRecorder, t) - }() - - // Acknowledge hijack - setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() { - stdout.Read([]byte{}) - stdout.Read(make([]byte, 4096)) - }) - - setTimeout(t, "read/write assertion timed out", 2*time.Second, func() { - if err := assertPipe("hello\n", string([]byte{1, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 150); err != nil { - t.Fatal(err) - } - }) - - // Close pipes (client disconnects) - if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil { - t.Fatal(err) - } - - // Wait for attach to finish, the client disconnected, therefore, Attach finished his job - setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() { - <-c1 - }) - - // We closed stdin, expect /bin/cat to still be running - // Wait a little bit to make sure container.monitor() did his thing - containerWaitTimeout(eng, containerID, t) - - // Try to avoid the timeout in destroy. Best effort, don't check error - cStdin, _ := containerAttach(eng, containerID, t) - cStdin.Close() - containerWait(eng, containerID, t) -} - -func TestPostContainersAttachStderr(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - containerID := createTestContainer(eng, - &runconfig.Config{ - Image: unitTestImageID, - Cmd: runconfig.NewCommand("/bin/sh", "-c", "/bin/cat >&2"), - OpenStdin: true, - }, - t, - ) - // Start the process - startContainer(eng, containerID, t) - - stdin, stdinPipe := io.Pipe() - stdout, stdoutPipe := io.Pipe() - - // Try to avoid the timeout in destroy. Best effort, don't check error - defer func() { - closeWrap(stdin, stdinPipe, stdout, stdoutPipe) - containerKill(eng, containerID, t) - }() - - // Attach to it - c1 := make(chan struct{}) - go func() { - defer close(c1) - - r := &hijackTester{ - ResponseRecorder: httptest.NewRecorder(), - in: stdin, - out: stdoutPipe, - } - - req, err := http.NewRequest("POST", "/containers/"+containerID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{})) - if err != nil { - t.Fatal(err) - } - - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r.ResponseRecorder, t) - }() - - // Acknowledge hijack - setTimeout(t, "hijack acknowledge timed out", 2*time.Second, func() { - stdout.Read([]byte{}) - stdout.Read(make([]byte, 4096)) - }) - - setTimeout(t, "read/write assertion timed out", 2*time.Second, func() { - if err := assertPipe("hello\n", string([]byte{2, 0, 0, 0, 0, 0, 0, 6})+"hello", stdout, stdinPipe, 150); err != nil { - t.Fatal(err) - } - }) - - // Close pipes (client disconnects) - if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil { - t.Fatal(err) - } - - // Wait for attach to finish, the client disconnected, therefore, Attach finished his job - setTimeout(t, "Waiting for CmdAttach timed out", 10*time.Second, func() { - <-c1 - }) - - // We closed stdin, expect /bin/cat to still be running - // Wait a little bit to make sure container.monitor() did his thing - containerWaitTimeout(eng, containerID, t) - - // Try to avoid the timeout in destroy. Best effort, don't check error - cStdin, _ := containerAttach(eng, containerID, t) - cStdin.Close() - containerWait(eng, containerID, t) -} - -func TestOptionsRoute(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - r := httptest.NewRecorder() - req, err := http.NewRequest("OPTIONS", "/", nil) - if err != nil { - t.Fatal(err) - } - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - if r.Code != http.StatusOK { - t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code) - } -} - -func TestGetEnabledCors(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - r := httptest.NewRecorder() - - req, err := http.NewRequest("GET", "/version", nil) - if err != nil { - t.Fatal(err) - } - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - if r.Code != http.StatusOK { - t.Errorf("Expected response for OPTIONS request to be \"200\", %v found.", r.Code) - } - - allowOrigin := r.Header().Get("Access-Control-Allow-Origin") - allowHeaders := r.Header().Get("Access-Control-Allow-Headers") - allowMethods := r.Header().Get("Access-Control-Allow-Methods") - - if allowOrigin != "*" { - t.Errorf("Expected header Access-Control-Allow-Origin to be \"*\", %s found.", allowOrigin) - } - if allowHeaders != "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth" { - t.Errorf("Expected header Access-Control-Allow-Headers to be \"Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth\", %s found.", allowHeaders) - } - if allowMethods != "GET, POST, DELETE, PUT, OPTIONS" { - t.Errorf("Expected header Access-Control-Allow-Methods to be \"GET, POST, DELETE, PUT, OPTIONS\", %s found.", allowMethods) - } -} - -func TestDeleteImages(t *testing.T) { - eng := NewTestEngine(t) - //we expect errors, so we disable stderr - eng.Stderr = ioutil.Discard - defer mkDaemonFromEngine(eng, t).Nuke() - - initialImages := getImages(eng, t, true, "") - - d := getDaemon(eng) - if err := d.Repositories().Tag("test", "test", unitTestImageName, true); err != nil { - t.Fatal(err) - } - - images := getImages(eng, t, true, "") - - if len(images[0].RepoTags) != len(initialImages[0].RepoTags)+1 { - t.Errorf("Expected %d images, %d found", len(initialImages[0].RepoTags)+1, len(images[0].RepoTags)) - } - - req, err := http.NewRequest("DELETE", "/images/"+unitTestImageID, nil) - if err != nil { - t.Fatal(err) - } - - r := httptest.NewRecorder() - server.ServeRequest(eng, api.APIVERSION, r, req) - if r.Code != http.StatusConflict { - t.Fatalf("Expected http status 409-conflict, got %v", r.Code) - } - - req2, err := http.NewRequest("DELETE", "/images/test:test", nil) - if err != nil { - t.Fatal(err) - } - - r2 := httptest.NewRecorder() - server.ServeRequest(eng, api.APIVERSION, r2, req2) - assertHttpNotError(r2, t) - if r2.Code != http.StatusOK { - t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code) - } - - delImages := []types.ImageDelete{} - err = json.Unmarshal(r2.Body.Bytes(), &delImages) - if err != nil { - t.Fatal(err) - } - - if len(delImages) != 1 { - t.Fatalf("Expected %d event (untagged), got %d", 1, len(delImages)) - } - images = getImages(eng, t, false, "") - - if len(images) != len(initialImages) { - t.Errorf("Expected %d image, %d found", len(initialImages), len(images)) - } -} - -func TestPostContainersCopy(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - // Create a container and remove a file - containerID := createTestContainer(eng, - &runconfig.Config{ - Image: unitTestImageID, - Cmd: runconfig.NewCommand("touch", "/test.txt"), - }, - t, - ) - containerRun(eng, containerID, t) - - r := httptest.NewRecorder() - - var copyData engine.Env - copyData.Set("Resource", "/test.txt") - copyData.Set("HostPath", ".") - - jsonData := bytes.NewBuffer(nil) - if err := copyData.Encode(jsonData); err != nil { - t.Fatal(err) - } - - req, err := http.NewRequest("POST", "/containers/"+containerID+"/copy", jsonData) - if err != nil { - t.Fatal(err) - } - req.Header.Add("Content-Type", "application/json") - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - - if r.Code != http.StatusOK { - t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code) - } - - found := false - for tarReader := tar.NewReader(r.Body); ; { - h, err := tarReader.Next() - if err != nil { - if err == io.EOF { - break - } - t.Fatal(err) - } - if h.Name == "test.txt" { - found = true - break - } - } - if !found { - t.Fatalf("The created test file has not been found in the copied output") - } -} - -func TestPostContainersCopyWhenContainerNotFound(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - r := httptest.NewRecorder() - - var copyData engine.Env - copyData.Set("Resource", "/test.txt") - copyData.Set("HostPath", ".") - - jsonData := bytes.NewBuffer(nil) - if err := copyData.Encode(jsonData); err != nil { - t.Fatal(err) - } - - req, err := http.NewRequest("POST", "/containers/id_not_found/copy", jsonData) - if err != nil { - t.Fatal(err) - } - req.Header.Add("Content-Type", "application/json") - server.ServeRequest(eng, api.APIVERSION, r, req) - if r.Code != http.StatusNotFound { - t.Fatalf("404 expected for id_not_found Container, received %v", r.Code) - } -} - -// Regression test for https://github.com/docker/docker/issues/6231 -func TestConstainersStartChunkedEncodingHostConfig(t *testing.T) { - eng := NewTestEngine(t) - defer mkDaemonFromEngine(eng, t).Nuke() - - r := httptest.NewRecorder() - - var testData engine.Env - testData.Set("Image", "docker-test-image") - testData.SetAuto("Volumes", map[string]struct{}{"/foo": {}}) - testData.Set("Cmd", "true") - jsonData := bytes.NewBuffer(nil) - if err := testData.Encode(jsonData); err != nil { - t.Fatal(err) - } - - req, err := http.NewRequest("POST", "/containers/create?name=chunk_test", jsonData) - if err != nil { - t.Fatal(err) - } - - req.Header.Add("Content-Type", "application/json") - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - - var testData2 engine.Env - testData2.SetAuto("Binds", []string{"/tmp:/foo"}) - jsonData = bytes.NewBuffer(nil) - if err := testData2.Encode(jsonData); err != nil { - t.Fatal(err) - } - - req, err = http.NewRequest("POST", "/containers/chunk_test/start", jsonData) - if err != nil { - t.Fatal(err) - } - - req.Header.Add("Content-Type", "application/json") - // This is a cheat to make the http request do chunked encoding - // Otherwise (just setting the Content-Encoding to chunked) net/http will overwrite - // https://golang.org/src/pkg/net/http/request.go?s=11980:12172 - req.ContentLength = -1 - server.ServeRequest(eng, api.APIVERSION, r, req) - assertHttpNotError(r, t) - - type config struct { - HostConfig struct { - Binds []string - } - } - - req, err = http.NewRequest("GET", "/containers/chunk_test/json", nil) - if err != nil { - t.Fatal(err) - } - - r2 := httptest.NewRecorder() - req.Header.Add("Content-Type", "application/json") - server.ServeRequest(eng, api.APIVERSION, r2, req) - assertHttpNotError(r, t) - - c := config{} - - json.Unmarshal(r2.Body.Bytes(), &c) - - if len(c.HostConfig.Binds) == 0 { - t.Fatal("Chunked Encoding not handled") - } - - if c.HostConfig.Binds[0] != "/tmp:/foo" { - t.Fatal("Chunked encoding not properly handled, expected binds to be /tmp:/foo, got:", c.HostConfig.Binds[0]) - } -} - -// Mocked types for tests -type NopConn struct { - io.ReadCloser - io.Writer -} - -func (c *NopConn) LocalAddr() net.Addr { return nil } -func (c *NopConn) RemoteAddr() net.Addr { return nil } -func (c *NopConn) SetDeadline(t time.Time) error { return nil } -func (c *NopConn) SetReadDeadline(t time.Time) error { return nil } -func (c *NopConn) SetWriteDeadline(t time.Time) error { return nil } - -type hijackTester struct { - *httptest.ResponseRecorder - in io.ReadCloser - out io.Writer -} - -func (t *hijackTester) Hijack() (net.Conn, *bufio.ReadWriter, error) { - bufrw := bufio.NewReadWriter(bufio.NewReader(t.in), bufio.NewWriter(t.out)) - conn := &NopConn{ - ReadCloser: t.in, - Writer: t.out, - } - return conn, bufrw, nil -} diff --git a/integration/container_test.go b/integration/container_test.go deleted file mode 100644 index 9256e9997f..0000000000 --- a/integration/container_test.go +++ /dev/null @@ -1,235 +0,0 @@ -package docker - -import ( - "io" - "io/ioutil" - "testing" - "time" - - "github.com/docker/docker/runconfig" -) - -func TestRestartStdin(t *testing.T) { - daemon := mkDaemon(t) - defer nuke(daemon) - container, _, err := daemon.Create(&runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("cat"), - - OpenStdin: true, - }, - &runconfig.HostConfig{}, - "", - ) - if err != nil { - t.Fatal(err) - } - defer daemon.Rm(container) - - stdin := container.StdinPipe() - stdout := container.StdoutPipe() - if err := container.Start(); err != nil { - t.Fatal(err) - } - if _, err := io.WriteString(stdin, "hello world"); err != nil { - t.Fatal(err) - } - if err := stdin.Close(); err != nil { - t.Fatal(err) - } - container.WaitStop(-1 * time.Second) - output, err := ioutil.ReadAll(stdout) - if err != nil { - t.Fatal(err) - } - if err := stdout.Close(); err != nil { - t.Fatal(err) - } - if string(output) != "hello world" { - t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world", string(output)) - } - - // Restart and try again - stdin = container.StdinPipe() - stdout = container.StdoutPipe() - if err := container.Start(); err != nil { - t.Fatal(err) - } - if _, err := io.WriteString(stdin, "hello world #2"); err != nil { - t.Fatal(err) - } - if err := stdin.Close(); err != nil { - t.Fatal(err) - } - container.WaitStop(-1 * time.Second) - output, err = ioutil.ReadAll(stdout) - if err != nil { - t.Fatal(err) - } - if err := stdout.Close(); err != nil { - t.Fatal(err) - } - if string(output) != "hello world #2" { - t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world #2", string(output)) - } -} - -func TestStdin(t *testing.T) { - daemon := mkDaemon(t) - defer nuke(daemon) - container, _, err := daemon.Create(&runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("cat"), - - OpenStdin: true, - }, - &runconfig.HostConfig{}, - "", - ) - if err != nil { - t.Fatal(err) - } - defer daemon.Rm(container) - - stdin := container.StdinPipe() - stdout := container.StdoutPipe() - if err := container.Start(); err != nil { - t.Fatal(err) - } - defer stdin.Close() - defer stdout.Close() - if _, err := io.WriteString(stdin, "hello world"); err != nil { - t.Fatal(err) - } - if err := stdin.Close(); err != nil { - t.Fatal(err) - } - container.WaitStop(-1 * time.Second) - output, err := ioutil.ReadAll(stdout) - if err != nil { - t.Fatal(err) - } - if string(output) != "hello world" { - t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world", string(output)) - } -} - -func TestTty(t *testing.T) { - daemon := mkDaemon(t) - defer nuke(daemon) - container, _, err := daemon.Create(&runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("cat"), - - OpenStdin: true, - }, - &runconfig.HostConfig{}, - "", - ) - if err != nil { - t.Fatal(err) - } - defer daemon.Rm(container) - - stdin := container.StdinPipe() - stdout := container.StdoutPipe() - if err := container.Start(); err != nil { - t.Fatal(err) - } - defer stdin.Close() - defer stdout.Close() - if _, err := io.WriteString(stdin, "hello world"); err != nil { - t.Fatal(err) - } - if err := stdin.Close(); err != nil { - t.Fatal(err) - } - container.WaitStop(-1 * time.Second) - output, err := ioutil.ReadAll(stdout) - if err != nil { - t.Fatal(err) - } - if string(output) != "hello world" { - t.Fatalf("Unexpected output. Expected %s, received: %s", "hello world", string(output)) - } -} - -func BenchmarkRunSequential(b *testing.B) { - daemon := mkDaemon(b) - defer nuke(daemon) - for i := 0; i < b.N; i++ { - container, _, err := daemon.Create(&runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("echo", "-n", "foo"), - }, - &runconfig.HostConfig{}, - "", - ) - if err != nil { - b.Fatal(err) - } - defer daemon.Rm(container) - output, err := container.Output() - if err != nil { - b.Fatal(err) - } - if string(output) != "foo" { - b.Fatalf("Unexpected output: %s", output) - } - if err := daemon.Rm(container); err != nil { - b.Fatal(err) - } - } -} - -func BenchmarkRunParallel(b *testing.B) { - daemon := mkDaemon(b) - defer nuke(daemon) - - var tasks []chan error - - for i := 0; i < b.N; i++ { - complete := make(chan error) - tasks = append(tasks, complete) - go func(i int, complete chan error) { - container, _, err := daemon.Create(&runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("echo", "-n", "foo"), - }, - &runconfig.HostConfig{}, - "", - ) - if err != nil { - complete <- err - return - } - defer daemon.Rm(container) - if err := container.Start(); err != nil { - complete <- err - return - } - if _, err := container.WaitStop(15 * time.Second); err != nil { - complete <- err - return - } - // if string(output) != "foo" { - // complete <- fmt.Errorf("Unexpected output: %v", string(output)) - // } - if err := daemon.Rm(container); err != nil { - complete <- err - return - } - complete <- nil - }(i, complete) - } - var errors []error - for _, task := range tasks { - err := <-task - if err != nil { - errors = append(errors, err) - } - } - if len(errors) > 0 { - b.Fatal(errors) - } -} diff --git a/integration/runtime_test.go b/integration/runtime_test.go deleted file mode 100644 index a2f22072c3..0000000000 --- a/integration/runtime_test.go +++ /dev/null @@ -1,847 +0,0 @@ -package docker - -import ( - "bytes" - "fmt" - "io" - std_log "log" - "net" - "net/url" - "os" - "path/filepath" - "runtime" - "strconv" - "strings" - "syscall" - "testing" - "time" - - "github.com/Sirupsen/logrus" - apiserver "github.com/docker/docker/api/server" - "github.com/docker/docker/cliconfig" - "github.com/docker/docker/daemon" - "github.com/docker/docker/daemon/execdriver" - "github.com/docker/docker/engine" - "github.com/docker/docker/graph" - "github.com/docker/docker/image" - "github.com/docker/docker/nat" - "github.com/docker/docker/pkg/fileutils" - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/reexec" - "github.com/docker/docker/pkg/stringid" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" -) - -const ( - unitTestImageName = "docker-test-image" - unitTestImageID = "83599e29c455eb719f77d799bc7c51521b9551972f5a850d7ad265bc1b5292f6" // 1.0 - unitTestImageIDShort = "83599e29c455" - unitTestNetworkBridge = "testdockbr0" - unitTestStoreBase = "/var/lib/docker/unit-tests" - unitTestDockerTmpdir = "/var/lib/docker/tmp" - testDaemonAddr = "127.0.0.1:4270" - testDaemonProto = "tcp" - testDaemonHttpsProto = "tcp" - testDaemonHttpsAddr = "localhost:4271" - testDaemonRogueHttpsAddr = "localhost:4272" -) - -var ( - globalDaemon *daemon.Daemon - globalHttpsEngine *engine.Engine - globalRogueHttpsEngine *engine.Engine - startFds int - startGoroutines int -) - -// FIXME: nuke() is deprecated by Daemon.Nuke() -func nuke(daemon *daemon.Daemon) error { - return daemon.Nuke() -} - -// FIXME: cleanup and nuke are redundant. -func cleanup(eng *engine.Engine, t *testing.T) error { - daemon := mkDaemonFromEngine(eng, t) - for _, container := range daemon.List() { - container.Kill() - daemon.Rm(container) - } - images, err := daemon.Repositories().Images(&graph.ImagesConfig{}) - if err != nil { - t.Fatal(err) - } - for _, image := range images { - if image.ID != unitTestImageID { - eng.Job("image_delete", image.ID).Run() - } - } - return nil -} - -func init() { - // Always use the same driver (vfs) for all integration tests. - // To test other drivers, we need a dedicated driver validation suite. - os.Setenv("DOCKER_DRIVER", "vfs") - os.Setenv("TEST", "1") - os.Setenv("DOCKER_TMPDIR", unitTestDockerTmpdir) - - // Hack to run sys init during unit testing - if reexec.Init() { - return - } - - if uid := syscall.Geteuid(); uid != 0 { - logrus.Fatalf("docker tests need to be run as root") - } - - // Copy dockerinit into our current testing directory, if provided (so we can test a separate dockerinit binary) - if dockerinit := os.Getenv("TEST_DOCKERINIT_PATH"); dockerinit != "" { - src, err := os.Open(dockerinit) - if err != nil { - logrus.Fatalf("Unable to open TEST_DOCKERINIT_PATH: %s", err) - } - defer src.Close() - dst, err := os.OpenFile(filepath.Join(filepath.Dir(utils.SelfPath()), "dockerinit"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0555) - if err != nil { - logrus.Fatalf("Unable to create dockerinit in test directory: %s", err) - } - defer dst.Close() - if _, err := io.Copy(dst, src); err != nil { - logrus.Fatalf("Unable to copy dockerinit to TEST_DOCKERINIT_PATH: %s", err) - } - dst.Close() - src.Close() - } - - // Setup the base daemon, which will be duplicated for each test. - // (no tests are run directly in the base) - setupBaseImage() - - // Create the "global daemon" with a long-running daemons for integration tests - spawnGlobalDaemon() - startFds, startGoroutines = fileutils.GetTotalUsedFds(), runtime.NumGoroutine() -} - -func setupBaseImage() { - eng := newTestEngine(std_log.New(os.Stderr, "", 0), false, unitTestStoreBase) - d := getDaemon(eng) - - _, err := d.Repositories().Lookup(unitTestImageName) - // If the unit test is not found, try to download it. - if err != nil { - // seems like we can just ignore the error here... - // there was a check of imgId from job stdout against unittestid but - // if there was an error how could the imgid from the job - // be compared?! it's obvious it's different, am I totally wrong? - - // Retrieve the Image - imagePullConfig := &graph.ImagePullConfig{ - Parallel: true, - OutStream: ioutils.NopWriteCloser(os.Stdout), - AuthConfig: &cliconfig.AuthConfig{}, - } - if err := d.Repositories().Pull(unitTestImageName, "", imagePullConfig); err != nil { - logrus.Fatalf("Unable to pull the test image: %s", err) - } - } -} - -func spawnGlobalDaemon() { - if globalDaemon != nil { - logrus.Debugf("Global daemon already exists. Skipping.") - return - } - t := std_log.New(os.Stderr, "", 0) - eng := NewTestEngine(t) - globalDaemon = mkDaemonFromEngine(eng, t) - - serverConfig := &apiserver.ServerConfig{Logging: true} - api := apiserver.New(serverConfig, eng) - // Spawn a Daemon - go func() { - logrus.Debugf("Spawning global daemon for integration tests") - listenURL := &url.URL{ - Scheme: testDaemonProto, - Host: testDaemonAddr, - } - - if err := api.ServeApi([]string{listenURL.String()}); err != nil { - logrus.Fatalf("Unable to spawn the test daemon: %s", err) - } - }() - - // Give some time to ListenAndServer to actually start - // FIXME: use inmem transports instead of tcp - time.Sleep(time.Second) - - api.AcceptConnections(getDaemon(eng)) -} - -// FIXME: test that ImagePull(json=true) send correct json output - -func GetTestImage(daemon *daemon.Daemon) *image.Image { - imgs, err := daemon.Graph().Map() - if err != nil { - logrus.Fatalf("Unable to get the test image: %s", err) - } - for _, image := range imgs { - if image.ID == unitTestImageID { - return image - } - } - logrus.Fatalf("Test image %v not found in %s: %s", unitTestImageID, daemon.Graph().Root, imgs) - return nil -} - -func TestDaemonCreate(t *testing.T) { - daemon := mkDaemon(t) - defer nuke(daemon) - - // Make sure we start we 0 containers - if len(daemon.List()) != 0 { - t.Errorf("Expected 0 containers, %v found", len(daemon.List())) - } - - container, _, err := daemon.Create(&runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("ls", "-al"), - }, - &runconfig.HostConfig{}, - "", - ) - if err != nil { - t.Fatal(err) - } - - defer func() { - if err := daemon.Rm(container); err != nil { - t.Error(err) - } - }() - - // Make sure we can find the newly created container with List() - if len(daemon.List()) != 1 { - t.Errorf("Expected 1 container, %v found", len(daemon.List())) - } - - // Make sure the container List() returns is the right one - if daemon.List()[0].ID != container.ID { - t.Errorf("Unexpected container %v returned by List", daemon.List()[0]) - } - - // Make sure we can get the container with Get() - if _, err := daemon.Get(container.ID); err != nil { - t.Errorf("Unable to get newly created container") - } - - // Make sure it is the right container - if c, _ := daemon.Get(container.ID); c != container { - t.Errorf("Get() returned the wrong container") - } - - // Make sure Exists returns it as existing - if !daemon.Exists(container.ID) { - t.Errorf("Exists() returned false for a newly created container") - } - - // Test that conflict error displays correct details - cmd := runconfig.NewCommand("ls", "-al") - testContainer, _, _ := daemon.Create( - &runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: cmd, - }, - &runconfig.HostConfig{}, - "conflictname", - ) - if _, _, err := daemon.Create(&runconfig.Config{Image: GetTestImage(daemon).ID, Cmd: cmd}, &runconfig.HostConfig{}, testContainer.Name); err == nil || !strings.Contains(err.Error(), stringid.TruncateID(testContainer.ID)) { - t.Fatalf("Name conflict error doesn't include the correct short id. Message was: %v", err) - } - - // Make sure create with bad parameters returns an error - if _, _, err = daemon.Create(&runconfig.Config{Image: GetTestImage(daemon).ID}, &runconfig.HostConfig{}, ""); err == nil { - t.Fatal("Builder.Create should throw an error when Cmd is missing") - } - - if _, _, err := daemon.Create( - &runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand(), - }, - &runconfig.HostConfig{}, - "", - ); err == nil { - t.Fatal("Builder.Create should throw an error when Cmd is empty") - } - - config := &runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("/bin/ls"), - PortSpecs: []string{"80"}, - } - container, _, err = daemon.Create(config, &runconfig.HostConfig{}, "") - - _, err = daemon.Commit(container, "testrepo", "testtag", "", "", true, config) - if err != nil { - t.Error(err) - } - - // test expose 80:8000 - container, warnings, err := daemon.Create(&runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("ls", "-al"), - PortSpecs: []string{"80:8000"}, - }, - &runconfig.HostConfig{}, - "", - ) - if err != nil { - t.Fatal(err) - } - if warnings == nil || len(warnings) != 1 { - t.Error("Expected a warning, got none") - } -} - -func TestDestroy(t *testing.T) { - daemon := mkDaemon(t) - defer nuke(daemon) - - container, _, err := daemon.Create(&runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("ls", "-al"), - }, - &runconfig.HostConfig{}, - "") - if err != nil { - t.Fatal(err) - } - // Destroy - if err := daemon.Rm(container); err != nil { - t.Error(err) - } - - // Make sure daemon.Exists() behaves correctly - if daemon.Exists("test_destroy") { - t.Errorf("Exists() returned true") - } - - // Make sure daemon.List() doesn't list the destroyed container - if len(daemon.List()) != 0 { - t.Errorf("Expected 0 container, %v found", len(daemon.List())) - } - - // Make sure daemon.Get() refuses to return the unexisting container - if c, _ := daemon.Get(container.ID); c != nil { - t.Errorf("Got a container that should not exist") - } - - // Test double destroy - if err := daemon.Rm(container); err == nil { - // It should have failed - t.Errorf("Double destroy did not fail") - } -} - -func TestGet(t *testing.T) { - daemon := mkDaemon(t) - defer nuke(daemon) - - container1, _, _ := mkContainer(daemon, []string{"_", "ls", "-al"}, t) - defer daemon.Rm(container1) - - container2, _, _ := mkContainer(daemon, []string{"_", "ls", "-al"}, t) - defer daemon.Rm(container2) - - container3, _, _ := mkContainer(daemon, []string{"_", "ls", "-al"}, t) - defer daemon.Rm(container3) - - if c, _ := daemon.Get(container1.ID); c != container1 { - t.Errorf("Get(test1) returned %v while expecting %v", c, container1) - } - - if c, _ := daemon.Get(container2.ID); c != container2 { - t.Errorf("Get(test2) returned %v while expecting %v", c, container2) - } - - if c, _ := daemon.Get(container3.ID); c != container3 { - t.Errorf("Get(test3) returned %v while expecting %v", c, container3) - } - -} - -func startEchoServerContainer(t *testing.T, proto string) (*daemon.Daemon, *daemon.Container, string) { - var ( - err error - id string - strPort string - eng = NewTestEngine(t) - daemon = mkDaemonFromEngine(eng, t) - port = 5554 - p nat.Port - ) - defer func() { - if err != nil { - daemon.Nuke() - } - }() - - for { - port += 1 - strPort = strconv.Itoa(port) - var cmd string - if proto == "tcp" { - cmd = "socat TCP-LISTEN:" + strPort + ",reuseaddr,fork EXEC:/bin/cat" - } else if proto == "udp" { - cmd = "socat UDP-RECVFROM:" + strPort + ",fork EXEC:/bin/cat" - } else { - t.Fatal(fmt.Errorf("Unknown protocol %v", proto)) - } - ep := make(map[nat.Port]struct{}, 1) - p = nat.Port(fmt.Sprintf("%s/%s", strPort, proto)) - ep[p] = struct{}{} - - c := &runconfig.Config{ - Image: unitTestImageID, - Cmd: runconfig.NewCommand("sh", "-c", cmd), - PortSpecs: []string{fmt.Sprintf("%s/%s", strPort, proto)}, - ExposedPorts: ep, - } - - id, _, err = daemon.ContainerCreate(unitTestImageID, c, &runconfig.HostConfig{}) - // FIXME: this relies on the undocumented behavior of daemon.Create - // which will return a nil error AND container if the exposed ports - // are invalid. That behavior should be fixed! - if id != "" { - break - } - t.Logf("Port %v already in use, trying another one", strPort) - - } - - if err := daemon.ContainerStart(id, &runconfig.HostConfig{}); err != nil { - t.Fatal(err) - } - - container, err := daemon.Get(id) - if err != nil { - t.Fatal(err) - } - - setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() { - for !container.IsRunning() { - time.Sleep(10 * time.Millisecond) - } - }) - - // Even if the state is running, lets give some time to lxc to spawn the process - container.WaitStop(500 * time.Millisecond) - - strPort = container.NetworkSettings.Ports[p][0].HostPort - return daemon, container, strPort -} - -// Run a container with a TCP port allocated, and test that it can receive connections on localhost -func TestAllocateTCPPortLocalhost(t *testing.T) { - daemon, container, port := startEchoServerContainer(t, "tcp") - defer nuke(daemon) - defer container.Kill() - - for i := 0; i != 10; i++ { - conn, err := net.Dial("tcp", fmt.Sprintf("localhost:%v", port)) - if err != nil { - t.Fatal(err) - } - defer conn.Close() - - input := bytes.NewBufferString("well hello there\n") - _, err = conn.Write(input.Bytes()) - if err != nil { - t.Fatal(err) - } - buf := make([]byte, 16) - read := 0 - conn.SetReadDeadline(time.Now().Add(3 * time.Second)) - read, err = conn.Read(buf) - if err != nil { - if err, ok := err.(*net.OpError); ok { - if err.Err == syscall.ECONNRESET { - t.Logf("Connection reset by the proxy, socat is probably not listening yet, trying again in a sec") - conn.Close() - time.Sleep(time.Second) - continue - } - if err.Timeout() { - t.Log("Timeout, trying again") - conn.Close() - continue - } - } - t.Fatal(err) - } - output := string(buf[:read]) - if !strings.Contains(output, "well hello there") { - t.Fatal(fmt.Errorf("[%v] doesn't contain [well hello there]", output)) - } else { - return - } - } - - t.Fatal("No reply from the container") -} - -// Run a container with an UDP port allocated, and test that it can receive connections on localhost -func TestAllocateUDPPortLocalhost(t *testing.T) { - daemon, container, port := startEchoServerContainer(t, "udp") - defer nuke(daemon) - defer container.Kill() - - conn, err := net.Dial("udp", fmt.Sprintf("localhost:%v", port)) - if err != nil { - t.Fatal(err) - } - defer conn.Close() - - input := bytes.NewBufferString("well hello there\n") - buf := make([]byte, 16) - // Try for a minute, for some reason the select in socat may take ages - // to return even though everything on the path seems fine (i.e: the - // UDPProxy forwards the traffic correctly and you can see the packets - // on the interface from within the container). - for i := 0; i != 120; i++ { - _, err := conn.Write(input.Bytes()) - if err != nil { - t.Fatal(err) - } - conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) - read, err := conn.Read(buf) - if err == nil { - output := string(buf[:read]) - if strings.Contains(output, "well hello there") { - return - } - } - } - - t.Fatal("No reply from the container") -} - -func TestRestore(t *testing.T) { - eng := NewTestEngine(t) - daemon1 := mkDaemonFromEngine(eng, t) - defer daemon1.Nuke() - // Create a container with one instance of docker - container1, _, _ := mkContainer(daemon1, []string{"_", "ls", "-al"}, t) - defer daemon1.Rm(container1) - - // Create a second container meant to be killed - container2, _, _ := mkContainer(daemon1, []string{"-i", "_", "/bin/cat"}, t) - defer daemon1.Rm(container2) - - // Start the container non blocking - if err := container2.Start(); err != nil { - t.Fatal(err) - } - - if !container2.IsRunning() { - t.Fatalf("Container %v should appear as running but isn't", container2.ID) - } - - // Simulate a crash/manual quit of dockerd: process dies, states stays 'Running' - cStdin := container2.StdinPipe() - cStdin.Close() - if _, err := container2.WaitStop(2 * time.Second); err != nil { - t.Fatal(err) - } - container2.SetRunning(42) - container2.ToDisk() - - if len(daemon1.List()) != 2 { - t.Errorf("Expected 2 container, %v found", len(daemon1.List())) - } - if err := container1.Run(); err != nil { - t.Fatal(err) - } - - if !container2.IsRunning() { - t.Fatalf("Container %v should appear as running but isn't", container2.ID) - } - - // Here are are simulating a docker restart - that is, reloading all containers - // from scratch - eng = newTestEngine(t, false, daemon1.Config().Root) - daemon2 := mkDaemonFromEngine(eng, t) - if len(daemon2.List()) != 2 { - t.Errorf("Expected 2 container, %v found", len(daemon2.List())) - } - runningCount := 0 - for _, c := range daemon2.List() { - if c.IsRunning() { - t.Errorf("Running container found: %v (%v)", c.ID, c.Path) - runningCount++ - } - } - if runningCount != 0 { - t.Fatalf("Expected 0 container alive, %d found", runningCount) - } - container3, err := daemon2.Get(container1.ID) - if err != nil { - t.Fatal("Unable to Get container") - } - if err := container3.Run(); err != nil { - t.Fatal(err) - } - container2.SetStopped(&execdriver.ExitStatus{ExitCode: 0}) -} - -func TestDefaultContainerName(t *testing.T) { - eng := NewTestEngine(t) - daemon := mkDaemonFromEngine(eng, t) - defer nuke(daemon) - - config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}) - if err != nil { - t.Fatal(err) - } - - container, err := daemon.Get(createNamedTestContainer(eng, config, t, "some_name")) - if err != nil { - t.Fatal(err) - } - containerID := container.ID - - if container.Name != "/some_name" { - t.Fatalf("Expect /some_name got %s", container.Name) - } - - c, err := daemon.Get("/some_name") - if err != nil { - t.Fatalf("Couldn't retrieve test container as /some_name") - } - if c.ID != containerID { - t.Fatalf("Container /some_name has ID %s instead of %s", c.ID, containerID) - } -} - -func TestRandomContainerName(t *testing.T) { - eng := NewTestEngine(t) - daemon := mkDaemonFromEngine(eng, t) - defer nuke(daemon) - - config, _, _, err := parseRun([]string{GetTestImage(daemon).ID, "echo test"}) - if err != nil { - t.Fatal(err) - } - - container, err := daemon.Get(createTestContainer(eng, config, t)) - if err != nil { - t.Fatal(err) - } - containerID := container.ID - - if container.Name == "" { - t.Fatalf("Expected not empty container name") - } - - if c, err := daemon.Get(container.Name); err != nil { - logrus.Fatalf("Could not lookup container %s by its name", container.Name) - } else if c.ID != containerID { - logrus.Fatalf("Looking up container name %s returned id %s instead of %s", container.Name, c.ID, containerID) - } -} - -func TestContainerNameValidation(t *testing.T) { - eng := NewTestEngine(t) - daemon := mkDaemonFromEngine(eng, t) - defer nuke(daemon) - - for _, test := range []struct { - Name string - Valid bool - }{ - {"abc-123_AAA.1", true}, - {"\000asdf", false}, - } { - config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}) - if err != nil { - if !test.Valid { - continue - } - t.Fatal(err) - } - - containerId, _, err := daemon.ContainerCreate(test.Name, config, &runconfig.HostConfig{}) - if err != nil { - if !test.Valid { - continue - } - t.Fatal(err) - } - - container, err := daemon.Get(containerId) - if err != nil { - t.Fatal(err) - } - - if container.Name != "/"+test.Name { - t.Fatalf("Expect /%s got %s", test.Name, container.Name) - } - - if c, err := daemon.Get("/" + test.Name); err != nil { - t.Fatalf("Couldn't retrieve test container as /%s", test.Name) - } else if c.ID != container.ID { - t.Fatalf("Container /%s has ID %s instead of %s", test.Name, c.ID, container.ID) - } - } -} - -func TestLinkChildContainer(t *testing.T) { - eng := NewTestEngine(t) - daemon := mkDaemonFromEngine(eng, t) - defer nuke(daemon) - - config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}) - if err != nil { - t.Fatal(err) - } - - container, err := daemon.Get(createNamedTestContainer(eng, config, t, "/webapp")) - if err != nil { - t.Fatal(err) - } - - webapp, err := daemon.GetByName("/webapp") - if err != nil { - t.Fatal(err) - } - - if webapp.ID != container.ID { - t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID) - } - - config, _, _, err = parseRun([]string{GetTestImage(daemon).ID, "echo test"}) - if err != nil { - t.Fatal(err) - } - - childContainer, err := daemon.Get(createTestContainer(eng, config, t)) - if err != nil { - t.Fatal(err) - } - - if err := daemon.RegisterLink(webapp, childContainer, "db"); err != nil { - t.Fatal(err) - } - - // Get the child by it's new name - db, err := daemon.GetByName("/webapp/db") - if err != nil { - t.Fatal(err) - } - if db.ID != childContainer.ID { - t.Fatalf("Expect db id to match container id: %s != %s", db.ID, childContainer.ID) - } -} - -func TestGetAllChildren(t *testing.T) { - eng := NewTestEngine(t) - daemon := mkDaemonFromEngine(eng, t) - defer nuke(daemon) - - config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}) - if err != nil { - t.Fatal(err) - } - - container, err := daemon.Get(createNamedTestContainer(eng, config, t, "/webapp")) - if err != nil { - t.Fatal(err) - } - - webapp, err := daemon.GetByName("/webapp") - if err != nil { - t.Fatal(err) - } - - if webapp.ID != container.ID { - t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID) - } - - config, _, _, err = parseRun([]string{unitTestImageID, "echo test"}) - if err != nil { - t.Fatal(err) - } - - childContainer, err := daemon.Get(createTestContainer(eng, config, t)) - if err != nil { - t.Fatal(err) - } - - if err := daemon.RegisterLink(webapp, childContainer, "db"); err != nil { - t.Fatal(err) - } - - children, err := daemon.Children("/webapp") - if err != nil { - t.Fatal(err) - } - - if children == nil { - t.Fatal("Children should not be nil") - } - if len(children) == 0 { - t.Fatal("Children should not be empty") - } - - for key, value := range children { - if key != "/webapp/db" { - t.Fatalf("Expected /webapp/db got %s", key) - } - if value.ID != childContainer.ID { - t.Fatalf("Expected id %s got %s", childContainer.ID, value.ID) - } - } -} - -func TestDestroyWithInitLayer(t *testing.T) { - daemon := mkDaemon(t) - defer nuke(daemon) - - container, _, err := daemon.Create(&runconfig.Config{ - Image: GetTestImage(daemon).ID, - Cmd: runconfig.NewCommand("ls", "-al"), - }, - &runconfig.HostConfig{}, - "") - - if err != nil { - t.Fatal(err) - } - // Destroy - if err := daemon.Rm(container); err != nil { - t.Fatal(err) - } - - // Make sure daemon.Exists() behaves correctly - if daemon.Exists("test_destroy") { - t.Fatalf("Exists() returned true") - } - - // Make sure daemon.List() doesn't list the destroyed container - if len(daemon.List()) != 0 { - t.Fatalf("Expected 0 container, %v found", len(daemon.List())) - } - - driver := daemon.Graph().Driver() - - // Make sure that the container does not exist in the driver - if _, err := driver.Get(container.ID, ""); err == nil { - t.Fatal("Container should not exist in the driver") - } - - // Make sure that the init layer is removed from the driver - if _, err := driver.Get(fmt.Sprintf("%s-init", container.ID), ""); err == nil { - t.Fatal("Container's init layer should not exist in the driver") - } -} diff --git a/integration/utils.go b/integration/utils.go deleted file mode 100644 index 62e02e9bb1..0000000000 --- a/integration/utils.go +++ /dev/null @@ -1,88 +0,0 @@ -package docker - -import ( - "bufio" - "fmt" - "io" - "strings" - "testing" - "time" - - "github.com/docker/docker/daemon" -) - -func closeWrap(args ...io.Closer) error { - e := false - ret := fmt.Errorf("Error closing elements") - for _, c := range args { - if err := c.Close(); err != nil { - e = true - ret = fmt.Errorf("%s\n%s", ret, err) - } - } - if e { - return ret - } - return nil -} - -func waitContainerStart(t *testing.T, timeout time.Duration) *daemon.Container { - var container *daemon.Container - - setTimeout(t, "Waiting for the container to be started timed out", timeout, func() { - for { - l := globalDaemon.List() - if len(l) == 1 && l[0].IsRunning() { - container = l[0] - break - } - time.Sleep(10 * time.Millisecond) - } - }) - - if container == nil { - t.Fatal("An error occurred while waiting for the container to start") - } - - return container -} - -func setTimeout(t *testing.T, msg string, d time.Duration, f func()) { - c := make(chan bool) - - // Make sure we are not too long - go func() { - time.Sleep(d) - c <- true - }() - go func() { - f() - c <- false - }() - if <-c && msg != "" { - t.Fatal(msg) - } -} - -func expectPipe(expected string, r io.Reader) error { - o, err := bufio.NewReader(r).ReadString('\n') - if err != nil { - return err - } - if strings.Trim(o, " \r\n") != expected { - return fmt.Errorf("Unexpected output. Expected [%s], received [%s]", expected, o) - } - return nil -} - -func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error { - for i := 0; i < count; i++ { - if _, err := w.Write([]byte(input)); err != nil { - return err - } - if err := expectPipe(output, r); err != nil { - return err - } - } - return nil -} diff --git a/integration/utils_test.go b/integration/utils_test.go deleted file mode 100644 index 9479d4296c..0000000000 --- a/integration/utils_test.go +++ /dev/null @@ -1,348 +0,0 @@ -package docker - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "os" - "path" - "path/filepath" - "strings" - "testing" - "time" - - "github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/daemon" - "github.com/docker/docker/daemon/networkdriver/bridge" - "github.com/docker/docker/engine" - "github.com/docker/docker/graph" - flag "github.com/docker/docker/pkg/mflag" - "github.com/docker/docker/registry" - "github.com/docker/docker/runconfig" - "github.com/docker/docker/utils" -) - -type Fataler interface { - Fatal(...interface{}) -} - -// This file contains utility functions for docker's unit test suite. -// It has to be named XXX_test.go, apparently, in other to access private functions -// from other XXX_test.go functions. - -// Create a temporary daemon suitable for unit testing. -// Call t.Fatal() at the first error. -func mkDaemon(f Fataler) *daemon.Daemon { - eng := newTestEngine(f, false, "") - return mkDaemonFromEngine(eng, f) -} - -func createNamedTestContainer(eng *engine.Engine, config *runconfig.Config, f Fataler, name string) (shortId string) { - containerId, _, err := getDaemon(eng).ContainerCreate(name, config, &runconfig.HostConfig{}) - if err != nil { - f.Fatal(err) - } - return containerId -} - -func createTestContainer(eng *engine.Engine, config *runconfig.Config, f Fataler) (shortId string) { - return createNamedTestContainer(eng, config, f, "") -} - -func startContainer(eng *engine.Engine, id string, t Fataler) { - if err := getDaemon(eng).ContainerStart(id, &runconfig.HostConfig{}); err != nil { - t.Fatal(err) - } -} - -func containerRun(eng *engine.Engine, id string, t Fataler) { - startContainer(eng, id, t) - containerWait(eng, id, t) -} - -func containerFileExists(eng *engine.Engine, id, dir string, t Fataler) bool { - c := getContainer(eng, id, t) - if err := c.Mount(); err != nil { - t.Fatal(err) - } - defer c.Unmount() - if _, err := os.Stat(path.Join(c.RootfsPath(), dir)); err != nil { - if os.IsNotExist(err) { - return false - } - t.Fatal(err) - } - return true -} - -func containerAttach(eng *engine.Engine, id string, t Fataler) (io.WriteCloser, io.ReadCloser) { - c := getContainer(eng, id, t) - i := c.StdinPipe() - o := c.StdoutPipe() - return i, o -} - -func containerWait(eng *engine.Engine, id string, t Fataler) int { - ex, _ := getContainer(eng, id, t).WaitStop(-1 * time.Second) - return ex -} - -func containerWaitTimeout(eng *engine.Engine, id string, t Fataler) error { - _, err := getContainer(eng, id, t).WaitStop(500 * time.Millisecond) - return err -} - -func containerKill(eng *engine.Engine, id string, t Fataler) { - if err := getDaemon(eng).ContainerKill(id, 0); err != nil { - t.Fatal(err) - } -} - -func containerRunning(eng *engine.Engine, id string, t Fataler) bool { - return getContainer(eng, id, t).IsRunning() -} - -func containerAssertExists(eng *engine.Engine, id string, t Fataler) { - getContainer(eng, id, t) -} - -func containerAssertNotExists(eng *engine.Engine, id string, t Fataler) { - daemon := mkDaemonFromEngine(eng, t) - if c, _ := daemon.Get(id); c != nil { - t.Fatal(fmt.Errorf("Container %s should not exist", id)) - } -} - -// assertHttpNotError expect the given response to not have an error. -// Otherwise the it causes the test to fail. -func assertHttpNotError(r *httptest.ResponseRecorder, t Fataler) { - // Non-error http status are [200, 400) - if r.Code < http.StatusOK || r.Code >= http.StatusBadRequest { - t.Fatal(fmt.Errorf("Unexpected http error: %v", r.Code)) - } -} - -// assertHttpError expect the given response to have an error. -// Otherwise the it causes the test to fail. -func assertHttpError(r *httptest.ResponseRecorder, t Fataler) { - // Non-error http status are [200, 400) - if !(r.Code < http.StatusOK || r.Code >= http.StatusBadRequest) { - t.Fatal(fmt.Errorf("Unexpected http success code: %v", r.Code)) - } -} - -func getContainer(eng *engine.Engine, id string, t Fataler) *daemon.Container { - daemon := mkDaemonFromEngine(eng, t) - c, err := daemon.Get(id) - if err != nil { - t.Fatal(err) - } - return c -} - -func mkDaemonFromEngine(eng *engine.Engine, t Fataler) *daemon.Daemon { - iDaemon := eng.HackGetGlobalVar("httpapi.daemon") - if iDaemon == nil { - panic("Legacy daemon field not set in engine") - } - daemon, ok := iDaemon.(*daemon.Daemon) - if !ok { - panic("Legacy daemon field in engine does not cast to *daemon.Daemon") - } - return daemon -} - -func newTestEngine(t Fataler, autorestart bool, root string) *engine.Engine { - if root == "" { - if dir, err := newTestDirectory(unitTestStoreBase); err != nil { - t.Fatal(err) - } else { - root = dir - } - } - os.MkdirAll(root, 0700) - - eng := engine.New() - eng.Logging = false - - // (This is manually copied and modified from main() until we have a more generic plugin system) - cfg := &daemon.Config{ - Root: root, - AutoRestart: autorestart, - ExecDriver: "native", - // Either InterContainerCommunication or EnableIptables must be set, - // otherwise NewDaemon will fail because of conflicting settings. - Bridge: bridge.Config{ - InterContainerCommunication: true, - }, - TrustKeyPath: filepath.Join(root, "key.json"), - LogConfig: runconfig.LogConfig{Type: "json-file"}, - } - d, err := daemon.NewDaemon(cfg, eng, registry.NewService(nil)) - if err != nil { - t.Fatal(err) - } - if err := d.Install(eng); err != nil { - t.Fatal(err) - } - return eng -} - -func NewTestEngine(t Fataler) *engine.Engine { - return newTestEngine(t, false, "") -} - -func newTestDirectory(templateDir string) (dir string, err error) { - return utils.TestDirectory(templateDir) -} - -func getCallerName(depth int) string { - return utils.GetCallerName(depth) -} - -// Write `content` to the file at path `dst`, creating it if necessary, -// as well as any missing directories. -// The file is truncated if it already exists. -// Call t.Fatal() at the first error. -func writeFile(dst, content string, t *testing.T) { - // Create subdirectories if necessary - if err := os.MkdirAll(path.Dir(dst), 0700); err != nil && !os.IsExist(err) { - t.Fatal(err) - } - f, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0700) - if err != nil { - t.Fatal(err) - } - // Write content (truncate if it exists) - if _, err := io.Copy(f, strings.NewReader(content)); err != nil { - t.Fatal(err) - } -} - -// Return the contents of file at path `src`. -// Call t.Fatal() at the first error (including if the file doesn't exist) -func readFile(src string, t *testing.T) (content string) { - f, err := os.Open(src) - if err != nil { - t.Fatal(err) - } - data, err := ioutil.ReadAll(f) - if err != nil { - t.Fatal(err) - } - return string(data) -} - -// Create a test container from the given daemon `r` and run arguments `args`. -// If the image name is "_", (eg. []string{"-i", "-t", "_", "bash"}, it is -// dynamically replaced by the current test image. -// The caller is responsible for destroying the container. -// Call t.Fatal() at the first error. -func mkContainer(r *daemon.Daemon, args []string, t *testing.T) (*daemon.Container, *runconfig.HostConfig, error) { - config, hc, _, err := parseRun(args) - defer func() { - if err != nil && t != nil { - t.Fatal(err) - } - }() - if err != nil { - return nil, nil, err - } - if config.Image == "_" { - config.Image = GetTestImage(r).ID - } - c, _, err := r.Create(config, nil, "") - if err != nil { - return nil, nil, err - } - // NOTE: hostConfig is ignored. - // If `args` specify privileged mode, custom lxc conf, external mount binds, - // port redirects etc. they will be ignored. - // This is because the correct way to set these things is to pass environment - // to the `start` job. - // FIXME: this helper function should be deprecated in favor of calling - // `create` and `start` jobs directly. - return c, hc, nil -} - -// Create a test container, start it, wait for it to complete, destroy it, -// and return its standard output as a string. -// The image name (eg. the XXX in []string{"-i", "-t", "XXX", "bash"}, is dynamically replaced by the current test image. -// If t is not nil, call t.Fatal() at the first error. Otherwise return errors normally. -func runContainer(eng *engine.Engine, r *daemon.Daemon, args []string, t *testing.T) (output string, err error) { - defer func() { - if err != nil && t != nil { - t.Fatal(err) - } - }() - container, hc, err := mkContainer(r, args, t) - if err != nil { - return "", err - } - defer r.Rm(container) - stdout := container.StdoutPipe() - defer stdout.Close() - - job := eng.Job("start", container.ID) - if err := job.ImportEnv(hc); err != nil { - return "", err - } - if err := job.Run(); err != nil { - return "", err - } - - container.WaitStop(-1 * time.Second) - data, err := ioutil.ReadAll(stdout) - if err != nil { - return "", err - } - output = string(data) - return -} - -// FIXME: this is duplicated from graph_test.go in the docker package. -func fakeTar() (io.ReadCloser, error) { - content := []byte("Hello world!\n") - buf := new(bytes.Buffer) - tw := tar.NewWriter(buf) - for _, name := range []string{"/etc/postgres/postgres.conf", "/etc/passwd", "/var/log/postgres/postgres.conf"} { - hdr := new(tar.Header) - hdr.Size = int64(len(content)) - hdr.Name = name - if err := tw.WriteHeader(hdr); err != nil { - return nil, err - } - tw.Write([]byte(content)) - } - tw.Close() - return ioutil.NopCloser(buf), nil -} - -func getImages(eng *engine.Engine, t *testing.T, all bool, filter string) []*types.Image { - config := graph.ImagesConfig{ - Filter: filter, - All: all, - } - images, err := getDaemon(eng).Repositories().Images(&config) - if err != nil { - t.Fatal(err) - } - - return images -} - -func parseRun(args []string) (*runconfig.Config, *runconfig.HostConfig, *flag.FlagSet, error) { - cmd := flag.NewFlagSet("run", flag.ContinueOnError) - cmd.SetOutput(ioutil.Discard) - cmd.Usage = nil - return runconfig.Parse(cmd, args) -} - -func getDaemon(eng *engine.Engine) *daemon.Daemon { - return eng.HackGetGlobalVar("httpapi.daemon").(*daemon.Daemon) -} diff --git a/integration/z_final_test.go b/integration/z_final_test.go deleted file mode 100644 index d6ef2884f2..0000000000 --- a/integration/z_final_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package docker - -import ( - "runtime" - "testing" - - "github.com/docker/docker/pkg/fileutils" -) - -func displayFdGoroutines(t *testing.T) { - t.Logf("File Descriptors: %d, Goroutines: %d", fileutils.GetTotalUsedFds(), runtime.NumGoroutine()) -} - -func TestFinal(t *testing.T) { - nuke(globalDaemon) - t.Logf("Start File Descriptors: %d, Start Goroutines: %d", startFds, startGoroutines) - displayFdGoroutines(t) -}