Merge pull request #12511 from LK4D4/gocheck_suites

Gocheck suites
This commit is contained in:
Arnaud Porterie 2015-04-21 15:42:33 -07:00
commit 61854b171d
81 changed files with 8461 additions and 4807 deletions

View file

@ -57,6 +57,8 @@ clone git github.com/Sirupsen/logrus v0.7.2
clone git github.com/go-fsnotify/fsnotify v1.0.4
clone git github.com/go-check/check 64131543e7896d5bcc6bd5a76287eb75ea96c673
# get Go tip's archive/tar, for xattr support and improved performance
# TODO after Go 1.4 drops, bump our minimum supported version and drop this vendored dep
if [ "$1" = '--go' ]; then

View file

@ -0,0 +1,34 @@
package main
import (
"fmt"
"testing"
"time"
"github.com/go-check/check"
)
func Test(t *testing.T) { check.TestingT(t) }
type TimerSuite struct {
start time.Time
}
func (s *TimerSuite) SetUpTest(c *check.C) {
s.start = time.Now()
}
func (s *TimerSuite) TearDownTest(c *check.C) {
fmt.Printf("%-60s%.2f\n", c.TestName(), time.Since(s.start).Seconds())
}
type DockerSuite struct {
TimerSuite
}
func (s *DockerSuite) TearDownTest(c *check.C) {
deleteAllContainers()
s.TimerSuite.TearDownTest(c)
}
var _ = check.Suite(&DockerSuite{})

View file

@ -4,23 +4,23 @@ import (
"bytes"
"os/exec"
"strings"
"testing"
"time"
"github.com/go-check/check"
"code.google.com/p/go.net/websocket"
)
func TestGetContainersAttachWebsocket(t *testing.T) {
func (s *DockerSuite) TestGetContainersAttachWebsocket(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-dit", "busybox", "cat")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
rwc, err := sockConn(time.Duration(10 * time.Second))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -29,12 +29,12 @@ func TestGetContainersAttachWebsocket(t *testing.T) {
"http://localhost",
)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
ws, err := websocket.NewClient(config, rwc)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer ws.Close()
@ -43,7 +43,7 @@ func TestGetContainersAttachWebsocket(t *testing.T) {
outChan := make(chan string)
go func() {
if _, err := ws.Read(actual); err != nil {
t.Fatal(err)
c.Fatal(err)
}
outChan <- "done"
}()
@ -51,7 +51,7 @@ func TestGetContainersAttachWebsocket(t *testing.T) {
inChan := make(chan string)
go func() {
if _, err := ws.Write(expected); err != nil {
t.Fatal(err)
c.Fatal(err)
}
inChan <- "done"
}()
@ -60,8 +60,6 @@ func TestGetContainersAttachWebsocket(t *testing.T) {
<-outChan
if !bytes.Equal(expected, actual) {
t.Fatal("Expected output on websocket to match input")
c.Fatal("Expected output on websocket to match input")
}
logDone("container attach websocket - can echo input via cat")
}

View file

@ -7,65 +7,59 @@ import (
"net/http"
"os/exec"
"strings"
"testing"
"time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
"github.com/go-check/check"
)
func TestContainerApiGetAll(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiGetAll(c *check.C) {
startCount, err := getContainerCount()
if err != nil {
t.Fatalf("Cannot query container count: %v", err)
c.Fatalf("Cannot query container count: %v", err)
}
name := "getall"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
_, body, err := sockRequest("GET", "/containers/json?all=1", nil)
if err != nil {
t.Fatalf("GET all containers sockRequest failed: %v", err)
c.Fatalf("GET all containers sockRequest failed: %v", err)
}
var inspectJSON []struct {
Names []string
}
if err = json.Unmarshal(body, &inspectJSON); err != nil {
t.Fatalf("unable to unmarshal response body: %v", err)
c.Fatalf("unable to unmarshal response body: %v", err)
}
if len(inspectJSON) != startCount+1 {
t.Fatalf("Expected %d container(s), %d found (started with: %d)", startCount+1, len(inspectJSON), startCount)
c.Fatalf("Expected %d container(s), %d found (started with: %d)", startCount+1, len(inspectJSON), startCount)
}
if actual := inspectJSON[0].Names[0]; actual != "/"+name {
t.Fatalf("Container Name mismatch. Expected: %q, received: %q\n", "/"+name, actual)
c.Fatalf("Container Name mismatch. Expected: %q, received: %q\n", "/"+name, actual)
}
logDone("container REST API - check GET json/all=1")
}
func TestContainerApiGetExport(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiGetExport(c *check.C) {
name := "exportcontainer"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
_, body, err := sockRequest("GET", "/containers/"+name+"/export", nil)
if err != nil {
t.Fatalf("GET containers/export sockRequest failed: %v", err)
c.Fatalf("GET containers/export sockRequest failed: %v", err)
}
found := false
@ -75,7 +69,7 @@ func TestContainerApiGetExport(t *testing.T) {
if err == io.EOF {
break
}
t.Fatal(err)
c.Fatal(err)
}
if h.Name == "test" {
found = true
@ -84,25 +78,21 @@ func TestContainerApiGetExport(t *testing.T) {
}
if !found {
t.Fatalf("The created test file has not been found in the exported image")
c.Fatalf("The created test file has not been found in the exported image")
}
logDone("container REST API - check GET containers/export")
}
func TestContainerApiGetChanges(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiGetChanges(c *check.C) {
name := "changescontainer"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "rm", "/etc/passwd")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
_, body, err := sockRequest("GET", "/containers/"+name+"/changes", nil)
if err != nil {
t.Fatalf("GET containers/changes sockRequest failed: %v", err)
c.Fatalf("GET containers/changes sockRequest failed: %v", err)
}
changes := []struct {
@ -110,7 +100,7 @@ func TestContainerApiGetChanges(t *testing.T) {
Path string
}{}
if err = json.Unmarshal(body, &changes); err != nil {
t.Fatalf("unable to unmarshal response body: %v", err)
c.Fatalf("unable to unmarshal response body: %v", err)
}
// Check the changelog for removal of /etc/passwd
@ -121,14 +111,11 @@ func TestContainerApiGetChanges(t *testing.T) {
}
}
if !success {
t.Fatalf("/etc/passwd has been removed but is not present in the diff")
c.Fatalf("/etc/passwd has been removed but is not present in the diff")
}
logDone("container REST API - check GET containers/changes")
}
func TestContainerApiStartVolumeBinds(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiStartVolumeBinds(c *check.C) {
name := "testing"
config := map[string]interface{}{
"Image": "busybox",
@ -136,7 +123,7 @@ func TestContainerApiStartVolumeBinds(t *testing.T) {
}
if status, _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && status != http.StatusCreated {
t.Fatal(err)
c.Fatal(err)
}
bindPath := randomUnixTmpDirPath("test")
@ -144,24 +131,21 @@ func TestContainerApiStartVolumeBinds(t *testing.T) {
"Binds": []string{bindPath + ":/tmp"},
}
if status, _, err := sockRequest("POST", "/containers/"+name+"/start", config); err != nil && status != http.StatusNoContent {
t.Fatal(err)
c.Fatal(err)
}
pth, err := inspectFieldMap(name, "Volumes", "/tmp")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if pth != bindPath {
t.Fatalf("expected volume host path to be %s, got %s", bindPath, pth)
c.Fatalf("expected volume host path to be %s, got %s", bindPath, pth)
}
logDone("container REST API - check volume binds on start")
}
// Test for GH#10618
func TestContainerApiStartDupVolumeBinds(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiStartDupVolumeBinds(c *check.C) {
name := "testdups"
config := map[string]interface{}{
"Image": "busybox",
@ -169,7 +153,7 @@ func TestContainerApiStartDupVolumeBinds(t *testing.T) {
}
if status, _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && status != http.StatusCreated {
t.Fatal(err)
c.Fatal(err)
}
bindPath1 := randomUnixTmpDirPath("test1")
@ -179,22 +163,19 @@ func TestContainerApiStartDupVolumeBinds(t *testing.T) {
"Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"},
}
if _, body, err := sockRequest("POST", "/containers/"+name+"/start", config); err == nil {
t.Fatal("expected container start to fail when duplicate volume binds to same container path")
c.Fatal("expected container start to fail when duplicate volume binds to same container path")
} else {
if !strings.Contains(string(body), "Duplicate volume") {
t.Fatalf("Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(body), err)
c.Fatalf("Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(body), err)
}
}
logDone("container REST API - check for duplicate volume binds error on start")
}
func TestContainerApiStartVolumesFrom(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiStartVolumesFrom(c *check.C) {
volName := "voltst"
volPath := "/tmp"
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", volName, "-v", volPath, "busybox")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
name := "testing"
@ -204,41 +185,38 @@ func TestContainerApiStartVolumesFrom(t *testing.T) {
}
if status, _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && status != http.StatusCreated {
t.Fatal(err)
c.Fatal(err)
}
config = map[string]interface{}{
"VolumesFrom": []string{volName},
}
if status, _, err := sockRequest("POST", "/containers/"+name+"/start", config); err != nil && status != http.StatusNoContent {
t.Fatal(err)
c.Fatal(err)
}
pth, err := inspectFieldMap(name, "Volumes", volPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
pth2, err := inspectFieldMap(volName, "Volumes", volPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if pth != pth2 {
t.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
c.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
}
logDone("container REST API - check VolumesFrom on start")
}
// Ensure that volumes-from has priority over binds/anything else
// This is pretty much the same as TestRunApplyVolumesFromBeforeVolumes, except with passing the VolumesFrom and the bind on start
func TestVolumesFromHasPriority(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestVolumesFromHasPriority(c *check.C) {
volName := "voltst2"
volPath := "/tmp"
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", volName, "-v", volPath, "busybox")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
name := "testing"
@ -248,7 +226,7 @@ func TestVolumesFromHasPriority(t *testing.T) {
}
if status, _, err := sockRequest("POST", "/containers/create?name="+name, config); err != nil && status != http.StatusCreated {
t.Fatal(err)
c.Fatal(err)
}
bindPath := randomUnixTmpDirPath("test")
@ -257,34 +235,31 @@ func TestVolumesFromHasPriority(t *testing.T) {
"Binds": []string{bindPath + ":/tmp"},
}
if status, _, err := sockRequest("POST", "/containers/"+name+"/start", config); err != nil && status != http.StatusNoContent {
t.Fatal(err)
c.Fatal(err)
}
pth, err := inspectFieldMap(name, "Volumes", volPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
pth2, err := inspectFieldMap(volName, "Volumes", volPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if pth != pth2 {
t.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
c.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
}
logDone("container REST API - check VolumesFrom has priority")
}
func TestGetContainerStats(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestGetContainerStats(c *check.C) {
var (
name = "statscontainer"
runCmd = exec.Command(dockerBinary, "run", "-d", "--name", name, "busybox", "top")
)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
type b struct {
body []byte
@ -299,38 +274,36 @@ func TestGetContainerStats(t *testing.T) {
// allow some time to stream the stats from the container
time.Sleep(4 * time.Second)
if _, err := runCommand(exec.Command(dockerBinary, "rm", "-f", name)); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// collect the results from the stats stream or timeout and fail
// if the stream was not disconnected.
select {
case <-time.After(2 * time.Second):
t.Fatal("stream was not closed after container was removed")
c.Fatal("stream was not closed after container was removed")
case sr := <-bc:
if sr.err != nil {
t.Fatal(sr.err)
c.Fatal(sr.err)
}
dec := json.NewDecoder(bytes.NewBuffer(sr.body))
var s *types.Stats
// decode only one object from the stream
if err := dec.Decode(&s); err != nil {
t.Fatal(err)
c.Fatal(err)
}
}
logDone("container REST API - check GET containers/stats")
}
func TestGetStoppedContainerStats(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestGetStoppedContainerStats(c *check.C) {
var (
name = "statscontainer"
runCmd = exec.Command(dockerBinary, "create", "--name", name, "busybox", "top")
)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("Error on container creation: %v, output: %q", err, out)
c.Fatalf("Error on container creation: %v, output: %q", err, out)
}
go func() {
@ -338,17 +311,15 @@ func TestGetStoppedContainerStats(t *testing.T) {
// just send request and see if panic or error would happen on daemon side.
_, _, err := sockRequest("GET", "/containers/"+name+"/stats", nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
}()
// allow some time to send request and let daemon deal with it
time.Sleep(1 * time.Second)
logDone("container REST API - check GET stopped containers/stats")
}
func TestBuildApiDockerfilePath(t *testing.T) {
func (s *DockerSuite) TestBuildApiDockerfilePath(c *check.C) {
// Test to make sure we stop people from trying to leave the
// build context when specifying the path to the dockerfile
buffer := new(bytes.Buffer)
@ -360,33 +331,31 @@ func TestBuildApiDockerfilePath(t *testing.T) {
Name: "Dockerfile",
Size: int64(len(dockerfile)),
}); err != nil {
t.Fatalf("failed to write tar file header: %v", err)
c.Fatalf("failed to write tar file header: %v", err)
}
if _, err := tw.Write(dockerfile); err != nil {
t.Fatalf("failed to write tar file content: %v", err)
c.Fatalf("failed to write tar file content: %v", err)
}
if err := tw.Close(); err != nil {
t.Fatalf("failed to close tar archive: %v", err)
c.Fatalf("failed to close tar archive: %v", err)
}
_, body, err := sockRequestRaw("POST", "/build?dockerfile=../Dockerfile", buffer, "application/x-tar")
if err == nil {
out, _ := readBody(body)
t.Fatalf("Build was supposed to fail: %s", out)
c.Fatalf("Build was supposed to fail: %s", out)
}
out, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !strings.Contains(string(out), "must be within the build context") {
t.Fatalf("Didn't complain about leaving build context: %s", out)
c.Fatalf("Didn't complain about leaving build context: %s", out)
}
logDone("container REST API - check build w/bad Dockerfile path")
}
func TestBuildApiDockerFileRemote(t *testing.T) {
func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) {
server, err := fakeStorage(map[string]string{
"testD": `FROM busybox
COPY * /tmp/
@ -394,17 +363,17 @@ RUN find / -name ba*
RUN find /tmp/`,
})
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer server.Close()
_, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json")
if err != nil {
t.Fatalf("Build failed: %s", err)
c.Fatalf("Build failed: %s", err)
}
buf, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// Make sure Dockerfile exists.
@ -412,41 +381,37 @@ RUN find /tmp/`,
out := string(buf)
if !strings.Contains(out, "/tmp/Dockerfile") ||
strings.Contains(out, "baz") {
t.Fatalf("Incorrect output: %s", out)
c.Fatalf("Incorrect output: %s", out)
}
logDone("container REST API - check build with -f from remote")
}
func TestBuildApiLowerDockerfile(t *testing.T) {
func (s *DockerSuite) TestBuildApiLowerDockerfile(c *check.C) {
git, err := fakeGIT("repo", map[string]string{
"dockerfile": `FROM busybox
RUN echo from dockerfile`,
}, false)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer git.Close()
_, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
if err != nil {
buf, _ := readBody(body)
t.Fatalf("Build failed: %s\n%q", err, buf)
c.Fatalf("Build failed: %s\n%q", err, buf)
}
buf, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out := string(buf)
if !strings.Contains(out, "from dockerfile") {
t.Fatalf("Incorrect output: %s", out)
c.Fatalf("Incorrect output: %s", out)
}
logDone("container REST API - check build with lower dockerfile")
}
func TestBuildApiBuildGitWithF(t *testing.T) {
func (s *DockerSuite) TestBuildApiBuildGitWithF(c *check.C) {
git, err := fakeGIT("repo", map[string]string{
"baz": `FROM busybox
RUN echo from baz`,
@ -454,7 +419,7 @@ RUN echo from baz`,
RUN echo from Dockerfile`,
}, false)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer git.Close()
@ -462,23 +427,21 @@ RUN echo from Dockerfile`,
_, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+git.RepoURL, nil, "application/json")
if err != nil {
buf, _ := readBody(body)
t.Fatalf("Build failed: %s\n%q", err, buf)
c.Fatalf("Build failed: %s\n%q", err, buf)
}
buf, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out := string(buf)
if !strings.Contains(out, "from baz") {
t.Fatalf("Incorrect output: %s", out)
c.Fatalf("Incorrect output: %s", out)
}
logDone("container REST API - check build from git w/F")
}
func TestBuildApiDoubleDockerfile(t *testing.T) {
testRequires(t, UnixCli) // dockerfile overwrites Dockerfile on Windows
func (s *DockerSuite) TestBuildApiDoubleDockerfile(c *check.C) {
testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows
git, err := fakeGIT("repo", map[string]string{
"Dockerfile": `FROM busybox
RUN echo from Dockerfile`,
@ -486,29 +449,27 @@ RUN echo from Dockerfile`,
RUN echo from dockerfile`,
}, false)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer git.Close()
// Make sure it tries to 'dockerfile' query param value
_, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
if err != nil {
t.Fatalf("Build failed: %s", err)
c.Fatalf("Build failed: %s", err)
}
buf, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out := string(buf)
if !strings.Contains(out, "from Dockerfile") {
t.Fatalf("Incorrect output: %s", out)
c.Fatalf("Incorrect output: %s", out)
}
logDone("container REST API - check build with two dockerfiles")
}
func TestBuildApiDockerfileSymlink(t *testing.T) {
func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
// Test to make sure we stop people from trying to leave the
// build context when specifying a symlink as the path to the dockerfile
buffer := new(bytes.Buffer)
@ -520,20 +481,20 @@ func TestBuildApiDockerfileSymlink(t *testing.T) {
Typeflag: tar.TypeSymlink,
Linkname: "/etc/passwd",
}); err != nil {
t.Fatalf("failed to write tar file header: %v", err)
c.Fatalf("failed to write tar file header: %v", err)
}
if err := tw.Close(); err != nil {
t.Fatalf("failed to close tar archive: %v", err)
c.Fatalf("failed to close tar archive: %v", err)
}
_, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
if err == nil {
out, _ := readBody(body)
t.Fatalf("Build was supposed to fail: %s", out)
c.Fatalf("Build was supposed to fail: %s", out)
}
out, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// The reason the error is "Cannot locate specified Dockerfile" is because
@ -541,96 +502,89 @@ func TestBuildApiDockerfileSymlink(t *testing.T) {
// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
// a nonexistent file.
if !strings.Contains(string(out), "Cannot locate specified Dockerfile: Dockerfile") {
t.Fatalf("Didn't complain about leaving build context: %s", out)
c.Fatalf("Didn't complain about leaving build context: %s", out)
}
logDone("container REST API - check build w/bad Dockerfile symlink path")
}
// #9981 - Allow a docker created volume (ie, one in /var/lib/docker/volumes) to be used to overwrite (via passing in Binds on api start) an existing volume
func TestPostContainerBindNormalVolume(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPostContainerBindNormalVolume(c *check.C) {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "-v", "/foo", "--name=one", "busybox"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
fooDir, err := inspectFieldMap("one", "Volumes", "/foo")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "create", "-v", "/foo", "--name=two", "busybox"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}}
if status, _, err := sockRequest("POST", "/containers/two/start", bindSpec); err != nil && status != http.StatusNoContent {
t.Fatal(err)
c.Fatal(err)
}
fooDir2, err := inspectFieldMap("two", "Volumes", "/foo")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if fooDir2 != fooDir {
t.Fatalf("expected volume path to be %s, got: %s", fooDir, fooDir2)
c.Fatalf("expected volume path to be %s, got: %s", fooDir, fooDir2)
}
logDone("container REST API - can use path from normal volume as bind-mount to overwrite another volume")
}
func TestContainerApiPause(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiPause(c *check.C) {
defer unpauseAllContainers()
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sleep", "30")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
ContainerID := strings.TrimSpace(out)
if status, _, err := sockRequest("POST", "/containers/"+ContainerID+"/pause", nil); err != nil && status != http.StatusNoContent {
t.Fatalf("POST a container pause: sockRequest failed: %v", err)
c.Fatalf("POST a container pause: sockRequest failed: %v", err)
}
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != 1 || stringid.TruncateID(ContainerID) != pausedContainers[0] {
t.Fatalf("there should be one paused container and not %d", len(pausedContainers))
c.Fatalf("there should be one paused container and not %d", len(pausedContainers))
}
if status, _, err := sockRequest("POST", "/containers/"+ContainerID+"/unpause", nil); err != nil && status != http.StatusNoContent {
t.Fatalf("POST a container pause: sockRequest failed: %v", err)
c.Fatalf("POST a container pause: sockRequest failed: %v", err)
}
pausedContainers, err = getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if pausedContainers != nil {
t.Fatalf("There should be no paused container.")
c.Fatalf("There should be no paused container.")
}
logDone("container REST API - check POST containers/pause and unpause")
}
func TestContainerApiTop(t *testing.T) {
defer deleteAllContainers()
out, _ := dockerCmd(t, "run", "-d", "-i", "busybox", "/bin/sh", "-c", "cat")
id := strings.TrimSpace(out)
func (s *DockerSuite) TestContainerApiTop(c *check.C) {
out, err := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", "top").CombinedOutput()
if err != nil {
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
type topResp struct {
@ -640,40 +594,41 @@ func TestContainerApiTop(t *testing.T) {
var top topResp
_, b, err := sockRequest("GET", "/containers/"+id+"/top?ps_args=aux", nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := json.Unmarshal(b, &top); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if len(top.Titles) != 11 {
t.Fatalf("expected 11 titles, found %d: %v", len(top.Titles), top.Titles)
c.Fatalf("expected 11 titles, found %d: %v", len(top.Titles), top.Titles)
}
if top.Titles[0] != "USER" || top.Titles[10] != "COMMAND" {
t.Fatalf("expected `USER` at `Titles[0]` and `COMMAND` at Titles[10]: %v", top.Titles)
c.Fatalf("expected `USER` at `Titles[0]` and `COMMAND` at Titles[10]: %v", top.Titles)
}
if len(top.Processes) != 2 {
t.Fatalf("expeted 2 processes, found %d: %v", len(top.Processes), top.Processes)
c.Fatalf("expected 2 processes, found %d: %v", len(top.Processes), top.Processes)
}
if top.Processes[0][10] != "/bin/sh -c cat" {
t.Fatalf("expected `/bin/sh -c cat`, found: %s", top.Processes[0][10])
if top.Processes[0][10] != "/bin/sh -c top" {
c.Fatalf("expected `/bin/sh -c top`, found: %s", top.Processes[0][10])
}
if top.Processes[1][10] != "cat" {
t.Fatalf("expected `cat`, found: %s", top.Processes[1][10])
if top.Processes[1][10] != "top" {
c.Fatalf("expected `top`, found: %s", top.Processes[1][10])
}
logDone("containers REST API - GET /containers/<id>/top")
}
func TestContainerApiCommit(t *testing.T) {
out, _ := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "touch /test")
id := strings.TrimSpace(out)
func (s *DockerSuite) TestContainerApiCommit(c *check.C) {
out, err := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", "touch /test").CombinedOutput()
if err != nil {
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
name := "testcommit"
_, b, err := sockRequest("POST", "/commit?repo="+name+"&testtag=tag&container="+id, nil)
if err != nil && !strings.Contains(err.Error(), "200 OK: 201") {
t.Fatal(err)
c.Fatal(err)
}
type resp struct {
@ -681,22 +636,25 @@ func TestContainerApiCommit(t *testing.T) {
}
var img resp
if err := json.Unmarshal(b, &img); err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer deleteImages(img.Id)
out, err = inspectField(img.Id, "Config.Cmd")
if out != "[/bin/sh -c touch /test]" {
t.Fatalf("got wrong Cmd from commit: %q", out)
cmd, err := inspectField(img.Id, "Config.Cmd")
if err != nil {
c.Fatal(err)
}
if cmd != "[/bin/sh -c touch /test]" {
c.Fatalf("got wrong Cmd from commit: %q", cmd)
}
// sanity check, make sure the image is what we think it is
dockerCmd(t, "run", img.Id, "ls", "/test")
logDone("containers REST API - POST /commit")
out, err = exec.Command(dockerBinary, "run", img.Id, "ls", "/test").CombinedOutput()
if err != nil {
c.Fatal(out, err)
}
}
func TestContainerApiCreate(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiCreate(c *check.C) {
config := map[string]interface{}{
"Image": "busybox",
"Cmd": []string{"/bin/sh", "-c", "touch /test && ls /test"},
@ -704,26 +662,26 @@ func TestContainerApiCreate(t *testing.T) {
_, b, err := sockRequest("POST", "/containers/create", config)
if err != nil && !strings.Contains(err.Error(), "200 OK: 201") {
t.Fatal(err)
c.Fatal(err)
}
type createResp struct {
Id string
}
var container createResp
if err := json.Unmarshal(b, &container); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, _ := dockerCmd(t, "start", "-a", container.Id)
if strings.TrimSpace(out) != "/test" {
t.Fatalf("expected output `/test`, got %q", out)
out, err := exec.Command(dockerBinary, "start", "-a", container.Id).CombinedOutput()
if err != nil {
c.Fatal(out, err)
}
if strings.TrimSpace(string(out)) != "/test" {
c.Fatalf("expected output `/test`, got %q", out)
}
logDone("containers REST API - POST /containers/create")
}
func TestContainerApiVerifyHeader(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerApiVerifyHeader(c *check.C) {
config := map[string]interface{}{
"Image": "busybox",
}
@ -731,7 +689,7 @@ func TestContainerApiVerifyHeader(t *testing.T) {
create := func(ct string) (int, io.ReadCloser, error) {
jsonData := bytes.NewBuffer(nil)
if err := json.NewEncoder(jsonData).Encode(config); err != nil {
t.Fatal(err)
c.Fatal(err)
}
return sockRequestRaw("POST", "/containers/create", jsonData, ct)
}
@ -740,14 +698,14 @@ func TestContainerApiVerifyHeader(t *testing.T) {
_, body, err := create("")
if err == nil {
b, _ := readBody(body)
t.Fatalf("expected error when content-type is not set: %q", string(b))
c.Fatalf("expected error when content-type is not set: %q", string(b))
}
body.Close()
// Try with wrong content-type
_, body, err = create("application/xml")
if err == nil {
b, _ := readBody(body)
t.Fatalf("expected error when content-type is not set: %q", string(b))
c.Fatalf("expected error when content-type is not set: %q", string(b))
}
body.Close()
@ -755,16 +713,14 @@ func TestContainerApiVerifyHeader(t *testing.T) {
_, body, err = create("application/json")
if err != nil && !strings.Contains(err.Error(), "200 OK: 201") {
b, _ := readBody(body)
t.Fatalf("%v - %q", err, string(b))
c.Fatalf("%v - %q", err, string(b))
}
body.Close()
logDone("containers REST API - verify create header")
}
// Issue 7941 - test to make sure a "null" in JSON is just ignored.
// W/o this fix a null in JSON would be parsed into a string var as "null"
func TestContainerApiPostCreateNull(t *testing.T) {
func (s *DockerSuite) TestContainerApiPostCreateNull(c *check.C) {
config := `{
"Hostname":"",
"Domainname":"",
@ -792,33 +748,31 @@ func TestContainerApiPostCreateNull(t *testing.T) {
_, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
if err != nil && !strings.Contains(err.Error(), "200 OK: 201") {
b, _ := readBody(body)
t.Fatal(err, string(b))
c.Fatal(err, string(b))
}
b, err := readBody(body)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
type createResp struct {
Id string
}
var container createResp
if err := json.Unmarshal(b, &container); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err := inspectField(container.Id, "HostConfig.CpusetCpus")
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if out != "" {
t.Fatalf("expected empty string, got %q", out)
c.Fatalf("expected empty string, got %q", out)
}
logDone("containers REST API - Create Null")
}
func TestCreateWithTooLowMemoryLimit(t *testing.T) {
func (s *DockerSuite) TestCreateWithTooLowMemoryLimit(c *check.C) {
defer deleteAllContainers()
config := `{
"Image": "busybox",
@ -831,22 +785,21 @@ func TestCreateWithTooLowMemoryLimit(t *testing.T) {
_, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
b, err2 := readBody(body)
if err2 != nil {
t.Fatal(err2)
c.Fatal(err2)
}
if err == nil || !strings.Contains(string(b), "Minimum memory limit allowed is 4MB") {
t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
c.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
}
logDone("container REST API - create can't set too low memory limit")
}
func TestStartWithTooLowMemoryLimit(t *testing.T) {
func (s *DockerSuite) TestStartWithTooLowMemoryLimit(c *check.C) {
defer deleteAllContainers()
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "busybox"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
containerID := strings.TrimSpace(out)
@ -859,12 +812,10 @@ func TestStartWithTooLowMemoryLimit(t *testing.T) {
_, body, err := sockRequestRaw("POST", "/containers/"+containerID+"/start", strings.NewReader(config), "application/json")
b, err2 := readBody(body)
if err2 != nil {
t.Fatal(err2)
c.Fatal(err2)
}
if err == nil || !strings.Contains(string(b), "Minimum memory limit allowed is 4MB") {
t.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
c.Errorf("Memory limit is smaller than the allowed limit. Container creation should've failed!")
}
logDone("container REST API - start can't set too low memory limit")
}

View file

@ -4,26 +4,24 @@ import (
"net/http"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestExecResizeApiHeightWidthNoInt(t *testing.T) {
func (s *DockerSuite) TestExecResizeApiHeightWidthNoInt(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
cleanedContainerID := strings.TrimSpace(out)
endpoint := "/exec/" + cleanedContainerID + "/resize?h=foo&w=bar"
status, _, err := sockRequest("POST", endpoint, nil)
if err == nil {
t.Fatal("Expected exec resize Request to fail")
c.Fatal("Expected exec resize Request to fail")
}
if status != http.StatusInternalServerError {
t.Fatalf("Status expected %d, got %d", http.StatusInternalServerError, status)
c.Fatalf("Status expected %d, got %d", http.StatusInternalServerError, status)
}
logDone("container exec resize - height, width no int fail")
}

View file

@ -6,22 +6,20 @@ import (
"bytes"
"fmt"
"os/exec"
"testing"
"github.com/go-check/check"
)
// Regression test for #9414
func TestExecApiCreateNoCmd(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecApiCreateNoCmd(c *check.C) {
name := "exec_test"
runCmd := exec.Command(dockerBinary, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
_, body, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), map[string]interface{}{"Cmd": nil})
if err == nil || !bytes.Contains(body, []byte("No exec command specified")) {
t.Fatalf("Expected error when creating exec command with no Cmd specified: %q", err)
c.Fatalf("Expected error when creating exec command with no Cmd specified: %q", err)
}
logDone("exec create API - returns error when missing Cmd")
}

View file

@ -3,50 +3,50 @@ package main
import (
"encoding/json"
"net/url"
"os/exec"
"strings"
"testing"
"github.com/docker/docker/api/types"
"github.com/go-check/check"
)
func TestLegacyImages(t *testing.T) {
func (s *DockerSuite) TestLegacyImages(c *check.C) {
_, body, err := sockRequest("GET", "/v1.6/images/json", nil)
if err != nil {
t.Fatalf("Error on GET: %s", err)
c.Fatalf("Error on GET: %s", err)
}
images := []types.LegacyImage{}
if err = json.Unmarshal(body, &images); err != nil {
t.Fatalf("Error on unmarshal: %s", err)
c.Fatalf("Error on unmarshal: %s", err)
}
if len(images) == 0 || images[0].Tag == "" || images[0].Repository == "" {
t.Fatalf("Bad data: %q", images)
c.Fatalf("Bad data: %q", images)
}
logDone("images - checking legacy json")
}
func TestApiImagesFilter(t *testing.T) {
func (s *DockerSuite) TestApiImagesFilter(c *check.C) {
name := "utest:tag1"
name2 := "utest/docker:tag2"
name3 := "utest:5000/docker:tag3"
defer deleteImages(name, name2, name3)
dockerCmd(t, "tag", "busybox", name)
dockerCmd(t, "tag", "busybox", name2)
dockerCmd(t, "tag", "busybox", name3)
for _, n := range []string{name, name2, name3} {
if out, err := exec.Command(dockerBinary, "tag", "busybox", n).CombinedOutput(); err != nil {
c.Fatal(err, out)
}
}
type image struct{ RepoTags []string }
getImages := func(filter string) []image {
v := url.Values{}
v.Set("filter", filter)
_, b, err := sockRequest("GET", "/images/json?"+v.Encode(), nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
var images []image
if err := json.Unmarshal(b, &images); err != nil {
t.Fatal(err)
c.Fatal(err)
}
return images
@ -54,48 +54,49 @@ func TestApiImagesFilter(t *testing.T) {
errMsg := "incorrect number of matches returned"
if images := getImages("utest*/*"); len(images[0].RepoTags) != 2 {
t.Fatal(errMsg)
c.Fatal(errMsg)
}
if images := getImages("utest"); len(images[0].RepoTags) != 1 {
t.Fatal(errMsg)
c.Fatal(errMsg)
}
if images := getImages("utest*"); len(images[0].RepoTags) != 1 {
t.Fatal(errMsg)
c.Fatal(errMsg)
}
if images := getImages("*5000*/*"); len(images[0].RepoTags) != 1 {
t.Fatal(errMsg)
c.Fatal(errMsg)
}
logDone("images - filter param is applied")
}
func TestApiImagesSaveAndLoad(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestApiImagesSaveAndLoad(c *check.C) {
testRequires(c, Network)
out, err := buildImage("saveandload", "FROM hello-world\nENV FOO bar", false)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
id := strings.TrimSpace(out)
defer deleteImages("saveandload")
_, body, err := sockRequestRaw("GET", "/images/"+id+"/get", nil, "")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer body.Close()
dockerCmd(t, "rmi", id)
if out, err := exec.Command(dockerBinary, "rmi", id).CombinedOutput(); err != nil {
c.Fatal(err, out)
}
_, loadBody, err := sockRequestRaw("POST", "/images/load", body, "application/x-tar")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer loadBody.Close()
out, _ = dockerCmd(t, "inspect", "--format='{{ .Id }}'", id)
if strings.TrimSpace(out) != id {
t.Fatal("load did not work properly")
inspectOut, err := exec.Command(dockerBinary, "inspect", "--format='{{ .Id }}'", id).CombinedOutput()
if err != nil {
c.Fatal(err, inspectOut)
}
if strings.TrimSpace(string(inspectOut)) != id {
c.Fatal("load did not work properly")
}
logDone("images API - save and load")
}

View file

@ -33,6 +33,4 @@ func TestInfoApi(t *testing.T) {
t.Errorf("couldn't find string %v in output", linePrefix)
}
}
logDone("container REST API - check GET /info")
}

View file

@ -4,16 +4,15 @@ import (
"encoding/json"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestInspectApiContainerResponse(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestInspectApiContainerResponse(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -29,12 +28,12 @@ func TestInspectApiContainerResponse(t *testing.T) {
}
_, body, err := sockRequest("GET", endpoint, nil)
if err != nil {
t.Fatalf("sockRequest failed for %s version: %v", testVersion, err)
c.Fatalf("sockRequest failed for %s version: %v", testVersion, err)
}
var inspectJSON map[string]interface{}
if err = json.Unmarshal(body, &inspectJSON); err != nil {
t.Fatalf("unable to unmarshal body for %s version: %v", testVersion, err)
c.Fatalf("unable to unmarshal body for %s version: %v", testVersion, err)
}
keys := []string{"State", "Created", "Path", "Args", "Config", "Image", "NetworkSettings", "ResolvConfPath", "HostnamePath", "HostsPath", "LogPath", "Name", "Driver", "ExecDriver", "MountLabel", "ProcessLabel", "Volumes", "VolumesRW"}
@ -47,14 +46,12 @@ func TestInspectApiContainerResponse(t *testing.T) {
for _, key := range keys {
if _, ok := inspectJSON[key]; !ok {
t.Fatalf("%s does not exist in response for %s version", key, testVersion)
c.Fatalf("%s does not exist in response for %s version", key, testVersion)
}
}
//Issue #6830: type not properly converted to JSON/back
if _, ok := inspectJSON["Path"].(bool); ok {
t.Fatalf("Path of `true` should not be converted to boolean `true` via JSON marshalling")
c.Fatalf("Path of `true` should not be converted to boolean `true` via JSON marshalling")
}
}
logDone("container json - check keys in container json response")
}

View file

@ -5,49 +5,44 @@ import (
"fmt"
"net/http"
"os/exec"
"testing"
"github.com/go-check/check"
)
func TestLogsApiWithStdout(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLogsApiWithStdout(c *check.C) {
name := "logs_test"
runCmd := exec.Command(dockerBinary, "run", "-d", "-t", "--name", name, "busybox", "bin/sh", "-c", "sleep 10 && echo "+name)
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
statusCode, body, err := sockRequest("GET", fmt.Sprintf("/containers/%s/logs?follow=1&stdout=1&timestamps=1", name), nil)
if err != nil || statusCode != http.StatusOK {
t.Fatalf("Expected %d from logs request, got %d", http.StatusOK, statusCode)
c.Fatalf("Expected %d from logs request, got %d", http.StatusOK, statusCode)
}
if !bytes.Contains(body, []byte(name)) {
t.Fatalf("Expected %s, got %s", name, string(body[:]))
c.Fatalf("Expected %s, got %s", name, string(body[:]))
}
logDone("logs API - with stdout ok")
}
func TestLogsApiNoStdoutNorStderr(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLogsApiNoStdoutNorStderr(c *check.C) {
name := "logs_test"
runCmd := exec.Command(dockerBinary, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
statusCode, body, err := sockRequest("GET", fmt.Sprintf("/containers/%s/logs", name), nil)
if err == nil || statusCode != http.StatusBadRequest {
t.Fatalf("Expected %d from logs request, got %d", http.StatusBadRequest, statusCode)
c.Fatalf("Expected %d from logs request, got %d", http.StatusBadRequest, statusCode)
}
expected := "Bad parameters: you must choose at least one stream"
if !bytes.Contains(body, []byte(expected)) {
t.Fatalf("Expected %s, got %s", expected, string(body[:]))
c.Fatalf("Expected %s, got %s", expected, string(body[:]))
}
logDone("logs API - returns error when no stdout nor stderr specified")
}

View file

@ -4,72 +4,64 @@ import (
"net/http"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestResizeApiResponse(t *testing.T) {
func (s *DockerSuite) TestResizeApiResponse(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
cleanedContainerID := strings.TrimSpace(out)
endpoint := "/containers/" + cleanedContainerID + "/resize?h=40&w=40"
_, _, err = sockRequest("POST", endpoint, nil)
if err != nil {
t.Fatalf("resize Request failed %v", err)
c.Fatalf("resize Request failed %v", err)
}
logDone("container resize - when started")
}
func TestResizeApiHeightWidthNoInt(t *testing.T) {
func (s *DockerSuite) TestResizeApiHeightWidthNoInt(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
cleanedContainerID := strings.TrimSpace(out)
endpoint := "/containers/" + cleanedContainerID + "/resize?h=foo&w=bar"
status, _, err := sockRequest("POST", endpoint, nil)
if err == nil {
t.Fatal("Expected resize Request to fail")
c.Fatal("Expected resize Request to fail")
}
if status != http.StatusInternalServerError {
t.Fatalf("Status expected %d, got %d", http.StatusInternalServerError, status)
c.Fatalf("Status expected %d, got %d", http.StatusInternalServerError, status)
}
logDone("container resize - height, width no int fail")
}
func TestResizeApiResponseWhenContainerNotStarted(t *testing.T) {
func (s *DockerSuite) TestResizeApiResponseWhenContainerNotStarted(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
defer deleteAllContainers()
cleanedContainerID := strings.TrimSpace(out)
// make sure the exited container is not running
runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
endpoint := "/containers/" + cleanedContainerID + "/resize?h=40&w=40"
_, body, err := sockRequest("POST", endpoint, nil)
if err == nil {
t.Fatalf("resize should fail when container is not started")
c.Fatalf("resize should fail when container is not started")
}
if !strings.Contains(string(body), "Cannot resize container") && !strings.Contains(string(body), cleanedContainerID) {
t.Fatalf("resize should fail with message 'Cannot resize container' but instead received %s", string(body))
c.Fatalf("resize should fail with message 'Cannot resize container' but instead received %s", string(body))
}
logDone("container resize - when not started should not resize")
}

View file

@ -2,23 +2,23 @@ package main
import (
"encoding/json"
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/autogen/dockerversion"
"github.com/go-check/check"
)
func TestGetVersion(t *testing.T) {
func (s *DockerSuite) TestGetVersion(c *check.C) {
_, body, err := sockRequest("GET", "/version", nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
var v types.Version
if err := json.Unmarshal(body, &v); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if v.Version != dockerversion.VERSION {
t.Fatal("Version mismatch")
c.Fatal("Version mismatch")
}
}

View file

@ -6,14 +6,14 @@ import (
"os/exec"
"strings"
"sync"
"testing"
"time"
"github.com/go-check/check"
)
const attachWait = 5 * time.Second
func TestAttachMultipleAndRestart(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
endGroup := &sync.WaitGroup{}
startGroup := &sync.WaitGroup{}
@ -21,7 +21,7 @@ func TestAttachMultipleAndRestart(t *testing.T) {
startGroup.Add(3)
if err := waitForContainer("attacher", "-d", "busybox", "/bin/sh", "-c", "while true; do sleep 1; echo hello; done"); err != nil {
t.Fatal(err)
c.Fatal(err)
}
startDone := make(chan struct{})
@ -39,32 +39,32 @@ func TestAttachMultipleAndRestart(t *testing.T) {
for i := 0; i < 3; i++ {
go func() {
c := exec.Command(dockerBinary, "attach", "attacher")
cmd := exec.Command(dockerBinary, "attach", "attacher")
defer func() {
c.Wait()
cmd.Wait()
endGroup.Done()
}()
out, err := c.StdoutPipe()
out, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := c.Start(); err != nil {
t.Fatal(err)
if err := cmd.Start(); err != nil {
c.Fatal(err)
}
buf := make([]byte, 1024)
if _, err := out.Read(buf); err != nil && err != io.EOF {
t.Fatal(err)
c.Fatal(err)
}
startGroup.Done()
if !strings.Contains(string(buf), "hello") {
t.Fatalf("unexpected output %s expected hello\n", string(buf))
c.Fatalf("unexpected output %s expected hello\n", string(buf))
}
}()
}
@ -72,41 +72,39 @@ func TestAttachMultipleAndRestart(t *testing.T) {
select {
case <-startDone:
case <-time.After(attachWait):
t.Fatalf("Attaches did not initialize properly")
c.Fatalf("Attaches did not initialize properly")
}
cmd := exec.Command(dockerBinary, "kill", "attacher")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
select {
case <-endDone:
case <-time.After(attachWait):
t.Fatalf("Attaches did not finish properly")
c.Fatalf("Attaches did not finish properly")
}
logDone("attach - multiple attach")
}
func TestAttachTtyWithoutStdin(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "-ti", "busybox")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to start container: %v (%v)", out, err)
c.Fatalf("failed to start container: %v (%v)", out, err)
}
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer func() {
cmd := exec.Command(dockerBinary, "kill", id)
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatalf("failed to kill container: %v (%v)", out, err)
c.Fatalf("failed to kill container: %v (%v)", out, err)
}
}()
@ -116,70 +114,67 @@ func TestAttachTtyWithoutStdin(t *testing.T) {
cmd := exec.Command(dockerBinary, "attach", id)
if _, err := cmd.StdinPipe(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
expected := "cannot enable tty mode"
if out, _, err := runCommandWithOutput(cmd); err == nil {
t.Fatal("attach should have failed")
c.Fatal("attach should have failed")
} else if !strings.Contains(out, expected) {
t.Fatalf("attach failed with error %q: expected %q", out, expected)
c.Fatalf("attach failed with error %q: expected %q", out, expected)
}
}()
select {
case <-done:
case <-time.After(attachWait):
t.Fatal("attach is running but should have failed")
c.Fatal("attach is running but should have failed")
}
logDone("attach - forbid piped stdin to tty enabled container")
}
func TestAttachDisconnect(t *testing.T) {
defer deleteAllContainers()
out, _ := dockerCmd(t, "run", "-di", "busybox", "/bin/cat")
func (s *DockerSuite) TestAttachDisconnect(c *check.C) {
out, _ := dockerCmd(c, "run", "-di", "busybox", "/bin/cat")
id := strings.TrimSpace(out)
cmd := exec.Command(dockerBinary, "attach", id)
stdin, err := cmd.StdinPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer stdin.Close()
stdout, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer cmd.Process.Kill()
if _, err := stdin.Write([]byte("hello\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err = bufio.NewReader(stdout).ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(out) != "hello" {
t.Fatalf("exepected 'hello', got %q", out)
c.Fatalf("exepected 'hello', got %q", out)
}
if err := stdin.Close(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// Expect container to still be running after stdin is closed
running, err := inspectField(id, "State.Running")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if running != "true" {
t.Fatal("exepected container to still be running")
c.Fatal("exepected container to still be running")
}
logDone("attach - disconnect")
}

View file

@ -6,26 +6,25 @@ import (
"bufio"
"os/exec"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/stringid"
"github.com/go-check/check"
"github.com/kr/pty"
)
// #9860
func TestAttachClosedOnContainerStop(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestAttachClosedOnContainerStop(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-dti", "busybox", "sleep", "2")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to start container: %v (%v)", out, err)
c.Fatalf("failed to start container: %v (%v)", out, err)
}
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
done := make(chan struct{})
@ -35,7 +34,7 @@ func TestAttachClosedOnContainerStop(t *testing.T) {
_, tty, err := pty.Open()
if err != nil {
t.Fatalf("could not open pty: %v", err)
c.Fatalf("could not open pty: %v", err)
}
attachCmd := exec.Command(dockerBinary, "attach", id)
attachCmd.Stdin = tty
@ -43,31 +42,29 @@ func TestAttachClosedOnContainerStop(t *testing.T) {
attachCmd.Stderr = tty
if err := attachCmd.Run(); err != nil {
t.Fatalf("attach returned error %s", err)
c.Fatalf("attach returned error %s", err)
}
}()
waitCmd := exec.Command(dockerBinary, "wait", id)
if out, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", out, err)
c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
}
select {
case <-done:
case <-time.After(attachWait):
t.Fatal("timed out without attach returning")
c.Fatal("timed out without attach returning")
}
logDone("attach - return after container finished")
}
func TestAttachAfterDetach(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestAttachAfterDetach(c *check.C) {
name := "detachtest"
cpty, tty, err := pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd := exec.Command(dockerBinary, "run", "-ti", "--name", name, "busybox")
cmd.Stdin = tty
@ -77,14 +74,14 @@ func TestAttachAfterDetach(t *testing.T) {
detached := make(chan struct{})
go func() {
if err := cmd.Run(); err != nil {
t.Fatalf("attach returned error %s", err)
c.Fatalf("attach returned error %s", err)
}
close(detached)
}()
time.Sleep(500 * time.Millisecond)
if err := waitRun(name); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cpty.Write([]byte{16})
time.Sleep(100 * time.Millisecond)
@ -94,7 +91,7 @@ func TestAttachAfterDetach(t *testing.T) {
cpty, tty, err = pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd = exec.Command(dockerBinary, "attach", name)
@ -103,7 +100,7 @@ func TestAttachAfterDetach(t *testing.T) {
cmd.Stderr = tty
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
bytes := make([]byte, 10)
@ -123,34 +120,33 @@ func TestAttachAfterDetach(t *testing.T) {
select {
case err := <-readErr:
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
case <-time.After(2 * time.Second):
t.Fatal("timeout waiting for attach read")
c.Fatal("timeout waiting for attach read")
}
if err := cmd.Wait(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !strings.Contains(string(bytes[:nBytes]), "/ #") {
t.Fatalf("failed to get a new prompt. got %s", string(bytes[:nBytes]))
c.Fatalf("failed to get a new prompt. got %s", string(bytes[:nBytes]))
}
logDone("attach - reconnect after detaching")
}
// TestAttachDetach checks that attach in tty mode can be detached using the long container ID
func TestAttachDetach(t *testing.T) {
out, _ := dockerCmd(t, "run", "-itd", "busybox", "cat")
func (s *DockerSuite) TestAttachDetach(c *check.C) {
out, _ := dockerCmd(c, "run", "-itd", "busybox", "cat")
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cpty, tty, err := pty.Open()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer cpty.Close()
@ -158,34 +154,34 @@ func TestAttachDetach(t *testing.T) {
cmd.Stdin = tty
stdout, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := waitRun(id); err != nil {
t.Fatalf("error waiting for container to start: %v", err)
c.Fatalf("error waiting for container to start: %v", err)
}
if _, err := cpty.Write([]byte("hello\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err = bufio.NewReader(stdout).ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(out) != "hello" {
t.Fatalf("exepected 'hello', got %q", out)
c.Fatalf("exepected 'hello', got %q", out)
}
// escape sequence
if _, err := cpty.Write([]byte{16}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(100 * time.Millisecond)
if _, err := cpty.Write([]byte{17}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
ch := make(chan struct{})
@ -196,36 +192,35 @@ func TestAttachDetach(t *testing.T) {
running, err := inspectField(id, "State.Running")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if running != "true" {
t.Fatal("exepected container to still be running")
c.Fatal("exepected container to still be running")
}
go func() {
dockerCmd(t, "kill", id)
dockerCmd(c, "kill", id)
}()
select {
case <-ch:
case <-time.After(10 * time.Millisecond):
t.Fatal("timed out waiting for container to exit")
c.Fatal("timed out waiting for container to exit")
}
logDone("attach - detach")
}
// TestAttachDetachTruncatedID checks that attach in tty mode can be detached
func TestAttachDetachTruncatedID(t *testing.T) {
out, _ := dockerCmd(t, "run", "-itd", "busybox", "cat")
func (s *DockerSuite) TestAttachDetachTruncatedID(c *check.C) {
out, _ := dockerCmd(c, "run", "-itd", "busybox", "cat")
id := stringid.TruncateID(strings.TrimSpace(out))
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cpty, tty, err := pty.Open()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer cpty.Close()
@ -233,31 +228,31 @@ func TestAttachDetachTruncatedID(t *testing.T) {
cmd.Stdin = tty
stdout, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if _, err := cpty.Write([]byte("hello\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err = bufio.NewReader(stdout).ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(out) != "hello" {
t.Fatalf("exepected 'hello', got %q", out)
c.Fatalf("exepected 'hello', got %q", out)
}
// escape sequence
if _, err := cpty.Write([]byte{16}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(100 * time.Millisecond)
if _, err := cpty.Write([]byte{17}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
ch := make(chan struct{})
@ -268,21 +263,20 @@ func TestAttachDetachTruncatedID(t *testing.T) {
running, err := inspectField(id, "State.Running")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if running != "true" {
t.Fatal("exepected container to still be running")
c.Fatal("exepected container to still be running")
}
go func() {
dockerCmd(t, "kill", id)
dockerCmd(c, "kill", id)
}()
select {
case <-ch:
case <-time.After(10 * time.Millisecond):
t.Fatal("timed out waiting for container to exit")
c.Fatal("timed out waiting for container to exit")
}
logDone("attach - detach truncated ID")
}

File diff suppressed because it is too large Load diff

View file

@ -5,9 +5,9 @@ import (
"os/exec"
"regexp"
"strings"
"testing"
"github.com/docker/docker/utils"
"github.com/go-check/check"
)
var (
@ -22,15 +22,15 @@ func setupImage() (string, error) {
func setupImageWithTag(tag string) (string, error) {
containerName := "busyboxbydigest"
c := exec.Command(dockerBinary, "run", "-d", "-e", "digest=1", "--name", containerName, "busybox")
if _, err := runCommand(c); err != nil {
cmd := exec.Command(dockerBinary, "run", "-d", "-e", "digest=1", "--name", containerName, "busybox")
if _, err := runCommand(cmd); err != nil {
return "", err
}
// tag the image to upload it to the private registry
repoAndTag := utils.ImageReference(repoName, tag)
c = exec.Command(dockerBinary, "commit", containerName, repoAndTag)
if out, _, err := runCommandWithOutput(c); err != nil {
cmd = exec.Command(dockerBinary, "commit", containerName, repoAndTag)
if out, _, err := runCommandWithOutput(cmd); err != nil {
return "", fmt.Errorf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoAndTag)
@ -41,15 +41,15 @@ func setupImageWithTag(tag string) (string, error) {
}
// push the image
c = exec.Command(dockerBinary, "push", repoAndTag)
out, _, err := runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "push", repoAndTag)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
return "", fmt.Errorf("pushing the image to the private registry has failed: %s, %v", out, err)
}
// delete our local repo that we previously tagged
c = exec.Command(dockerBinary, "rmi", repoAndTag)
if out, _, err := runCommandWithOutput(c); err != nil {
cmd = exec.Command(dockerBinary, "rmi", repoAndTag)
if out, _, err := runCommandWithOutput(cmd); err != nil {
return "", fmt.Errorf("error deleting images prior to real test: %s, %v", out, err)
}
@ -63,194 +63,189 @@ func setupImageWithTag(tag string) (string, error) {
return pushDigest, nil
}
func TestPullByTagDisplaysDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPullByTagDisplaysDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
// pull from the registry using the tag
c := exec.Command(dockerBinary, "pull", repoName)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", repoName)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by tag: %s, %v", out, err)
c.Fatalf("error pulling by tag: %s, %v", out, err)
}
defer deleteImages(repoName)
// the pull output includes "Digest: <digest>", so find that
matches := digestRegex.FindStringSubmatch(out)
if len(matches) != 2 {
t.Fatalf("unable to parse digest from pull output: %s", out)
c.Fatalf("unable to parse digest from pull output: %s", out)
}
pullDigest := matches[1]
// make sure the pushed and pull digests match
if pushDigest != pullDigest {
t.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
c.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
}
logDone("by_digest - pull by tag displays digest")
}
func TestPullByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPullByDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
// pull from the registry using the <name>@<digest> reference
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
defer deleteImages(imageReference)
// the pull output includes "Digest: <digest>", so find that
matches := digestRegex.FindStringSubmatch(out)
if len(matches) != 2 {
t.Fatalf("unable to parse digest from pull output: %s", out)
c.Fatalf("unable to parse digest from pull output: %s", out)
}
pullDigest := matches[1]
// make sure the pushed and pull digests match
if pushDigest != pullDigest {
t.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
c.Fatalf("push digest %q didn't match pull digest %q", pushDigest, pullDigest)
}
logDone("by_digest - pull by digest")
}
func TestCreateByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestCreateByDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
containerName := "createByDigest"
c := exec.Command(dockerBinary, "create", "--name", containerName, imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "create", "--name", containerName, imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error creating by digest: %s, %v", out, err)
c.Fatalf("error creating by digest: %s, %v", out, err)
}
defer deleteContainer(containerName)
res, err := inspectField(containerName, "Config.Image")
if err != nil {
t.Fatalf("failed to get Config.Image: %s, %v", out, err)
c.Fatalf("failed to get Config.Image: %s, %v", out, err)
}
if res != imageReference {
t.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
c.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
}
logDone("by_digest - create by digest")
}
func TestRunByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestRunByDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
containerName := "runByDigest"
c := exec.Command(dockerBinary, "run", "--name", containerName, imageReference, "sh", "-c", "echo found=$digest")
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "run", "--name", containerName, imageReference, "sh", "-c", "echo found=$digest")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error run by digest: %s, %v", out, err)
c.Fatalf("error run by digest: %s, %v", out, err)
}
defer deleteContainer(containerName)
foundRegex := regexp.MustCompile("found=([^\n]+)")
matches := foundRegex.FindStringSubmatch(out)
if len(matches) != 2 {
t.Fatalf("error locating expected 'found=1' output: %s", out)
c.Fatalf("error locating expected 'found=1' output: %s", out)
}
if matches[1] != "1" {
t.Fatalf("Expected %q, got %q", "1", matches[1])
c.Fatalf("Expected %q, got %q", "1", matches[1])
}
res, err := inspectField(containerName, "Config.Image")
if err != nil {
t.Fatalf("failed to get Config.Image: %s, %v", out, err)
c.Fatalf("failed to get Config.Image: %s, %v", out, err)
}
if res != imageReference {
t.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
c.Fatalf("unexpected Config.Image: %s (expected %s)", res, imageReference)
}
logDone("by_digest - run by digest")
}
func TestRemoveImageByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestRemoveImageByDigest(c *check.C) {
defer setupRegistry(c)()
digest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, digest)
// pull from the registry using the <name>@<digest> reference
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// make sure inspect runs ok
if _, err := inspectField(imageReference, "Id"); err != nil {
t.Fatalf("failed to inspect image: %v", err)
c.Fatalf("failed to inspect image: %v", err)
}
// do the delete
if err := deleteImages(imageReference); err != nil {
t.Fatalf("unexpected error deleting image: %v", err)
c.Fatalf("unexpected error deleting image: %v", err)
}
// try to inspect again - it should error this time
if _, err := inspectField(imageReference, "Id"); err == nil {
t.Fatalf("unexpected nil err trying to inspect what should be a non-existent image")
c.Fatalf("unexpected nil err trying to inspect what should be a non-existent image")
} else if !strings.Contains(err.Error(), "No such image") {
t.Fatalf("expected 'No such image' output, got %v", err)
c.Fatalf("expected 'No such image' output, got %v", err)
}
logDone("by_digest - remove image by digest")
}
func TestBuildByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestBuildByDigest(c *check.C) {
defer setupRegistry(c)()
digest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, digest)
// pull from the registry using the <name>@<digest> reference
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// get the image id
imageID, err := inspectField(imageReference, "Id")
if err != nil {
t.Fatalf("error getting image id: %v", err)
c.Fatalf("error getting image id: %v", err)
}
// do the build
@ -261,275 +256,270 @@ func TestBuildByDigest(t *testing.T) {
CMD ["/bin/echo", "Hello World"]`, imageReference),
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// get the build's image id
res, err := inspectField(name, "Config.Image")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// make sure they match
if res != imageID {
t.Fatalf("Image %s, expected %s", res, imageID)
c.Fatalf("Image %s, expected %s", res, imageID)
}
logDone("by_digest - build by digest")
}
func TestTagByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestTagByDigest(c *check.C) {
defer setupRegistry(c)()
digest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, digest)
// pull from the registry using the <name>@<digest> reference
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// tag it
tag := "tagbydigest"
c = exec.Command(dockerBinary, "tag", imageReference, tag)
if _, err := runCommand(c); err != nil {
t.Fatalf("unexpected error tagging: %v", err)
cmd = exec.Command(dockerBinary, "tag", imageReference, tag)
if _, err := runCommand(cmd); err != nil {
c.Fatalf("unexpected error tagging: %v", err)
}
expectedID, err := inspectField(imageReference, "Id")
if err != nil {
t.Fatalf("error getting original image id: %v", err)
c.Fatalf("error getting original image id: %v", err)
}
tagID, err := inspectField(tag, "Id")
if err != nil {
t.Fatalf("error getting tagged image id: %v", err)
c.Fatalf("error getting tagged image id: %v", err)
}
if tagID != expectedID {
t.Fatalf("expected image id %q, got %q", expectedID, tagID)
c.Fatalf("expected image id %q, got %q", expectedID, tagID)
}
logDone("by_digest - tag by digest")
}
func TestListImagesWithoutDigests(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestListImagesWithoutDigests(c *check.C) {
defer setupRegistry(c)()
digest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference := fmt.Sprintf("%s@%s", repoName, digest)
// pull from the registry using the <name>@<digest> reference
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
c = exec.Command(dockerBinary, "images")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
if strings.Contains(out, "DIGEST") {
t.Fatalf("list output should not have contained DIGEST header: %s", out)
c.Fatalf("list output should not have contained DIGEST header: %s", out)
}
logDone("by_digest - list images - digest header not displayed by default")
}
func TestListImagesWithDigests(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestListImagesWithDigests(c *check.C) {
defer setupRegistry(c)()
defer deleteImages(repoName+":tag1", repoName+":tag2")
// setup image1
digest1, err := setupImageWithTag("tag1")
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference1 := fmt.Sprintf("%s@%s", repoName, digest1)
defer deleteImages(imageReference1)
t.Logf("imageReference1 = %s", imageReference1)
c.Logf("imageReference1 = %s", imageReference1)
// pull image1 by digest
c := exec.Command(dockerBinary, "pull", imageReference1)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference1)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure repo shown, tag=<none>, digest = $digest1
re1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
if !re1.MatchString(out) {
t.Fatalf("expected %q: %s", re1.String(), out)
c.Fatalf("expected %q: %s", re1.String(), out)
}
// setup image2
digest2, err := setupImageWithTag("tag2")
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
imageReference2 := fmt.Sprintf("%s@%s", repoName, digest2)
defer deleteImages(imageReference2)
t.Logf("imageReference2 = %s", imageReference2)
c.Logf("imageReference2 = %s", imageReference2)
// pull image1 by digest
c = exec.Command(dockerBinary, "pull", imageReference1)
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "pull", imageReference1)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// pull image2 by digest
c = exec.Command(dockerBinary, "pull", imageReference2)
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "pull", imageReference2)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure repo shown, tag=<none>, digest = $digest1
if !re1.MatchString(out) {
t.Fatalf("expected %q: %s", re1.String(), out)
c.Fatalf("expected %q: %s", re1.String(), out)
}
// make sure repo shown, tag=<none>, digest = $digest2
re2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
if !re2.MatchString(out) {
t.Fatalf("expected %q: %s", re2.String(), out)
c.Fatalf("expected %q: %s", re2.String(), out)
}
// pull tag1
c = exec.Command(dockerBinary, "pull", repoName+":tag1")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "pull", repoName+":tag1")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling tag1: %s, %v", out, err)
c.Fatalf("error pulling tag1: %s, %v", out, err)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure image 1 has repo, tag, <none> AND repo, <none>, digest
reWithTag1 := regexp.MustCompile(`\s*` + repoName + `\s*tag1\s*<none>\s`)
reWithDigest1 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest1 + `\s`)
if !reWithTag1.MatchString(out) {
t.Fatalf("expected %q: %s", reWithTag1.String(), out)
c.Fatalf("expected %q: %s", reWithTag1.String(), out)
}
if !reWithDigest1.MatchString(out) {
t.Fatalf("expected %q: %s", reWithDigest1.String(), out)
c.Fatalf("expected %q: %s", reWithDigest1.String(), out)
}
// make sure image 2 has repo, <none>, digest
if !re2.MatchString(out) {
t.Fatalf("expected %q: %s", re2.String(), out)
c.Fatalf("expected %q: %s", re2.String(), out)
}
// pull tag 2
c = exec.Command(dockerBinary, "pull", repoName+":tag2")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "pull", repoName+":tag2")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling tag2: %s, %v", out, err)
c.Fatalf("error pulling tag2: %s, %v", out, err)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure image 1 has repo, tag, digest
if !reWithTag1.MatchString(out) {
t.Fatalf("expected %q: %s", re1.String(), out)
c.Fatalf("expected %q: %s", re1.String(), out)
}
// make sure image 2 has repo, tag, digest
reWithTag2 := regexp.MustCompile(`\s*` + repoName + `\s*tag2\s*<none>\s`)
reWithDigest2 := regexp.MustCompile(`\s*` + repoName + `\s*<none>\s*` + digest2 + `\s`)
if !reWithTag2.MatchString(out) {
t.Fatalf("expected %q: %s", reWithTag2.String(), out)
c.Fatalf("expected %q: %s", reWithTag2.String(), out)
}
if !reWithDigest2.MatchString(out) {
t.Fatalf("expected %q: %s", reWithDigest2.String(), out)
c.Fatalf("expected %q: %s", reWithDigest2.String(), out)
}
// list images
c = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "--digests")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error listing images: %s, %v", out, err)
c.Fatalf("error listing images: %s, %v", out, err)
}
// make sure image 1 has repo, tag, digest
if !reWithTag1.MatchString(out) {
t.Fatalf("expected %q: %s", re1.String(), out)
c.Fatalf("expected %q: %s", re1.String(), out)
}
// make sure image 2 has repo, tag, digest
if !reWithTag2.MatchString(out) {
t.Fatalf("expected %q: %s", re2.String(), out)
c.Fatalf("expected %q: %s", re2.String(), out)
}
// make sure busybox has tag, but not digest
busyboxRe := regexp.MustCompile(`\s*busybox\s*latest\s*<none>\s`)
if !busyboxRe.MatchString(out) {
t.Fatalf("expected %q: %s", busyboxRe.String(), out)
c.Fatalf("expected %q: %s", busyboxRe.String(), out)
}
logDone("by_digest - list images with digests")
}
func TestDeleteImageByIDOnlyPulledByDigest(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestDeleteImageByIDOnlyPulledByDigest(c *check.C) {
defer setupRegistry(c)()
pushDigest, err := setupImage()
if err != nil {
t.Fatalf("error setting up image: %v", err)
c.Fatalf("error setting up image: %v", err)
}
// pull from the registry using the <name>@<digest> reference
imageReference := fmt.Sprintf("%s@%s", repoName, pushDigest)
c := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "pull", imageReference)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error pulling by digest: %s, %v", out, err)
c.Fatalf("error pulling by digest: %s, %v", out, err)
}
// just in case...
defer deleteImages(imageReference)
imageID, err := inspectField(imageReference, ".Id")
if err != nil {
t.Fatalf("error inspecting image id: %v", err)
c.Fatalf("error inspecting image id: %v", err)
}
c = exec.Command(dockerBinary, "rmi", imageID)
if _, err := runCommand(c); err != nil {
t.Fatalf("error deleting image by id: %v", err)
cmd = exec.Command(dockerBinary, "rmi", imageID)
if _, err := runCommand(cmd); err != nil {
c.Fatalf("error deleting image by id: %v", err)
}
logDone("by_digest - delete image by id only pulled by digest")
}

View file

@ -3,96 +3,94 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestCommitAfterContainerIsDone(t *testing.T) {
func (s *DockerSuite) TestCommitAfterContainerIsDone(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-i", "-a", "stdin", "busybox", "echo", "foo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("failed to run container: %s, %v", out, err)
c.Fatalf("failed to run container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
waitCmd := exec.Command(dockerBinary, "wait", cleanedContainerID)
if _, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", out, err)
c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container to image: %s, %v", out, err)
c.Fatalf("failed to commit container to image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("failed to inspect image: %s, %v", out, err)
c.Fatalf("failed to inspect image: %s, %v", out, err)
}
deleteContainer(cleanedContainerID)
deleteImages(cleanedImageID)
logDone("commit - echo foo and commit the image")
}
func TestCommitWithoutPause(t *testing.T) {
func (s *DockerSuite) TestCommitWithoutPause(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-i", "-a", "stdin", "busybox", "echo", "foo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("failed to run container: %s, %v", out, err)
c.Fatalf("failed to run container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
waitCmd := exec.Command(dockerBinary, "wait", cleanedContainerID)
if _, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", out, err)
c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", "-p=false", cleanedContainerID)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container to image: %s, %v", out, err)
c.Fatalf("failed to commit container to image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("failed to inspect image: %s, %v", out, err)
c.Fatalf("failed to inspect image: %s, %v", out, err)
}
deleteContainer(cleanedContainerID)
deleteImages(cleanedImageID)
logDone("commit - echo foo and commit the image with --pause=false")
}
//test commit a paused container should not unpause it after commit
func TestCommitPausedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitPausedContainer(c *check.C) {
defer unpauseAllContainers()
cmd := exec.Command(dockerBinary, "run", "-i", "-d", "busybox")
out, _, _, err := runCommandWithStdoutStderr(cmd)
if err != nil {
t.Fatalf("failed to run container: %v, output: %q", err, out)
c.Fatalf("failed to run container: %v, output: %q", err, out)
}
cleanedContainerID := strings.TrimSpace(out)
cmd = exec.Command(dockerBinary, "pause", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(cmd)
if err != nil {
t.Fatalf("failed to pause container: %v, output: %q", err, out)
c.Fatalf("failed to pause container: %v, output: %q", err, out)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container to image: %s, %v", out, err)
c.Fatalf("failed to commit container to image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
defer deleteImages(cleanedImageID)
@ -100,28 +98,26 @@ func TestCommitPausedContainer(t *testing.T) {
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Paused}}", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(cmd)
if err != nil {
t.Fatalf("failed to inspect container: %v, output: %q", err, out)
c.Fatalf("failed to inspect container: %v, output: %q", err, out)
}
if !strings.Contains(out, "true") {
t.Fatalf("commit should not unpause a paused container")
c.Fatalf("commit should not unpause a paused container")
}
logDone("commit - commit a paused container will not unpause it")
}
func TestCommitNewFile(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitNewFile(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "--name", "commiter", "busybox", "/bin/sh", "-c", "echo koye > /foo")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "commit", "commiter")
imageID, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
imageID = strings.Trim(imageID, "\r\n")
defer deleteImages(imageID)
@ -130,22 +126,20 @@ func TestCommitNewFile(t *testing.T) {
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if actual := strings.Trim(out, "\r\n"); actual != "koye" {
t.Fatalf("expected output koye received %q", actual)
c.Fatalf("expected output koye received %q", actual)
}
logDone("commit - commit file and read")
}
func TestCommitHardlink(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitHardlink(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-t", "--name", "hardlinks", "busybox", "sh", "-c", "touch file1 && ln file1 file2 && ls -di file1 file2")
firstOuput, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
chunks := strings.Split(strings.TrimSpace(firstOuput), " ")
@ -158,13 +152,13 @@ func TestCommitHardlink(t *testing.T) {
}
}
if !found {
t.Fatalf("Failed to create hardlink in a container. Expected to find %q in %q", inode, chunks[1:])
c.Fatalf("Failed to create hardlink in a container. Expected to find %q in %q", inode, chunks[1:])
}
cmd = exec.Command(dockerBinary, "commit", "hardlinks", "hardlinks")
imageID, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(imageID, err)
c.Fatal(imageID, err)
}
imageID = strings.Trim(imageID, "\r\n")
defer deleteImages(imageID)
@ -172,7 +166,7 @@ func TestCommitHardlink(t *testing.T) {
cmd = exec.Command(dockerBinary, "run", "-t", "hardlinks", "ls", "-di", "file1", "file2")
secondOuput, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
chunks = strings.Split(strings.TrimSpace(secondOuput), " ")
@ -185,48 +179,44 @@ func TestCommitHardlink(t *testing.T) {
}
}
if !found {
t.Fatalf("Failed to create hardlink in a container. Expected to find %q in %q", inode, chunks[1:])
c.Fatalf("Failed to create hardlink in a container. Expected to find %q in %q", inode, chunks[1:])
}
logDone("commit - commit hardlinks")
}
func TestCommitTTY(t *testing.T) {
func (s *DockerSuite) TestCommitTTY(c *check.C) {
defer deleteImages("ttytest")
defer deleteAllContainers()
cmd := exec.Command(dockerBinary, "run", "-t", "--name", "tty", "busybox", "/bin/ls")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "commit", "tty", "ttytest")
imageID, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
imageID = strings.Trim(imageID, "\r\n")
cmd = exec.Command(dockerBinary, "run", "ttytest", "/bin/ls")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
logDone("commit - commit tty")
}
func TestCommitWithHostBindMount(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitWithHostBindMount(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "--name", "bind-commit", "-v", "/dev/null:/winning", "busybox", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "commit", "bind-commit", "bindtest")
imageID, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(imageID, err)
c.Fatal(imageID, err)
}
imageID = strings.Trim(imageID, "\r\n")
@ -235,18 +225,16 @@ func TestCommitWithHostBindMount(t *testing.T) {
cmd = exec.Command(dockerBinary, "run", "bindtest", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
logDone("commit - commit bind mounted file")
}
func TestCommitChange(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitChange(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "--name", "test", "busybox", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "commit",
@ -257,7 +245,7 @@ func TestCommitChange(t *testing.T) {
"test", "test-commit")
imageId, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(imageId, err)
c.Fatal(imageId, err)
}
imageId = strings.Trim(imageId, "\r\n")
defer deleteImages(imageId)
@ -270,29 +258,27 @@ func TestCommitChange(t *testing.T) {
for conf, value := range expected {
res, err := inspectField(imageId, conf)
if err != nil {
t.Errorf("failed to get value %s, error: %s", conf, err)
c.Errorf("failed to get value %s, error: %s", conf, err)
}
if res != value {
t.Errorf("%s('%s'), expected %s", conf, res, value)
c.Errorf("%s('%s'), expected %s", conf, res, value)
}
}
logDone("commit - commit --change")
}
// TODO: commit --run is deprecated, remove this once --run is removed
func TestCommitMergeConfigRun(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCommitMergeConfigRun(c *check.C) {
name := "commit-test"
out, _ := dockerCmd(t, "run", "-d", "-e=FOO=bar", "busybox", "/bin/sh", "-c", "echo testing > /tmp/foo")
out, _ := dockerCmd(c, "run", "-d", "-e=FOO=bar", "busybox", "/bin/sh", "-c", "echo testing > /tmp/foo")
id := strings.TrimSpace(out)
dockerCmd(t, "commit", `--run={"Cmd": ["cat", "/tmp/foo"]}`, id, "commit-test")
dockerCmd(c, "commit", `--run={"Cmd": ["cat", "/tmp/foo"]}`, id, "commit-test")
defer deleteImages("commit-test")
out, _ = dockerCmd(t, "run", "--name", name, "commit-test")
out, _ = dockerCmd(c, "run", "--name", name, "commit-test")
if strings.TrimSpace(out) != "testing" {
t.Fatal("run config in commited container was not merged")
c.Fatal("run config in commited container was not merged")
}
type cfg struct {
@ -301,11 +287,11 @@ func TestCommitMergeConfigRun(t *testing.T) {
}
config1 := cfg{}
if err := inspectFieldAndMarshall(id, "Config", &config1); err != nil {
t.Fatal(err)
c.Fatal(err)
}
config2 := cfg{}
if err := inspectFieldAndMarshall(name, "Config", &config2); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// Env has at least PATH loaded as well here, so let's just grab the FOO one
@ -324,8 +310,7 @@ func TestCommitMergeConfigRun(t *testing.T) {
}
if len(config1.Env) != len(config2.Env) || env1 != env2 && env2 != "" {
t.Fatalf("expected envs to match: %v - %v", config1.Env, config2.Env)
c.Fatalf("expected envs to match: %v - %v", config1.Env, config2.Env)
}
logDone("commit - configs are merged with --run")
}

View file

@ -7,13 +7,13 @@ import (
"os"
"os/exec"
"path/filepath"
"testing"
"github.com/docker/docker/pkg/homedir"
"github.com/go-check/check"
)
func TestConfigHttpHeader(t *testing.T) {
testRequires(t, UnixCli) // Can't set/unset HOME on windows right now
func (s *DockerSuite) TestConfigHttpHeader(c *check.C) {
testRequires(c, UnixCli) // Can't set/unset HOME on windows right now
// We either need a level of Go that supports Unsetenv (for cases
// when HOME/USERPROFILE isn't set), or we need to be able to use
// os/user but user.Current() only works if we aren't statically compiling
@ -44,15 +44,13 @@ func TestConfigHttpHeader(t *testing.T) {
err := ioutil.WriteFile(tmpCfg, []byte(data), 0600)
if err != nil {
t.Fatalf("Err creating file(%s): %v", tmpCfg, err)
c.Fatalf("Err creating file(%s): %v", tmpCfg, err)
}
cmd := exec.Command(dockerBinary, "-H="+server.URL[7:], "ps")
out, _, _ := runCommandWithOutput(cmd)
if headers["Myheader"] == nil || headers["Myheader"][0] != "MyValue" {
t.Fatalf("Missing/bad header: %q\nout:%v", headers, out)
c.Fatalf("Missing/bad header: %q\nout:%v", headers, out)
}
logDone("config - add new http headers")
}

View file

@ -9,7 +9,8 @@ import (
"path"
"path/filepath"
"strings"
"testing"
"github.com/go-check/check"
)
const (
@ -24,27 +25,27 @@ const (
// Test for #5656
// Check that garbage paths don't escape the container's rootfs
func TestCpGarbagePath(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
func (s *DockerSuite) TestCpGarbagePath(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -53,7 +54,7 @@ func TestCpGarbagePath(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -61,49 +62,48 @@ func TestCpGarbagePath(t *testing.T) {
path := path.Join("../../../../../../../../../../../../", cpFullPath)
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+path, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- garbage path can escape container rootfs")
c.Errorf("output matched host file -- garbage path can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for garbage path")
c.Errorf("output doesn't match the input for garbage path")
}
logDone("cp - garbage paths relative to container's rootfs")
}
// Check that relative paths are relative to the container's rootfs
func TestCpRelativePath(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
func (s *DockerSuite) TestCpRelativePath(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -113,7 +113,7 @@ func TestCpRelativePath(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -125,52 +125,51 @@ func TestCpRelativePath(t *testing.T) {
// get this unix-path manipulation on windows with filepath.
relPath = cpFullPath[1:]
} else {
t.Fatalf("path %s was assumed to be an absolute path", cpFullPath)
c.Fatalf("path %s was assumed to be an absolute path", cpFullPath)
}
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+relPath, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+relPath, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- relative path can escape container rootfs")
c.Errorf("output matched host file -- relative path can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for relative path")
c.Errorf("output doesn't match the input for relative path")
}
logDone("cp - relative paths relative to container's rootfs")
}
// Check that absolute paths are relative to the container's rootfs
func TestCpAbsolutePath(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
func (s *DockerSuite) TestCpAbsolutePath(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath)
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -180,7 +179,7 @@ func TestCpAbsolutePath(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -188,50 +187,49 @@ func TestCpAbsolutePath(t *testing.T) {
path := cpFullPath
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+path, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- absolute path can escape container rootfs")
c.Errorf("output matched host file -- absolute path can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for absolute path")
c.Errorf("output doesn't match the input for absolute path")
}
logDone("cp - absolute paths relative to container's rootfs")
}
// Test for #5619
// Check that absolute symlinks are still relative to the container's rootfs
func TestCpAbsoluteSymlink(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpFullPath+" container_path")
func (s *DockerSuite) TestCpAbsoluteSymlink(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpFullPath+" container_path")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -241,7 +239,7 @@ func TestCpAbsoluteSymlink(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -249,50 +247,49 @@ func TestCpAbsoluteSymlink(t *testing.T) {
path := path.Join("/", "container_path")
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+path, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- absolute symlink can escape container rootfs")
c.Errorf("output matched host file -- absolute symlink can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for absolute symlink")
c.Errorf("output doesn't match the input for absolute symlink")
}
logDone("cp - absolute symlink relative to container's rootfs")
}
// Test for #5619
// Check that symlinks which are part of the resource path are still relative to the container's rootfs
func TestCpSymlinkComponent(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpTestPath+" container_path")
func (s *DockerSuite) TestCpSymlinkComponent(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir -p '"+cpTestPath+"' && echo -n '"+cpContainerContents+"' > "+cpFullPath+" && ln -s "+cpTestPath+" container_path")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
if err := os.MkdirAll(cpTestPath, os.ModeDir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
hostFile, err := os.Create(cpFullPath)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer hostFile.Close()
defer os.RemoveAll(cpTestPathParent)
@ -302,7 +299,7 @@ func TestCpSymlinkComponent(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
tmpname := filepath.Join(tmpdir, cpTestName)
@ -310,268 +307,263 @@ func TestCpSymlinkComponent(t *testing.T) {
path := path.Join("/", "container_path", cpTestName)
_, _ = dockerCmd(t, "cp", cleanedContainerID+":"+path, tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":"+path, tmpdir)
file, _ := os.Open(tmpname)
defer file.Close()
test, err := ioutil.ReadAll(file)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if string(test) == cpHostContents {
t.Errorf("output matched host file -- symlink path component can escape container rootfs")
c.Errorf("output matched host file -- symlink path component can escape container rootfs")
}
if string(test) != cpContainerContents {
t.Errorf("output doesn't match the input for symlink path component")
c.Errorf("output doesn't match the input for symlink path component")
}
logDone("cp - symlink path components relative to container's rootfs")
}
// Check that cp with unprivileged user doesn't return any error
func TestCpUnprivilegedUser(t *testing.T) {
testRequires(t, UnixCli) // uses chmod/su: not available on windows
func (s *DockerSuite) TestCpUnprivilegedUser(c *check.C) {
testRequires(c, UnixCli) // uses chmod/su: not available on windows
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "touch "+cpTestName)
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "touch "+cpTestName)
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpdir)
if err = os.Chmod(tmpdir, 0777); err != nil {
t.Fatal(err)
c.Fatal(err)
}
path := cpTestName
_, _, err = runCommandWithOutput(exec.Command("su", "unprivilegeduser", "-c", dockerBinary+" cp "+cleanedContainerID+":"+path+" "+tmpdir))
if err != nil {
t.Fatalf("couldn't copy with unprivileged user: %s:%s %s", cleanedContainerID, path, err)
c.Fatalf("couldn't copy with unprivileged user: %s:%s %s", cleanedContainerID, path, err)
}
logDone("cp - unprivileged user")
}
func TestCpSpecialFiles(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestCpSpecialFiles(c *check.C) {
testRequires(c, SameHostDaemon)
outDir, err := ioutil.TempDir("", "cp-test-special-files")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(outDir)
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "touch /foo")
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "touch /foo")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
// Copy actual /etc/resolv.conf
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/etc/resolv.conf", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/etc/resolv.conf", outDir)
expected, err := ioutil.ReadFile("/var/lib/docker/containers/" + cleanedContainerID + "/resolv.conf")
actual, err := ioutil.ReadFile(outDir + "/resolv.conf")
if !bytes.Equal(actual, expected) {
t.Fatalf("Expected copied file to be duplicate of the container resolvconf")
c.Fatalf("Expected copied file to be duplicate of the container resolvconf")
}
// Copy actual /etc/hosts
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/etc/hosts", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/etc/hosts", outDir)
expected, err = ioutil.ReadFile("/var/lib/docker/containers/" + cleanedContainerID + "/hosts")
actual, err = ioutil.ReadFile(outDir + "/hosts")
if !bytes.Equal(actual, expected) {
t.Fatalf("Expected copied file to be duplicate of the container hosts")
c.Fatalf("Expected copied file to be duplicate of the container hosts")
}
// Copy actual /etc/resolv.conf
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/etc/hostname", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/etc/hostname", outDir)
expected, err = ioutil.ReadFile("/var/lib/docker/containers/" + cleanedContainerID + "/hostname")
actual, err = ioutil.ReadFile(outDir + "/hostname")
if !bytes.Equal(actual, expected) {
t.Fatalf("Expected copied file to be duplicate of the container resolvconf")
c.Fatalf("Expected copied file to be duplicate of the container resolvconf")
}
logDone("cp - special files (resolv.conf, hosts, hostname)")
}
func TestCpVolumePath(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestCpVolumePath(c *check.C) {
testRequires(c, SameHostDaemon)
tmpDir, err := ioutil.TempDir("", "cp-test-volumepath")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpDir)
outDir, err := ioutil.TempDir("", "cp-test-volumepath-out")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(outDir)
_, err = os.Create(tmpDir + "/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, exitCode := dockerCmd(t, "run", "-d", "-v", "/foo", "-v", tmpDir+"/test:/test", "-v", tmpDir+":/baz", "busybox", "/bin/sh", "-c", "touch /foo/bar")
out, exitCode := dockerCmd(c, "run", "-d", "-v", "/foo", "-v", tmpDir+"/test:/test", "-v", tmpDir+":/baz", "busybox", "/bin/sh", "-c", "touch /foo/bar")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer dockerCmd(t, "rm", "-fv", cleanedContainerID)
defer dockerCmd(c, "rm", "-fv", cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
// Copy actual volume path
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/foo", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/foo", outDir)
stat, err := os.Stat(outDir + "/foo")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !stat.IsDir() {
t.Fatal("expected copied content to be dir")
c.Fatal("expected copied content to be dir")
}
stat, err = os.Stat(outDir + "/foo/bar")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if stat.IsDir() {
t.Fatal("Expected file `bar` to be a file")
c.Fatal("Expected file `bar` to be a file")
}
// Copy file nested in volume
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/foo/bar", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/foo/bar", outDir)
stat, err = os.Stat(outDir + "/bar")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if stat.IsDir() {
t.Fatal("Expected file `bar` to be a file")
c.Fatal("Expected file `bar` to be a file")
}
// Copy Bind-mounted dir
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/baz", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/baz", outDir)
stat, err = os.Stat(outDir + "/baz")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !stat.IsDir() {
t.Fatal("Expected `baz` to be a dir")
c.Fatal("Expected `baz` to be a dir")
}
// Copy file nested in bind-mounted dir
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/baz/test", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/baz/test", outDir)
fb, err := ioutil.ReadFile(outDir + "/baz/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
fb2, err := ioutil.ReadFile(tmpDir + "/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !bytes.Equal(fb, fb2) {
t.Fatalf("Expected copied file to be duplicate of bind-mounted file")
c.Fatalf("Expected copied file to be duplicate of bind-mounted file")
}
// Copy bind-mounted file
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/test", outDir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/test", outDir)
fb, err = ioutil.ReadFile(outDir + "/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
fb2, err = ioutil.ReadFile(tmpDir + "/test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !bytes.Equal(fb, fb2) {
t.Fatalf("Expected copied file to be duplicate of bind-mounted file")
c.Fatalf("Expected copied file to be duplicate of bind-mounted file")
}
logDone("cp - volume path")
}
func TestCpToDot(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test")
func (s *DockerSuite) TestCpToDot(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpdir)
cwd, err := os.Getwd()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.Chdir(cwd)
if err := os.Chdir(tmpdir); err != nil {
t.Fatal(err)
c.Fatal(err)
}
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/test", ".")
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/test", ".")
content, err := ioutil.ReadFile("./test")
if string(content) != "lololol\n" {
t.Fatalf("Wrong content in copied file %q, should be %q", content, "lololol\n")
c.Fatalf("Wrong content in copied file %q, should be %q", content, "lololol\n")
}
logDone("cp - to dot path")
}
func TestCpToStdout(t *testing.T) {
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test")
func (s *DockerSuite) TestCpToStdout(c *check.C) {
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /test")
if exitCode != 0 {
t.Fatalf("failed to create a container:%s\n", out)
c.Fatalf("failed to create a container:%s\n", out)
}
cID := strings.TrimSpace(out)
defer deleteContainer(cID)
out, _ = dockerCmd(t, "wait", cID)
out, _ = dockerCmd(c, "wait", cID)
if strings.TrimSpace(out) != "0" {
t.Fatalf("failed to set up container:%s\n", out)
c.Fatalf("failed to set up container:%s\n", out)
}
out, _, err := runCommandPipelineWithOutput(
@ -579,40 +571,38 @@ func TestCpToStdout(t *testing.T) {
exec.Command("tar", "-vtf", "-"))
if err != nil {
t.Fatalf("Failed to run commands: %s", err)
c.Fatalf("Failed to run commands: %s", err)
}
if !strings.Contains(out, "test") || !strings.Contains(out, "-rw") {
t.Fatalf("Missing file from tar TOC:\n%s", out)
c.Fatalf("Missing file from tar TOC:\n%s", out)
}
logDone("cp - to stdout")
}
func TestCpNameHasColon(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestCpNameHasColon(c *check.C) {
testRequires(c, SameHostDaemon)
out, exitCode := dockerCmd(t, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /te:s:t")
out, exitCode := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "echo lololol > /te:s:t")
if exitCode != 0 {
t.Fatal("failed to create a container", out)
c.Fatal("failed to create a container", out)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
out, _ = dockerCmd(t, "wait", cleanedContainerID)
out, _ = dockerCmd(c, "wait", cleanedContainerID)
if strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out)
c.Fatal("failed to set up container", out)
}
tmpdir, err := ioutil.TempDir("", "docker-integration")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpdir)
_, _ = dockerCmd(t, "cp", cleanedContainerID+":/te:s:t", tmpdir)
_, _ = dockerCmd(c, "cp", cleanedContainerID+":/te:s:t", tmpdir)
content, err := ioutil.ReadFile(tmpdir + "/te:s:t")
if string(content) != "lololol\n" {
t.Fatalf("Wrong content in copied file %q, should be %q", content, "lololol\n")
c.Fatalf("Wrong content in copied file %q, should be %q", content, "lololol\n")
}
logDone("cp - copy filename has ':'")
}

View file

@ -6,20 +6,19 @@ import (
"os/exec"
"reflect"
"strings"
"testing"
"time"
"github.com/docker/docker/nat"
"github.com/go-check/check"
)
// Make sure we can create a simple container with some args
func TestCreateArgs(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateArgs(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "busybox", "command", "arg1", "arg2", "arg with space")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -27,7 +26,7 @@ func TestCreateArgs(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
containers := []struct {
@ -38,40 +37,38 @@ func TestCreateArgs(t *testing.T) {
Image string
}{}
if err := json.Unmarshal([]byte(out), &containers); err != nil {
t.Fatalf("Error inspecting the container: %s", err)
c.Fatalf("Error inspecting the container: %s", err)
}
if len(containers) != 1 {
t.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
c.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
}
c := containers[0]
if c.Path != "command" {
t.Fatalf("Unexpected container path. Expected command, received: %s", c.Path)
cont := containers[0]
if cont.Path != "command" {
c.Fatalf("Unexpected container path. Expected command, received: %s", cont.Path)
}
b := false
expected := []string{"arg1", "arg2", "arg with space"}
for i, arg := range expected {
if arg != c.Args[i] {
if arg != cont.Args[i] {
b = true
break
}
}
if len(c.Args) != len(expected) || b {
t.Fatalf("Unexpected args. Expected %v, received: %v", expected, c.Args)
if len(cont.Args) != len(expected) || b {
c.Fatalf("Unexpected args. Expected %v, received: %v", expected, cont.Args)
}
logDone("create - args")
}
// Make sure we can set hostconfig options too
func TestCreateHostConfig(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateHostConfig(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "-P", "busybox", "echo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -79,7 +76,7 @@ func TestCreateHostConfig(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
containers := []struct {
@ -88,31 +85,29 @@ func TestCreateHostConfig(t *testing.T) {
}
}{}
if err := json.Unmarshal([]byte(out), &containers); err != nil {
t.Fatalf("Error inspecting the container: %s", err)
c.Fatalf("Error inspecting the container: %s", err)
}
if len(containers) != 1 {
t.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
c.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
}
c := containers[0]
if c.HostConfig == nil {
t.Fatalf("Expected HostConfig, got none")
cont := containers[0]
if cont.HostConfig == nil {
c.Fatalf("Expected HostConfig, got none")
}
if !c.HostConfig.PublishAllPorts {
t.Fatalf("Expected PublishAllPorts, got false")
if !cont.HostConfig.PublishAllPorts {
c.Fatalf("Expected PublishAllPorts, got false")
}
logDone("create - hostconfig")
}
func TestCreateWithPortRange(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateWithPortRange(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "-p", "3300-3303:3300-3303/tcp", "busybox", "echo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -120,7 +115,7 @@ func TestCreateWithPortRange(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
containers := []struct {
@ -129,39 +124,37 @@ func TestCreateWithPortRange(t *testing.T) {
}
}{}
if err := json.Unmarshal([]byte(out), &containers); err != nil {
t.Fatalf("Error inspecting the container: %s", err)
c.Fatalf("Error inspecting the container: %s", err)
}
if len(containers) != 1 {
t.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
c.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
}
c := containers[0]
if c.HostConfig == nil {
t.Fatalf("Expected HostConfig, got none")
cont := containers[0]
if cont.HostConfig == nil {
c.Fatalf("Expected HostConfig, got none")
}
if len(c.HostConfig.PortBindings) != 4 {
t.Fatalf("Expected 4 ports bindings, got %d", len(c.HostConfig.PortBindings))
if len(cont.HostConfig.PortBindings) != 4 {
c.Fatalf("Expected 4 ports bindings, got %d", len(cont.HostConfig.PortBindings))
}
for k, v := range c.HostConfig.PortBindings {
for k, v := range cont.HostConfig.PortBindings {
if len(v) != 1 {
t.Fatalf("Expected 1 ports binding, for the port %s but found %s", k, v)
c.Fatalf("Expected 1 ports binding, for the port %s but found %s", k, v)
}
if k.Port() != v[0].HostPort {
t.Fatalf("Expected host port %d to match published port %d", k.Port(), v[0].HostPort)
c.Fatalf("Expected host port %d to match published port %d", k.Port(), v[0].HostPort)
}
}
logDone("create - port range")
}
func TestCreateWithiLargePortRange(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateWithiLargePortRange(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "-p", "1-65535:1-65535/tcp", "busybox", "echo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -169,7 +162,7 @@ func TestCreateWithiLargePortRange(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
containers := []struct {
@ -178,40 +171,38 @@ func TestCreateWithiLargePortRange(t *testing.T) {
}
}{}
if err := json.Unmarshal([]byte(out), &containers); err != nil {
t.Fatalf("Error inspecting the container: %s", err)
c.Fatalf("Error inspecting the container: %s", err)
}
if len(containers) != 1 {
t.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
c.Fatalf("Unexpected container count. Expected 0, received: %d", len(containers))
}
c := containers[0]
if c.HostConfig == nil {
t.Fatalf("Expected HostConfig, got none")
cont := containers[0]
if cont.HostConfig == nil {
c.Fatalf("Expected HostConfig, got none")
}
if len(c.HostConfig.PortBindings) != 65535 {
t.Fatalf("Expected 65535 ports bindings, got %d", len(c.HostConfig.PortBindings))
if len(cont.HostConfig.PortBindings) != 65535 {
c.Fatalf("Expected 65535 ports bindings, got %d", len(cont.HostConfig.PortBindings))
}
for k, v := range c.HostConfig.PortBindings {
for k, v := range cont.HostConfig.PortBindings {
if len(v) != 1 {
t.Fatalf("Expected 1 ports binding, for the port %s but found %s", k, v)
c.Fatalf("Expected 1 ports binding, for the port %s but found %s", k, v)
}
if k.Port() != v[0].HostPort {
t.Fatalf("Expected host port %d to match published port %d", k.Port(), v[0].HostPort)
c.Fatalf("Expected host port %d to match published port %d", k.Port(), v[0].HostPort)
}
}
logDone("create - large port range")
}
// "test123" should be printed by docker create + start
func TestCreateEchoStdout(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestCreateEchoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "busybox", "echo", "test123")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -219,62 +210,58 @@ func TestCreateEchoStdout(t *testing.T) {
runCmd = exec.Command(dockerBinary, "start", "-ai", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out != "test123\n" {
t.Errorf("container should've printed 'test123', got %q", out)
c.Errorf("container should've printed 'test123', got %q", out)
}
logDone("create - echo test123")
}
func TestCreateVolumesCreated(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestCreateVolumesCreated(c *check.C) {
testRequires(c, SameHostDaemon)
name := "test_create_volume"
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "--name", name, "-v", "/foo", "busybox")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
dir, err := inspectFieldMap(name, "Volumes", "/foo")
if err != nil {
t.Fatalf("Error getting volume host path: %q", err)
c.Fatalf("Error getting volume host path: %q", err)
}
if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
t.Fatalf("Volume was not created")
c.Fatalf("Volume was not created")
}
if err != nil {
t.Fatalf("Error statting volume host path: %q", err)
c.Fatalf("Error statting volume host path: %q", err)
}
logDone("create - volumes are created")
}
func TestCreateLabels(t *testing.T) {
func (s *DockerSuite) TestCreateLabels(c *check.C) {
name := "test_create_labels"
expected := map[string]string{"k1": "v1", "k2": "v2"}
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "--name", name, "-l", "k1=v1", "--label", "k2=v2", "busybox")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
actual := make(map[string]string)
err := inspectFieldAndMarshall(name, "Config.Labels", &actual)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %s got %s", expected, actual)
c.Fatalf("Expected %s got %s", expected, actual)
}
deleteAllContainers()
logDone("create - labels")
}
func TestCreateLabelFromImage(t *testing.T) {
func (s *DockerSuite) TestCreateLabelFromImage(c *check.C) {
imageName := "testcreatebuildlabel"
defer deleteImages(imageName)
_, err := buildImage(imageName,
@ -282,34 +269,32 @@ func TestCreateLabelFromImage(t *testing.T) {
LABEL k1=v1 k2=v2`,
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
name := "test_create_labels_from_image"
expected := map[string]string{"k2": "x", "k3": "v3", "k1": "v1"}
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "--name", name, "-l", "k2=x", "--label", "k3=v3", imageName)); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
actual := make(map[string]string)
err = inspectFieldAndMarshall(name, "Config.Labels", &actual)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected %s got %s", expected, actual)
c.Fatalf("Expected %s got %s", expected, actual)
}
deleteAllContainers()
logDone("create - labels from image")
}
func TestCreateHostnameWithNumber(t *testing.T) {
out, _ := dockerCmd(t, "run", "-h", "web.0", "busybox", "hostname")
func (s *DockerSuite) TestCreateHostnameWithNumber(c *check.C) {
out, _ := dockerCmd(c, "run", "-h", "web.0", "busybox", "hostname")
if strings.TrimSpace(out) != "web.0" {
t.Fatalf("hostname not set, expected `web.0`, got: %s", out)
c.Fatalf("hostname not set, expected `web.0`, got: %s", out)
}
logDone("create - use hostname with number")
}

File diff suppressed because it is too large Load diff

View file

@ -3,16 +3,17 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// ensure that an added file shows up in docker diff
func TestDiffFilenameShownInOutput(t *testing.T) {
func (s *DockerSuite) TestDiffFilenameShownInOutput(c *check.C) {
containerCmd := `echo foo > /root/bar`
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", containerCmd)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to start the container: %s, %v", out, err)
c.Fatalf("failed to start the container: %s, %v", out, err)
}
cleanCID := strings.TrimSpace(out)
@ -20,7 +21,7 @@ func TestDiffFilenameShownInOutput(t *testing.T) {
diffCmd := exec.Command(dockerBinary, "diff", cleanCID)
out, _, err = runCommandWithOutput(diffCmd)
if err != nil {
t.Fatalf("failed to run diff: %s %v", out, err)
c.Fatalf("failed to run diff: %s %v", out, err)
}
found := false
@ -31,15 +32,12 @@ func TestDiffFilenameShownInOutput(t *testing.T) {
}
}
if !found {
t.Errorf("couldn't find the new file in docker diff's output: %v", out)
c.Errorf("couldn't find the new file in docker diff's output: %v", out)
}
deleteContainer(cleanCID)
logDone("diff - check if created file shows up")
}
// test to ensure GH #3840 doesn't occur any more
func TestDiffEnsureDockerinitFilesAreIgnored(t *testing.T) {
func (s *DockerSuite) TestDiffEnsureDockerinitFilesAreIgnored(c *check.C) {
// this is a list of files which shouldn't show up in `docker diff`
dockerinitFiles := []string{"/etc/resolv.conf", "/etc/hostname", "/etc/hosts", "/.dockerinit", "/.dockerenv"}
@ -49,7 +47,7 @@ func TestDiffEnsureDockerinitFilesAreIgnored(t *testing.T) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", containerCmd)
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanCID := strings.TrimSpace(out)
@ -57,26 +55,22 @@ func TestDiffEnsureDockerinitFilesAreIgnored(t *testing.T) {
diffCmd := exec.Command(dockerBinary, "diff", cleanCID)
out, _, err = runCommandWithOutput(diffCmd)
if err != nil {
t.Fatalf("failed to run diff: %s, %v", out, err)
c.Fatalf("failed to run diff: %s, %v", out, err)
}
deleteContainer(cleanCID)
for _, filename := range dockerinitFiles {
if strings.Contains(out, filename) {
t.Errorf("found file which should've been ignored %v in diff output", filename)
c.Errorf("found file which should've been ignored %v in diff output", filename)
}
}
}
logDone("diff - check if ignored files show up in diff")
}
func TestDiffEnsureOnlyKmsgAndPtmx(t *testing.T) {
func (s *DockerSuite) TestDiffEnsureOnlyKmsgAndPtmx(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sleep", "0")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanCID := strings.TrimSpace(out)
@ -84,9 +78,8 @@ func TestDiffEnsureOnlyKmsgAndPtmx(t *testing.T) {
diffCmd := exec.Command(dockerBinary, "diff", cleanCID)
out, _, err = runCommandWithOutput(diffCmd)
if err != nil {
t.Fatalf("failed to run diff: %s, %v", out, err)
c.Fatalf("failed to run diff: %s, %v", out, err)
}
deleteContainer(cleanCID)
expected := map[string]bool{
"C /dev": true,
@ -109,9 +102,7 @@ func TestDiffEnsureOnlyKmsgAndPtmx(t *testing.T) {
for _, line := range strings.Split(out, "\n") {
if line != "" && !expected[line] {
t.Errorf("%q is shown in the diff but shouldn't", line)
c.Errorf("%q is shown in the diff but shouldn't", line)
}
}
logDone("diff - ensure that only kmsg and ptmx in diff")
}

View file

@ -7,20 +7,21 @@ import (
"regexp"
"strconv"
"strings"
"testing"
"time"
"github.com/go-check/check"
)
func TestEventsUntag(t *testing.T) {
func (s *DockerSuite) TestEventsUntag(c *check.C) {
image := "busybox"
dockerCmd(t, "tag", image, "utest:tag1")
dockerCmd(t, "tag", image, "utest:tag2")
dockerCmd(t, "rmi", "utest:tag1")
dockerCmd(t, "rmi", "utest:tag2")
dockerCmd(c, "tag", image, "utest:tag1")
dockerCmd(c, "tag", image, "utest:tag2")
dockerCmd(c, "rmi", "utest:tag1")
dockerCmd(c, "rmi", "utest:tag2")
eventsCmd := exec.Command(dockerBinary, "events", "--since=1")
out, exitCode, _, err := runCommandWithOutputForDuration(eventsCmd, time.Duration(time.Millisecond*200))
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events - exit code %d: %s", exitCode, err)
c.Fatalf("Failed to get events - exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
nEvents := len(events)
@ -29,126 +30,119 @@ func TestEventsUntag(t *testing.T) {
// looking for.
for _, v := range events[nEvents-3 : nEvents-1] {
if !strings.Contains(v, "untag") {
t.Fatalf("event should be untag, not %#v", v)
c.Fatalf("event should be untag, not %#v", v)
}
}
logDone("events - untags are logged")
}
func TestEventsContainerFailStartDie(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestEventsContainerFailStartDie(c *check.C) {
out, _ := dockerCmd(t, "images", "-q")
out, _ := dockerCmd(c, "images", "-q")
image := strings.Split(out, "\n")[0]
eventsCmd := exec.Command(dockerBinary, "run", "--name", "testeventdie", image, "blerg")
_, _, err := runCommandWithOutput(eventsCmd)
if err == nil {
t.Fatalf("Container run with command blerg should have failed, but it did not")
c.Fatalf("Container run with command blerg should have failed, but it did not")
}
eventsCmd = exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd = exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= 1 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
c.Fatalf("event should be start, not %#v", startEvent)
}
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
c.Fatalf("event should be die, not %#v", dieEvent)
}
logDone("events - container unwilling to start logs die")
}
func TestEventsLimit(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestEventsLimit(c *check.C) {
for i := 0; i < 30; i++ {
dockerCmd(t, "run", "busybox", "echo", strconv.Itoa(i))
dockerCmd(c, "run", "busybox", "echo", strconv.Itoa(i))
}
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ := runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
nEvents := len(events) - 1
if nEvents != 64 {
t.Fatalf("events should be limited to 64, but received %d", nEvents)
c.Fatalf("events should be limited to 64, but received %d", nEvents)
}
logDone("events - limited to 64 entries")
}
func TestEventsContainerEvents(t *testing.T) {
dockerCmd(t, "run", "--rm", "busybox", "true")
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
func (s *DockerSuite) TestEventsContainerEvents(c *check.C) {
dockerCmd(c, "run", "--rm", "busybox", "true")
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, exitCode, err := runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
c.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) < 4 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
createEvent := strings.Fields(events[len(events)-4])
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
destroyEvent := strings.Fields(events[len(events)-1])
if createEvent[len(createEvent)-1] != "create" {
t.Fatalf("event should be create, not %#v", createEvent)
c.Fatalf("event should be create, not %#v", createEvent)
}
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
c.Fatalf("event should be start, not %#v", startEvent)
}
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
c.Fatalf("event should be die, not %#v", dieEvent)
}
if destroyEvent[len(destroyEvent)-1] != "destroy" {
t.Fatalf("event should be destroy, not %#v", destroyEvent)
c.Fatalf("event should be destroy, not %#v", destroyEvent)
}
logDone("events - container create, start, die, destroy is logged")
}
func TestEventsContainerEventsSinceUnixEpoch(t *testing.T) {
dockerCmd(t, "run", "--rm", "busybox", "true")
func (s *DockerSuite) TestEventsContainerEventsSinceUnixEpoch(c *check.C) {
dockerCmd(c, "run", "--rm", "busybox", "true")
timeBeginning := time.Unix(0, 0).Format(time.RFC3339Nano)
timeBeginning = strings.Replace(timeBeginning, "Z", ".000000000Z", -1)
eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since='%s'", timeBeginning),
fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, exitCode, err := runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
c.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) < 4 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
createEvent := strings.Fields(events[len(events)-4])
startEvent := strings.Fields(events[len(events)-3])
dieEvent := strings.Fields(events[len(events)-2])
destroyEvent := strings.Fields(events[len(events)-1])
if createEvent[len(createEvent)-1] != "create" {
t.Fatalf("event should be create, not %#v", createEvent)
c.Fatalf("event should be create, not %#v", createEvent)
}
if startEvent[len(startEvent)-1] != "start" {
t.Fatalf("event should be start, not %#v", startEvent)
c.Fatalf("event should be start, not %#v", startEvent)
}
if dieEvent[len(dieEvent)-1] != "die" {
t.Fatalf("event should be die, not %#v", dieEvent)
c.Fatalf("event should be die, not %#v", dieEvent)
}
if destroyEvent[len(destroyEvent)-1] != "destroy" {
t.Fatalf("event should be destroy, not %#v", destroyEvent)
c.Fatalf("event should be destroy, not %#v", destroyEvent)
}
logDone("events - container create, start, die, destroy since Unix Epoch time")
}
func TestEventsImageUntagDelete(t *testing.T) {
func (s *DockerSuite) TestEventsImageUntagDelete(c *check.C) {
name := "testimageevents"
defer deleteImages(name)
_, err := buildImage(name,
@ -156,67 +150,64 @@ func TestEventsImageUntagDelete(t *testing.T) {
MAINTAINER "docker"`,
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := deleteImages(name); err != nil {
t.Fatal(err)
c.Fatal(err)
}
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, exitCode, err := runCommandWithOutput(eventsCmd)
if exitCode != 0 || err != nil {
t.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
c.Fatalf("Failed to get events with exit code %d: %s", exitCode, err)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) < 2 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
untagEvent := strings.Fields(events[len(events)-2])
deleteEvent := strings.Fields(events[len(events)-1])
if untagEvent[len(untagEvent)-1] != "untag" {
t.Fatalf("untag should be untag, not %#v", untagEvent)
c.Fatalf("untag should be untag, not %#v", untagEvent)
}
if deleteEvent[len(deleteEvent)-1] != "delete" {
t.Fatalf("delete should be delete, not %#v", deleteEvent)
c.Fatalf("delete should be delete, not %#v", deleteEvent)
}
logDone("events - image untag, delete is logged")
}
func TestEventsImagePull(t *testing.T) {
since := daemonTime(t).Unix()
testRequires(t, Network)
func (s *DockerSuite) TestEventsImagePull(c *check.C) {
since := daemonTime(c).Unix()
testRequires(c, Network)
defer deleteImages("hello-world")
pullCmd := exec.Command(dockerBinary, "pull", "hello-world")
if out, _, err := runCommandWithOutput(pullCmd); err != nil {
t.Fatalf("pulling the hello-world image from has failed: %s, %v", out, err)
c.Fatalf("pulling the hello-world image from has failed: %s, %v", out, err)
}
eventsCmd := exec.Command(dockerBinary, "events",
fmt.Sprintf("--since=%d", since),
fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ := runCommandWithOutput(eventsCmd)
events := strings.Split(strings.TrimSpace(out), "\n")
event := strings.TrimSpace(events[len(events)-1])
if !strings.HasSuffix(event, "hello-world:latest: pull") {
t.Fatalf("Missing pull event - got:%q", event)
c.Fatalf("Missing pull event - got:%q", event)
}
logDone("events - image pull is logged")
}
func TestEventsImageImport(t *testing.T) {
defer deleteAllContainers()
since := daemonTime(t).Unix()
func (s *DockerSuite) TestEventsImageImport(c *check.C) {
since := daemonTime(c).Unix()
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -225,25 +216,24 @@ func TestEventsImageImport(t *testing.T) {
exec.Command(dockerBinary, "import", "-"),
)
if err != nil {
t.Errorf("import failed with errors: %v, output: %q", err, out)
c.Errorf("import failed with errors: %v, output: %q", err, out)
}
eventsCmd := exec.Command(dockerBinary, "events",
fmt.Sprintf("--since=%d", since),
fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(strings.TrimSpace(out), "\n")
event := strings.TrimSpace(events[len(events)-1])
if !strings.HasSuffix(event, ": import") {
t.Fatalf("Missing import event - got:%q", event)
c.Fatalf("Missing import event - got:%q", event)
}
logDone("events - image import is logged")
}
func TestEventsFilters(t *testing.T) {
func (s *DockerSuite) TestEventsFilters(c *check.C) {
parseEvents := func(out, match string) {
events := strings.Split(out, "\n")
events = events[:len(events)-1]
@ -251,67 +241,65 @@ func TestEventsFilters(t *testing.T) {
eventFields := strings.Fields(event)
eventName := eventFields[len(eventFields)-1]
if ok, err := regexp.MatchString(match, eventName); err != nil || !ok {
t.Fatalf("event should match %s, got %#v, err: %v", match, eventFields, err)
c.Fatalf("event should match %s, got %#v, err: %v", match, eventFields, err)
}
}
}
since := daemonTime(t).Unix()
since := daemonTime(c).Unix()
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", "busybox", "true"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", "busybox", "true"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(t).Unix()), "--filter", "event=die"))
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=die"))
if err != nil {
t.Fatalf("Failed to get events: %s", err)
c.Fatalf("Failed to get events: %s", err)
}
parseEvents(out, "die")
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(t).Unix()), "--filter", "event=die", "--filter", "event=start"))
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", "event=die", "--filter", "event=start"))
if err != nil {
t.Fatalf("Failed to get events: %s", err)
c.Fatalf("Failed to get events: %s", err)
}
parseEvents(out, "((die)|(start))")
// make sure we at least got 2 start events
count := strings.Count(out, "start")
if count < 2 {
t.Fatalf("should have had 2 start events but had %d, out: %s", count, out)
c.Fatalf("should have had 2 start events but had %d, out: %s", count, out)
}
logDone("events - filters")
}
func TestEventsFilterImageName(t *testing.T) {
since := daemonTime(t).Unix()
defer deleteAllContainers()
func (s *DockerSuite) TestEventsFilterImageName(c *check.C) {
since := daemonTime(c).Unix()
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_1", "-d", "busybox:latest", "true"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
container1 := strings.TrimSpace(out)
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "container_2", "-d", "busybox", "true"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
container2 := strings.TrimSpace(out)
s := "busybox"
eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(t).Unix()), "--filter", fmt.Sprintf("image=%s", s))
name := "busybox"
eventsCmd := exec.Command(dockerBinary, "events", fmt.Sprintf("--since=%d", since), fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "--filter", fmt.Sprintf("image=%s", name))
out, _, err = runCommandWithOutput(eventsCmd)
if err != nil {
t.Fatalf("Failed to get events, error: %s(%s)", err, out)
c.Fatalf("Failed to get events, error: %s(%s)", err, out)
}
events := strings.Split(out, "\n")
events = events[:len(events)-1]
if len(events) == 0 {
t.Fatalf("Expected events but found none for the image busybox:latest")
c.Fatalf("Expected events but found none for the image busybox:latest")
}
count1 := 0
count2 := 0
@ -324,27 +312,25 @@ func TestEventsFilterImageName(t *testing.T) {
}
}
if count1 == 0 || count2 == 0 {
t.Fatalf("Expected events from each container but got %d from %s and %d from %s", count1, container1, count2, container2)
c.Fatalf("Expected events from each container but got %d from %s and %d from %s", count1, container1, count2, container2)
}
logDone("events - filters using image")
}
func TestEventsFilterContainer(t *testing.T) {
defer deleteAllContainers()
since := fmt.Sprintf("%d", daemonTime(t).Unix())
func (s *DockerSuite) TestEventsFilterContainer(c *check.C) {
since := fmt.Sprintf("%d", daemonTime(c).Unix())
nameID := make(map[string]string)
for _, name := range []string{"container_1", "container_2"} {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", name, "busybox", "true"))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
nameID[name] = strings.TrimSpace(out)
waitInspect(name, "{{.State.Runing }}", "false", 5)
}
until := fmt.Sprintf("%d", daemonTime(t).Unix())
until := fmt.Sprintf("%d", daemonTime(c).Unix())
checkEvents := func(id string, events []string) error {
if len(events) != 3 { // create, start, die
@ -370,32 +356,31 @@ func TestEventsFilterContainer(t *testing.T) {
eventsCmd := exec.Command(dockerBinary, "events", "--since", since, "--until", until, "--filter", "container="+name)
out, _, err := runCommandWithOutput(eventsCmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
events := strings.Split(strings.TrimSuffix(out, "\n"), "\n")
if err := checkEvents(ID, events); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// filter by ID's
eventsCmd = exec.Command(dockerBinary, "events", "--since", since, "--until", until, "--filter", "container="+ID)
out, _, err = runCommandWithOutput(eventsCmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
events = strings.Split(strings.TrimSuffix(out, "\n"), "\n")
if err := checkEvents(ID, events); err != nil {
t.Fatal(err)
c.Fatal(err)
}
}
logDone("events - filters using container name")
}
func TestEventsStreaming(t *testing.T) {
start := daemonTime(t).Unix()
func (s *DockerSuite) TestEventsStreaming(c *check.C) {
start := daemonTime(c).Unix()
finish := make(chan struct{})
defer close(finish)
@ -409,11 +394,11 @@ func TestEventsStreaming(t *testing.T) {
eventsCmd := exec.Command(dockerBinary, "events", "--since", strconv.FormatInt(start, 10))
stdout, err := eventsCmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
err = eventsCmd.Start()
if err != nil {
t.Fatalf("failed to start 'docker events': %s", err)
c.Fatalf("failed to start 'docker events': %s", err)
}
go func() {
@ -444,35 +429,35 @@ func TestEventsStreaming(t *testing.T) {
err = eventsCmd.Wait()
if err != nil && !IsKilled(err) {
t.Fatalf("docker events had bad exit status: %s", err)
c.Fatalf("docker events had bad exit status: %s", err)
}
}()
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox:latest", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
id <- cleanedContainerID
select {
case <-time.After(5 * time.Second):
t.Fatal("failed to observe container create in timely fashion")
c.Fatal("failed to observe container create in timely fashion")
case <-eventCreate:
// ignore, done
}
select {
case <-time.After(5 * time.Second):
t.Fatal("failed to observe container start in timely fashion")
c.Fatal("failed to observe container start in timely fashion")
case <-eventStart:
// ignore, done
}
select {
case <-time.After(5 * time.Second):
t.Fatal("failed to observe container die in timely fashion")
c.Fatal("failed to observe container die in timely fashion")
case <-eventDie:
// ignore, done
}
@ -480,15 +465,14 @@ func TestEventsStreaming(t *testing.T) {
rmCmd := exec.Command(dockerBinary, "rm", cleanedContainerID)
out, _, err = runCommandWithOutput(rmCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
select {
case <-time.After(5 * time.Second):
t.Fatal("failed to observe container destroy in timely fashion")
c.Fatal("failed to observe container destroy in timely fashion")
case <-eventDestroy:
// ignore, done
}
logDone("events - streamed to stdout")
}

View file

@ -8,48 +8,46 @@ import (
"io/ioutil"
"os"
"os/exec"
"testing"
"unicode"
"github.com/go-check/check"
"github.com/kr/pty"
)
// #5979
func TestEventsRedirectStdout(t *testing.T) {
since := daemonTime(t).Unix()
dockerCmd(t, "run", "busybox", "true")
defer deleteAllContainers()
func (s *DockerSuite) TestEventsRedirectStdout(c *check.C) {
since := daemonTime(c).Unix()
dockerCmd(c, "run", "busybox", "true")
file, err := ioutil.TempFile("", "")
if err != nil {
t.Fatalf("could not create temp file: %v", err)
c.Fatalf("could not create temp file: %v", err)
}
defer os.Remove(file.Name())
command := fmt.Sprintf("%s events --since=%d --until=%d > %s", dockerBinary, since, daemonTime(t).Unix(), file.Name())
command := fmt.Sprintf("%s events --since=%d --until=%d > %s", dockerBinary, since, daemonTime(c).Unix(), file.Name())
_, tty, err := pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd := exec.Command("sh", "-c", command)
cmd.Stdin = tty
cmd.Stdout = tty
cmd.Stderr = tty
if err := cmd.Run(); err != nil {
t.Fatalf("run err for command %q: %v", command, err)
c.Fatalf("run err for command %q: %v", command, err)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
for _, c := range scanner.Text() {
if unicode.IsControl(c) {
t.Fatalf("found control character %v", []byte(string(c)))
for _, ch := range scanner.Text() {
if unicode.IsControl(ch) {
c.Fatalf("found control character %v", []byte(string(ch)))
}
}
}
if err := scanner.Err(); err != nil {
t.Fatalf("Scan err for command %q: %v", command, err)
c.Fatalf("Scan err for command %q: %v", command, err)
}
logDone("events - redirect stdout")
}

View file

@ -12,38 +12,36 @@ import (
"sort"
"strings"
"sync"
"testing"
"time"
"github.com/go-check/check"
)
func TestExec(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExec(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && top")
if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
execCmd := exec.Command(dockerBinary, "exec", "testing", "cat", "/tmp/file")
out, _, err := runCommandWithOutput(execCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
if expected := "test"; out != expected {
t.Errorf("container exec should've printed %q but printed %q", expected, out)
c.Errorf("container exec should've printed %q but printed %q", expected, out)
}
logDone("exec - basic test")
}
func TestExecInteractiveStdinClose(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecInteractiveStdinClose(c *check.C) {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-itd", "busybox", "/bin/cat"))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
contId := strings.TrimSpace(out)
@ -55,16 +53,16 @@ func TestExecInteractiveStdinClose(t *testing.T) {
cmd := exec.Command(dockerBinary, "exec", "-i", contId, "/bin/ls", "/")
cmd.Stdin = os.Stdin
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatal(err, string(out))
c.Fatal(err, string(out))
}
if string(out) == "" {
t.Fatalf("Output was empty, likely blocked by standard input")
c.Fatalf("Output was empty, likely blocked by standard input")
}
returnchan <- struct{}{}
@ -73,163 +71,153 @@ func TestExecInteractiveStdinClose(t *testing.T) {
select {
case <-returnchan:
case <-time.After(10 * time.Second):
t.Fatal("timed out running docker exec")
c.Fatal("timed out running docker exec")
}
logDone("exec - interactive mode closes stdin after execution")
}
func TestExecInteractive(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecInteractive(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "sh", "-c", "echo test > /tmp/file && top")
if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
execCmd := exec.Command(dockerBinary, "exec", "-i", "testing", "sh")
stdin, err := execCmd.StdinPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
stdout, err := execCmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := execCmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if _, err := stdin.Write([]byte("cat /tmp/file\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
r := bufio.NewReader(stdout)
line, err := r.ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
line = strings.TrimSpace(line)
if line != "test" {
t.Fatalf("Output should be 'test', got '%q'", line)
c.Fatalf("Output should be 'test', got '%q'", line)
}
if err := stdin.Close(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
finish := make(chan struct{})
go func() {
if err := execCmd.Wait(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
close(finish)
}()
select {
case <-finish:
case <-time.After(1 * time.Second):
t.Fatal("docker exec failed to exit on stdin close")
c.Fatal("docker exec failed to exit on stdin close")
}
logDone("exec - Interactive test")
}
func TestExecAfterContainerRestart(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecAfterContainerRestart(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "exec", cleanedContainerID, "echo", "hello")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
outStr := strings.TrimSpace(out)
if outStr != "hello" {
t.Errorf("container should've printed hello, instead printed %q", outStr)
c.Errorf("container should've printed hello, instead printed %q", outStr)
}
logDone("exec - exec running container after container restart")
}
func TestExecAfterDaemonRestart(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestExecAfterDaemonRestart(c *check.C) {
testRequires(c, SameHostDaemon)
d := NewDaemon(t)
d := NewDaemon(c)
if err := d.StartWithBusybox(); err != nil {
t.Fatalf("Could not start daemon with busybox: %v", err)
c.Fatalf("Could not start daemon with busybox: %v", err)
}
defer d.Stop()
if out, err := d.Cmd("run", "-d", "--name", "top", "-p", "80", "busybox:latest", "top"); err != nil {
t.Fatalf("Could not run top: err=%v\n%s", err, out)
c.Fatalf("Could not run top: err=%v\n%s", err, out)
}
if err := d.Restart(); err != nil {
t.Fatalf("Could not restart daemon: %v", err)
c.Fatalf("Could not restart daemon: %v", err)
}
if out, err := d.Cmd("start", "top"); err != nil {
t.Fatalf("Could not start top after daemon restart: err=%v\n%s", err, out)
c.Fatalf("Could not start top after daemon restart: err=%v\n%s", err, out)
}
out, err := d.Cmd("exec", "top", "echo", "hello")
if err != nil {
t.Fatalf("Could not exec on container top: err=%v\n%s", err, out)
c.Fatalf("Could not exec on container top: err=%v\n%s", err, out)
}
outStr := strings.TrimSpace(string(out))
if outStr != "hello" {
t.Errorf("container should've printed hello, instead printed %q", outStr)
c.Errorf("container should've printed hello, instead printed %q", outStr)
}
logDone("exec - exec running container after daemon restart")
}
// Regression test for #9155, #9044
func TestExecEnv(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecEnv(c *check.C) {
runCmd := exec.Command(dockerBinary, "run",
"-e", "LALA=value1",
"-e", "LALA=value2",
"-d", "--name", "testing", "busybox", "top")
if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
execCmd := exec.Command(dockerBinary, "exec", "testing", "env")
out, _, err := runCommandWithOutput(execCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if strings.Contains(out, "LALA=value1") ||
!strings.Contains(out, "LALA=value2") ||
!strings.Contains(out, "HOME=/root") {
t.Errorf("exec env(%q), expect %q, %q", out, "LALA=value2", "HOME=/root")
c.Errorf("exec env(%q), expect %q, %q", out, "LALA=value2", "HOME=/root")
}
logDone("exec - exec inherits correct env")
}
func TestExecExitStatus(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecExitStatus(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "top", "busybox", "top")
if out, _, _, err := runCommandWithStdoutStderr(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// Test normal (non-detached) case first
@ -237,20 +225,18 @@ func TestExecExitStatus(t *testing.T) {
ec, _ := runCommand(cmd)
if ec != 23 {
t.Fatalf("Should have had an ExitCode of 23, not: %d", ec)
c.Fatalf("Should have had an ExitCode of 23, not: %d", ec)
}
logDone("exec - exec non-zero ExitStatus")
}
func TestExecPausedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecPausedContainer(c *check.C) {
defer unpauseAllContainers()
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ContainerID := strings.TrimSpace(out)
@ -258,82 +244,78 @@ func TestExecPausedContainer(t *testing.T) {
pausedCmd := exec.Command(dockerBinary, "pause", "testing")
out, _, _, err = runCommandWithStdoutStderr(pausedCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
execCmd := exec.Command(dockerBinary, "exec", "-i", "-t", ContainerID, "echo", "hello")
out, _, err = runCommandWithOutput(execCmd)
if err == nil {
t.Fatal("container should fail to exec new command if it is paused")
c.Fatal("container should fail to exec new command if it is paused")
}
expected := ContainerID + " is paused, unpause the container before exec"
if !strings.Contains(out, expected) {
t.Fatal("container should not exec new command if it is paused")
c.Fatal("container should not exec new command if it is paused")
}
logDone("exec - exec should not exec a pause container")
}
// regression test for #9476
func TestExecTtyCloseStdin(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecTtyCloseStdin(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "-it", "--name", "exec_tty_stdin", "busybox")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd = exec.Command(dockerBinary, "exec", "-i", "exec_tty_stdin", "cat")
stdinRw, err := cmd.StdinPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
stdinRw.Write([]byte("test"))
stdinRw.Close()
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd = exec.Command(dockerBinary, "top", "exec_tty_stdin")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
outArr := strings.Split(out, "\n")
if len(outArr) > 3 || strings.Contains(out, "nsenter-exec") {
// This is the really bad part
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rm", "-f", "exec_tty_stdin")); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
t.Fatalf("exec process left running\n\t %s", out)
c.Fatalf("exec process left running\n\t %s", out)
}
logDone("exec - stdin is closed properly with tty enabled")
}
func TestExecTtyWithoutStdin(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecTtyWithoutStdin(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "-ti", "busybox")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to start container: %v (%v)", out, err)
c.Fatalf("failed to start container: %v (%v)", out, err)
}
id := strings.TrimSpace(out)
if err := waitRun(id); err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer func() {
cmd := exec.Command(dockerBinary, "kill", id)
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatalf("failed to kill container: %v (%v)", out, err)
c.Fatalf("failed to kill container: %v (%v)", out, err)
}
}()
@ -343,86 +325,80 @@ func TestExecTtyWithoutStdin(t *testing.T) {
cmd := exec.Command(dockerBinary, "exec", "-ti", id, "true")
if _, err := cmd.StdinPipe(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
expected := "cannot enable tty mode"
if out, _, err := runCommandWithOutput(cmd); err == nil {
t.Fatal("exec should have failed")
c.Fatal("exec should have failed")
} else if !strings.Contains(out, expected) {
t.Fatalf("exec failed with error %q: expected %q", out, expected)
c.Fatalf("exec failed with error %q: expected %q", out, expected)
}
}()
select {
case <-done:
case <-time.After(3 * time.Second):
t.Fatal("exec is running but should have failed")
c.Fatal("exec is running but should have failed")
}
logDone("exec - forbid piped stdin to tty enabled container")
}
func TestExecParseError(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecParseError(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "top", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// Test normal (non-detached) case first
cmd := exec.Command(dockerBinary, "exec", "top")
if _, stderr, code, err := runCommandWithStdoutStderr(cmd); err == nil || !strings.Contains(stderr, "See '"+dockerBinary+" exec --help'") || code == 0 {
t.Fatalf("Should have thrown error & point to help: %s", stderr)
c.Fatalf("Should have thrown error & point to help: %s", stderr)
}
logDone("exec - error on parseExec should point to help")
}
func TestExecStopNotHanging(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecStopNotHanging(c *check.C) {
if out, err := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top").CombinedOutput(); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if err := exec.Command(dockerBinary, "exec", "testing", "top").Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
wait := make(chan struct{})
go func() {
if out, err := exec.Command(dockerBinary, "stop", "testing").CombinedOutput(); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
close(wait)
}()
select {
case <-time.After(3 * time.Second):
t.Fatal("Container stop timed out")
c.Fatal("Container stop timed out")
case <-wait:
}
logDone("exec - container with exec not hanging on stop")
}
func TestExecCgroup(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecCgroup(c *check.C) {
var cmd *exec.Cmd
cmd = exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top")
_, err := runCommand(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "exec", "testing", "cat", "/proc/1/cgroup")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerCgroups := sort.StringSlice(strings.Split(string(out), "\n"))
var wg sync.WaitGroup
var s sync.Mutex
var mu sync.Mutex
execCgroups := []sort.StringSlice{}
// exec a few times concurrently to get consistent failure
for i := 0; i < 5; i++ {
@ -431,13 +407,13 @@ func TestExecCgroup(t *testing.T) {
cmd := exec.Command(dockerBinary, "exec", "testing", "cat", "/proc/self/cgroup")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cg := sort.StringSlice(strings.Split(string(out), "\n"))
s.Lock()
mu.Lock()
execCgroups = append(execCgroups, cg)
s.Unlock()
mu.Unlock()
wg.Done()
}()
}
@ -454,86 +430,81 @@ func TestExecCgroup(t *testing.T) {
for _, name := range containerCgroups {
fmt.Printf(" %s\n", name)
}
t.Fatal("cgroups mismatched")
c.Fatal("cgroups mismatched")
}
}
logDone("exec - exec has the container cgroups")
}
func TestInspectExecID(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestInspectExecID(c *check.C) {
out, exitCode, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox", "top"))
if exitCode != 0 || err != nil {
t.Fatalf("failed to run container: %s, %v", out, err)
c.Fatalf("failed to run container: %s, %v", out, err)
}
id := strings.TrimSuffix(out, "\n")
out, err = inspectField(id, "ExecIDs")
if err != nil {
t.Fatalf("failed to inspect container: %s, %v", out, err)
c.Fatalf("failed to inspect container: %s, %v", out, err)
}
if out != "<no value>" {
t.Fatalf("ExecIDs should be empty, got: %s", out)
c.Fatalf("ExecIDs should be empty, got: %s", out)
}
exitCode, err = runCommand(exec.Command(dockerBinary, "exec", "-d", id, "ls", "/"))
if exitCode != 0 || err != nil {
t.Fatalf("failed to exec in container: %s, %v", out, err)
c.Fatalf("failed to exec in container: %s, %v", out, err)
}
out, err = inspectField(id, "ExecIDs")
if err != nil {
t.Fatalf("failed to inspect container: %s, %v", out, err)
c.Fatalf("failed to inspect container: %s, %v", out, err)
}
out = strings.TrimSuffix(out, "\n")
if out == "[]" || out == "<no value>" {
t.Fatalf("ExecIDs should not be empty, got: %s", out)
c.Fatalf("ExecIDs should not be empty, got: %s", out)
}
logDone("inspect - inspect a container with ExecIDs")
}
func TestLinksPingLinkedContainersOnRename(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksPingLinkedContainersOnRename(c *check.C) {
var out string
out, _ = dockerCmd(t, "run", "-d", "--name", "container1", "busybox", "top")
out, _ = dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
idA := strings.TrimSpace(out)
if idA == "" {
t.Fatal(out, "id should not be nil")
c.Fatal(out, "id should not be nil")
}
out, _ = dockerCmd(t, "run", "-d", "--link", "container1:alias1", "--name", "container2", "busybox", "top")
out, _ = dockerCmd(c, "run", "-d", "--link", "container1:alias1", "--name", "container2", "busybox", "top")
idB := strings.TrimSpace(out)
if idB == "" {
t.Fatal(out, "id should not be nil")
c.Fatal(out, "id should not be nil")
}
execCmd := exec.Command(dockerBinary, "exec", "container2", "ping", "-c", "1", "alias1", "-W", "1")
out, _, err := runCommandWithOutput(execCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
dockerCmd(t, "rename", "container1", "container_new")
dockerCmd(c, "rename", "container1", "container_new")
execCmd = exec.Command(dockerBinary, "exec", "container2", "ping", "-c", "1", "alias1", "-W", "1")
out, _, err = runCommandWithOutput(execCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
logDone("links - ping linked container upon rename")
}
func TestRunExecDir(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestRunExecDir(c *check.C) {
testRequires(c, SameHostDaemon)
cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
id := strings.TrimSpace(out)
execDir := filepath.Join(execDriverPath, id)
@ -542,92 +513,90 @@ func TestRunExecDir(t *testing.T) {
{
fi, err := os.Stat(execDir)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !fi.IsDir() {
t.Fatalf("%q must be a directory", execDir)
c.Fatalf("%q must be a directory", execDir)
}
fi, err = os.Stat(stateFile)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
}
stopCmd := exec.Command(dockerBinary, "stop", id)
out, _, err = runCommandWithOutput(stopCmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
{
_, err := os.Stat(execDir)
if err == nil {
t.Fatal(err)
c.Fatal(err)
}
if err == nil {
t.Fatalf("Exec directory %q exists for removed container!", execDir)
c.Fatalf("Exec directory %q exists for removed container!", execDir)
}
if !os.IsNotExist(err) {
t.Fatalf("Error should be about non-existing, got %s", err)
c.Fatalf("Error should be about non-existing, got %s", err)
}
}
startCmd := exec.Command(dockerBinary, "start", id)
out, _, err = runCommandWithOutput(startCmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
{
fi, err := os.Stat(execDir)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if !fi.IsDir() {
t.Fatalf("%q must be a directory", execDir)
c.Fatalf("%q must be a directory", execDir)
}
fi, err = os.Stat(stateFile)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
}
rmCmd := exec.Command(dockerBinary, "rm", "-f", id)
out, _, err = runCommandWithOutput(rmCmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
{
_, err := os.Stat(execDir)
if err == nil {
t.Fatal(err)
c.Fatal(err)
}
if err == nil {
t.Fatalf("Exec directory %q is exists for removed container!", execDir)
c.Fatalf("Exec directory %q is exists for removed container!", execDir)
}
if !os.IsNotExist(err) {
t.Fatalf("Error should be about non-existing, got %s", err)
c.Fatalf("Error should be about non-existing, got %s", err)
}
}
logDone("run - check execdriver dir behavior")
}
func TestRunMutableNetworkFiles(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestRunMutableNetworkFiles(c *check.C) {
testRequires(c, SameHostDaemon)
for _, fn := range []string{"resolv.conf", "hosts"} {
deleteAllContainers()
content, err := runCommandAndReadContainerFile(fn, exec.Command(dockerBinary, "run", "-d", "--name", "c1", "busybox", "sh", "-c", fmt.Sprintf("echo success >/etc/%s && top", fn)))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(string(content)) != "success" {
t.Fatal("Content was not what was modified in the container", string(content))
c.Fatal("Content was not what was modified in the container", string(content))
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "c2", "busybox", "top"))
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
contID := strings.TrimSpace(out)
@ -636,88 +605,83 @@ func TestRunMutableNetworkFiles(t *testing.T) {
f, err := os.OpenFile(netFilePath, os.O_WRONLY|os.O_SYNC|os.O_APPEND, 0644)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if _, err := f.Seek(0, 0); err != nil {
f.Close()
t.Fatal(err)
c.Fatal(err)
}
if err := f.Truncate(0); err != nil {
f.Close()
t.Fatal(err)
c.Fatal(err)
}
if _, err := f.Write([]byte("success2\n")); err != nil {
f.Close()
t.Fatal(err)
c.Fatal(err)
}
f.Close()
res, err := exec.Command(dockerBinary, "exec", contID, "cat", "/etc/"+fn).CombinedOutput()
if err != nil {
t.Fatalf("Output: %s, error: %s", res, err)
c.Fatalf("Output: %s, error: %s", res, err)
}
if string(res) != "success2\n" {
t.Fatalf("Expected content of %s: %q, got: %q", fn, "success2\n", res)
c.Fatalf("Expected content of %s: %q, got: %q", fn, "success2\n", res)
}
}
logDone("run - mutable network files")
}
func TestExecWithUser(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecWithUser(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd := exec.Command(dockerBinary, "exec", "-u", "1", "parent", "id")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if !strings.Contains(out, "uid=1(daemon) gid=1(daemon)") {
t.Fatalf("exec with user by id expected daemon user got %s", out)
c.Fatalf("exec with user by id expected daemon user got %s", out)
}
cmd = exec.Command(dockerBinary, "exec", "-u", "root", "parent", "id")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if !strings.Contains(out, "uid=0(root) gid=0(root)") {
t.Fatalf("exec with user by root expected root user got %s", out)
c.Fatalf("exec with user by root expected root user got %s", out)
}
logDone("exec - with user")
}
func TestExecWithPrivileged(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestExecWithPrivileged(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "--cap-drop=ALL", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd := exec.Command(dockerBinary, "exec", "parent", "sh", "-c", "mknod /tmp/sda b 8 0")
out, _, err := runCommandWithOutput(cmd)
if err == nil || !strings.Contains(out, "Operation not permitted") {
t.Fatalf("exec mknod in --cap-drop=ALL container without --privileged should failed")
c.Fatalf("exec mknod in --cap-drop=ALL container without --privileged should failed")
}
cmd = exec.Command(dockerBinary, "exec", "--privileged", "parent", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if actual := strings.TrimSpace(out); actual != "ok" {
t.Fatalf("exec mknod in --cap-drop=ALL container with --privileged failed: %v, output: %q", err, out)
c.Fatalf("exec mknod in --cap-drop=ALL container with --privileged failed: %v, output: %q", err, out)
}
logDone("exec - exec command in a container with privileged")
}

View file

@ -4,11 +4,12 @@ import (
"os"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// export an image and try to import it into a new one
func TestExportContainerAndImportImage(t *testing.T) {
func (s *DockerSuite) TestExportContainerAndImportImage(c *check.C) {
containerID := "testexportcontainerandimportimage"
defer deleteImages("repo/testexp:v1")
@ -17,39 +18,38 @@ func TestExportContainerAndImportImage(t *testing.T) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", containerID, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
inspectCmd := exec.Command(dockerBinary, "inspect", containerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("output should've been a container id: %s %s ", containerID, err)
c.Fatalf("output should've been a container id: %s %s ", containerID, err)
}
exportCmd := exec.Command(dockerBinary, "export", containerID)
if out, _, err = runCommandWithOutput(exportCmd); err != nil {
t.Fatalf("failed to export container: %s, %v", out, err)
c.Fatalf("failed to export container: %s, %v", out, err)
}
importCmd := exec.Command(dockerBinary, "import", "-", "repo/testexp:v1")
importCmd.Stdin = strings.NewReader(out)
out, _, err = runCommandWithOutput(importCmd)
if err != nil {
t.Fatalf("failed to import image: %s, %v", out, err)
c.Fatalf("failed to import image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd = exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("output should've been an image id: %s, %v", out, err)
c.Fatalf("output should've been an image id: %s, %v", out, err)
}
logDone("export - export/import a container/image")
}
// Used to test output flag in the export command
func TestExportContainerWithOutputAndImportImage(t *testing.T) {
func (s *DockerSuite) TestExportContainerWithOutputAndImportImage(c *check.C) {
containerID := "testexportcontainerwithoutputandimportimage"
defer deleteImages("repo/testexp:v1")
@ -58,40 +58,39 @@ func TestExportContainerWithOutputAndImportImage(t *testing.T) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", containerID, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
inspectCmd := exec.Command(dockerBinary, "inspect", containerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("output should've been a container id: %s %s ", containerID, err)
c.Fatalf("output should've been a container id: %s %s ", containerID, err)
}
defer os.Remove("testexp.tar")
exportCmd := exec.Command(dockerBinary, "export", "--output=testexp.tar", containerID)
if out, _, err = runCommandWithOutput(exportCmd); err != nil {
t.Fatalf("failed to export container: %s, %v", out, err)
c.Fatalf("failed to export container: %s, %v", out, err)
}
out, _, err = runCommandWithOutput(exec.Command("cat", "testexp.tar"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
importCmd := exec.Command(dockerBinary, "import", "-", "repo/testexp:v1")
importCmd.Stdin = strings.NewReader(out)
out, _, err = runCommandWithOutput(importCmd)
if err != nil {
t.Fatalf("failed to import image: %s, %v", out, err)
c.Fatalf("failed to import image: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
inspectCmd = exec.Command(dockerBinary, "inspect", cleanedImageID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("output should've been an image id: %s, %v", out, err)
c.Fatalf("output should've been an image id: %s, %v", out, err)
}
logDone("export - export/import a container/image with output flag")
}

View file

@ -5,13 +5,13 @@ import (
"os/exec"
"runtime"
"strings"
"testing"
"unicode"
"github.com/docker/docker/pkg/homedir"
"github.com/go-check/check"
)
func TestHelpTextVerify(t *testing.T) {
func (s *DockerSuite) TestHelpTextVerify(c *check.C) {
// Make sure main help text fits within 80 chars and that
// on non-windows system we use ~ when possible (to shorten things).
// Test for HOME set to its default value and set to "/" on linux
@ -51,26 +51,26 @@ func TestHelpTextVerify(t *testing.T) {
helpCmd.Env = newEnvs
out, ec, err := runCommandWithOutput(helpCmd)
if err != nil || ec != 0 {
t.Fatalf("docker help should have worked\nout:%s\nec:%d", out, ec)
c.Fatalf("docker help should have worked\nout:%s\nec:%d", out, ec)
}
lines := strings.Split(out, "\n")
for _, line := range lines {
if len(line) > 80 {
t.Fatalf("Line is too long(%d chars):\n%s", len(line), line)
c.Fatalf("Line is too long(%d chars):\n%s", len(line), line)
}
// All lines should not end with a space
if strings.HasSuffix(line, " ") {
t.Fatalf("Line should not end with a space: %s", line)
c.Fatalf("Line should not end with a space: %s", line)
}
if scanForHome && strings.Contains(line, `=`+home) {
t.Fatalf("Line should use '%q' instead of %q:\n%s", homedir.GetShortcutString(), home, line)
c.Fatalf("Line should use '%q' instead of %q:\n%s", homedir.GetShortcutString(), home, line)
}
if runtime.GOOS != "windows" {
i := strings.Index(line, homedir.GetShortcutString())
if i >= 0 && i != len(line)-1 && line[i+1] != '/' {
t.Fatalf("Main help should not have used home shortcut:\n%s", line)
c.Fatalf("Main help should not have used home shortcut:\n%s", line)
}
}
}
@ -82,11 +82,11 @@ func TestHelpTextVerify(t *testing.T) {
helpCmd.Env = newEnvs
out, ec, err = runCommandWithOutput(helpCmd)
if err != nil || ec != 0 {
t.Fatalf("docker help should have worked\nout:%s\nec:%d", out, ec)
c.Fatalf("docker help should have worked\nout:%s\nec:%d", out, ec)
}
i := strings.Index(out, "Commands:")
if i < 0 {
t.Fatalf("Missing 'Commands:' in:\n%s", out)
c.Fatalf("Missing 'Commands:' in:\n%s", out)
}
// Grab all chars starting at "Commands:"
@ -106,39 +106,39 @@ func TestHelpTextVerify(t *testing.T) {
helpCmd.Env = newEnvs
out, ec, err := runCommandWithOutput(helpCmd)
if err != nil || ec != 0 {
t.Fatalf("Error on %q help: %s\nexit code:%d", cmd, out, ec)
c.Fatalf("Error on %q help: %s\nexit code:%d", cmd, out, ec)
}
lines := strings.Split(out, "\n")
for _, line := range lines {
if len(line) > 80 {
t.Fatalf("Help for %q is too long(%d chars):\n%s", cmd,
c.Fatalf("Help for %q is too long(%d chars):\n%s", cmd,
len(line), line)
}
if scanForHome && strings.Contains(line, `"`+home) {
t.Fatalf("Help for %q should use ~ instead of %q on:\n%s",
c.Fatalf("Help for %q should use ~ instead of %q on:\n%s",
cmd, home, line)
}
i := strings.Index(line, "~")
if i >= 0 && i != len(line)-1 && line[i+1] != '/' {
t.Fatalf("Help for %q should not have used ~:\n%s", cmd, line)
c.Fatalf("Help for %q should not have used ~:\n%s", cmd, line)
}
// If a line starts with 4 spaces then assume someone
// added a multi-line description for an option and we need
// to flag it
if strings.HasPrefix(line, " ") {
t.Fatalf("Help for %q should not have a multi-line option: %s", cmd, line)
c.Fatalf("Help for %q should not have a multi-line option: %s", cmd, line)
}
// Options should NOT end with a period
if strings.HasPrefix(line, " -") && strings.HasSuffix(line, ".") {
t.Fatalf("Help for %q should not end with a period: %s", cmd, line)
c.Fatalf("Help for %q should not end with a period: %s", cmd, line)
}
// Options should NOT end with a space
if strings.HasSuffix(line, " ") {
t.Fatalf("Help for %q should not end with a space: %s", cmd, line)
c.Fatalf("Help for %q should not end with a space: %s", cmd, line)
}
}
@ -146,10 +146,9 @@ func TestHelpTextVerify(t *testing.T) {
expected := 39
if len(cmds) != expected {
t.Fatalf("Wrong # of cmds(%d), it should be: %d\nThe list:\n%q",
c.Fatalf("Wrong # of cmds(%d), it should be: %d\nThe list:\n%q",
len(cmds), expected, cmds)
}
}
logDone("help - verify text")
}

View file

@ -4,12 +4,13 @@ import (
"fmt"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// This is a heisen-test. Because the created timestamp of images and the behavior of
// sort is not predictable it doesn't always fail.
func TestBuildHistory(t *testing.T) {
func (s *DockerSuite) TestBuildHistory(c *check.C) {
name := "testbuildhistory"
defer deleteImages(name)
_, err := buildImage(name, `FROM busybox
@ -42,12 +43,12 @@ RUN echo "Z"`,
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, exitCode, err := runCommandWithOutput(exec.Command(dockerBinary, "history", "testbuildhistory"))
if err != nil || exitCode != 0 {
t.Fatalf("failed to get image history: %s, %v", out, err)
c.Fatalf("failed to get image history: %s, %v", out, err)
}
actualValues := strings.Split(out, "\n")[1:27]
@ -58,32 +59,29 @@ RUN echo "Z"`,
actualValue := actualValues[i]
if !strings.Contains(actualValue, echoValue) {
t.Fatalf("Expected layer \"%s\", but was: %s", expectedValues[i], actualValue)
c.Fatalf("Expected layer \"%s\", but was: %s", expectedValues[i], actualValue)
}
}
logDone("history - build history")
}
func TestHistoryExistentImage(t *testing.T) {
func (s *DockerSuite) TestHistoryExistentImage(c *check.C) {
historyCmd := exec.Command(dockerBinary, "history", "busybox")
_, exitCode, err := runCommandWithOutput(historyCmd)
if err != nil || exitCode != 0 {
t.Fatal("failed to get image history")
c.Fatal("failed to get image history")
}
logDone("history - history on existent image must pass")
}
func TestHistoryNonExistentImage(t *testing.T) {
func (s *DockerSuite) TestHistoryNonExistentImage(c *check.C) {
historyCmd := exec.Command(dockerBinary, "history", "testHistoryNonExistentImage")
_, exitCode, err := runCommandWithOutput(historyCmd)
if err == nil || exitCode == 0 {
t.Fatal("history on a non-existent image didn't result in a non-zero exit status")
c.Fatal("history on a non-existent image didn't result in a non-zero exit status")
}
logDone("history - history on non-existent image must pass")
}
func TestHistoryImageWithComment(t *testing.T) {
func (s *DockerSuite) TestHistoryImageWithComment(c *check.C) {
name := "testhistoryimagewithcomment"
defer deleteContainer(name)
defer deleteImages(name)
@ -93,26 +91,26 @@ func TestHistoryImageWithComment(t *testing.T) {
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to run container: %s, %v", out, err)
c.Fatalf("failed to run container: %s, %v", out, err)
}
waitCmd := exec.Command(dockerBinary, "wait", name)
if out, _, err := runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("error thrown while waiting for container: %s, %v", out, err)
c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
}
comment := "This_is_a_comment"
commitCmd := exec.Command(dockerBinary, "commit", "-m="+comment, name, name)
if out, _, err := runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container to image: %s, %v", out, err)
c.Fatalf("failed to commit container to image: %s, %v", out, err)
}
// test docker history <image id> to check comment messages
historyCmd := exec.Command(dockerBinary, "history", name)
out, exitCode, err := runCommandWithOutput(historyCmd)
if err != nil || exitCode != 0 {
t.Fatalf("failed to get image history: %s, %v", out, err)
c.Fatalf("failed to get image history: %s, %v", out, err)
}
outputTabs := strings.Fields(strings.Split(out, "\n")[1])
@ -120,8 +118,7 @@ func TestHistoryImageWithComment(t *testing.T) {
actualValue := outputTabs[len(outputTabs)-1]
if !strings.Contains(actualValue, comment) {
t.Fatalf("Expected comments %q, but found %q", comment, actualValue)
c.Fatalf("Expected comments %q, but found %q", comment, actualValue)
}
logDone("history - history on image with comment")
}

View file

@ -6,27 +6,26 @@ import (
"reflect"
"sort"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/stringid"
"github.com/go-check/check"
)
func TestImagesEnsureImageIsListed(t *testing.T) {
func (s *DockerSuite) TestImagesEnsureImageIsListed(c *check.C) {
imagesCmd := exec.Command(dockerBinary, "images")
out, _, err := runCommandWithOutput(imagesCmd)
if err != nil {
t.Fatalf("listing images failed with errors: %s, %v", out, err)
c.Fatalf("listing images failed with errors: %s, %v", out, err)
}
if !strings.Contains(out, "busybox") {
t.Fatal("images should've listed busybox")
c.Fatal("images should've listed busybox")
}
logDone("images - busybox should be listed")
}
func TestImagesOrderedByCreationDate(t *testing.T) {
func (s *DockerSuite) TestImagesOrderedByCreationDate(c *check.C) {
defer deleteImages("order:test_a")
defer deleteImages("order:test_c")
defer deleteImages("order:test_b")
@ -34,56 +33,53 @@ func TestImagesOrderedByCreationDate(t *testing.T) {
`FROM scratch
MAINTAINER dockerio1`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(time.Second)
id2, err := buildImage("order:test_c",
`FROM scratch
MAINTAINER dockerio2`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(time.Second)
id3, err := buildImage("order:test_b",
`FROM scratch
MAINTAINER dockerio3`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "images", "-q", "--no-trunc"))
if err != nil {
t.Fatalf("listing images failed with errors: %s, %v", out, err)
c.Fatalf("listing images failed with errors: %s, %v", out, err)
}
imgs := strings.Split(out, "\n")
if imgs[0] != id3 {
t.Fatalf("First image must be %s, got %s", id3, imgs[0])
c.Fatalf("First image must be %s, got %s", id3, imgs[0])
}
if imgs[1] != id2 {
t.Fatalf("Second image must be %s, got %s", id2, imgs[1])
c.Fatalf("Second image must be %s, got %s", id2, imgs[1])
}
if imgs[2] != id1 {
t.Fatalf("Third image must be %s, got %s", id1, imgs[2])
c.Fatalf("Third image must be %s, got %s", id1, imgs[2])
}
logDone("images - ordering by creation date")
}
func TestImagesErrorWithInvalidFilterNameTest(t *testing.T) {
func (s *DockerSuite) TestImagesErrorWithInvalidFilterNameTest(c *check.C) {
imagesCmd := exec.Command(dockerBinary, "images", "-f", "FOO=123")
out, _, err := runCommandWithOutput(imagesCmd)
if !strings.Contains(out, "Invalid filter") {
t.Fatalf("error should occur when listing images with invalid filter name FOO, %s, %v", out, err)
c.Fatalf("error should occur when listing images with invalid filter name FOO, %s, %v", out, err)
}
logDone("images - invalid filter name check working")
}
func TestImagesFilterLabel(t *testing.T) {
func (s *DockerSuite) TestImagesFilterLabel(c *check.C) {
imageName1 := "images_filter_test1"
imageName2 := "images_filter_test2"
imageName3 := "images_filter_test3"
defer deleteAllContainers()
defer deleteImages(imageName1)
defer deleteImages(imageName2)
defer deleteImages(imageName3)
@ -91,51 +87,49 @@ func TestImagesFilterLabel(t *testing.T) {
`FROM scratch
LABEL match me`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
image2ID, err := buildImage(imageName2,
`FROM scratch
LABEL match="me too"`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
image3ID, err := buildImage(imageName3,
`FROM scratch
LABEL nomatch me`, true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd := exec.Command(dockerBinary, "images", "--no-trunc", "-q", "-f", "label=match")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.TrimSpace(out)
if (!strings.Contains(out, image1ID) && !strings.Contains(out, image2ID)) || strings.Contains(out, image3ID) {
t.Fatalf("Expected ids %s,%s got %s", image1ID, image2ID, out)
c.Fatalf("Expected ids %s,%s got %s", image1ID, image2ID, out)
}
cmd = exec.Command(dockerBinary, "images", "--no-trunc", "-q", "-f", "label=match=me too")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.TrimSpace(out)
if out != image2ID {
t.Fatalf("Expected %s got %s", image2ID, out)
c.Fatalf("Expected %s got %s", image2ID, out)
}
logDone("images - filter label")
}
func TestImagesFilterWhiteSpaceTrimmingAndLowerCasingWorking(t *testing.T) {
func (s *DockerSuite) TestImagesFilterSpaceTrimCase(c *check.C) {
imageName := "images_filter_test"
defer deleteAllContainers()
defer deleteImages(imageName)
buildImage(imageName,
`FROM scratch
@ -156,7 +150,7 @@ func TestImagesFilterWhiteSpaceTrimmingAndLowerCasingWorking(t *testing.T) {
cmd := exec.Command(dockerBinary, "images", "-q", "-f", filter)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
listing := strings.Split(out, "\n")
sort.Strings(listing)
@ -172,50 +166,47 @@ func TestImagesFilterWhiteSpaceTrimmingAndLowerCasingWorking(t *testing.T) {
}
fmt.Print("")
}
t.Fatalf("All output must be the same")
c.Fatalf("All output must be the same")
}
}
logDone("images - white space trimming and lower casing")
}
func TestImagesEnsureDanglingImageOnlyListedOnce(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestImagesEnsureDanglingImageOnlyListedOnce(c *check.C) {
// create container 1
c := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(c)
cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error running busybox: %s, %v", out, err)
c.Fatalf("error running busybox: %s, %v", out, err)
}
containerId1 := strings.TrimSpace(out)
// tag as foobox
c = exec.Command(dockerBinary, "commit", containerId1, "foobox")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "commit", containerId1, "foobox")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error tagging foobox: %s", err)
c.Fatalf("error tagging foobox: %s", err)
}
imageId := stringid.TruncateID(strings.TrimSpace(out))
defer deleteImages(imageId)
// overwrite the tag, making the previous image dangling
c = exec.Command(dockerBinary, "tag", "-f", "busybox", "foobox")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "tag", "-f", "busybox", "foobox")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("error tagging foobox: %s", err)
c.Fatalf("error tagging foobox: %s", err)
}
defer deleteImages("foobox")
c = exec.Command(dockerBinary, "images", "-q", "-f", "dangling=true")
out, _, err = runCommandWithOutput(c)
cmd = exec.Command(dockerBinary, "images", "-q", "-f", "dangling=true")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("listing images failed with errors: %s, %v", out, err)
c.Fatalf("listing images failed with errors: %s, %v", out, err)
}
if e, a := 1, strings.Count(out, imageId); e != a {
t.Fatalf("expected 1 dangling image, got %d: %s", a, out)
c.Fatalf("expected 1 dangling image, got %d: %s", a, out)
}
logDone("images - dangling image only listed once")
}

View file

@ -3,14 +3,15 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestImportDisplay(t *testing.T) {
func (s *DockerSuite) TestImportDisplay(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
@ -20,11 +21,11 @@ func TestImportDisplay(t *testing.T) {
exec.Command(dockerBinary, "import", "-"),
)
if err != nil {
t.Errorf("import failed with errors: %v, output: %q", err, out)
c.Errorf("import failed with errors: %v, output: %q", err, out)
}
if n := strings.Count(out, "\n"); n != 1 {
t.Fatalf("display is messed up: %d '\\n' instead of 1:\n%s", n, out)
c.Fatalf("display is messed up: %d '\\n' instead of 1:\n%s", n, out)
}
image := strings.TrimSpace(out)
defer deleteImages(image)
@ -32,12 +33,11 @@ func TestImportDisplay(t *testing.T) {
runCmd = exec.Command(dockerBinary, "run", "--rm", image, "true")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal("failed to create a container", out, err)
c.Fatal("failed to create a container", out, err)
}
if out != "" {
t.Fatalf("command output should've been nothing, was %q", out)
c.Fatalf("command output should've been nothing, was %q", out)
}
logDone("import - display is fine, imported image runs")
}

View file

@ -3,15 +3,16 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// ensure docker info succeeds
func TestInfoEnsureSucceeds(t *testing.T) {
func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
versionCmd := exec.Command(dockerBinary, "info")
out, exitCode, err := runCommandWithOutput(versionCmd)
if err != nil || exitCode != 0 {
t.Fatalf("failed to execute docker info: %s, %v", out, err)
c.Fatalf("failed to execute docker info: %s, %v", out, err)
}
// always shown fields
@ -29,9 +30,8 @@ func TestInfoEnsureSucceeds(t *testing.T) {
for _, linePrefix := range stringsToCheck {
if !strings.Contains(out, linePrefix) {
t.Errorf("couldn't find string %v in output", linePrefix)
c.Errorf("couldn't find string %v in output", linePrefix)
}
}
logDone("info - verify that it works")
}

View file

@ -3,21 +3,21 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestInspectImage(t *testing.T) {
func (s *DockerSuite) TestInspectImage(c *check.C) {
imageTest := "emptyfs"
imageTestID := "511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158"
imagesCmd := exec.Command(dockerBinary, "inspect", "--format='{{.Id}}'", imageTest)
out, exitCode, err := runCommandWithOutput(imagesCmd)
if exitCode != 0 || err != nil {
t.Fatalf("failed to inspect image: %s, %v", out, err)
c.Fatalf("failed to inspect image: %s, %v", out, err)
}
if id := strings.TrimSuffix(out, "\n"); id != imageTestID {
t.Fatalf("Expected id: %s for image: %s but received id: %s", imageTestID, imageTest, id)
c.Fatalf("Expected id: %s for image: %s but received id: %s", imageTestID, imageTest, id)
}
logDone("inspect - inspect an image")
}

View file

@ -3,73 +3,72 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestKillContainer(t *testing.T) {
func (s *DockerSuite) TestKillContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
t.Fatalf("failed to kill container: %s, %v", out, err)
c.Fatalf("failed to kill container: %s, %v", out, err)
}
listRunningContainersCmd := exec.Command(dockerBinary, "ps", "-q")
out, _, err = runCommandWithOutput(listRunningContainersCmd)
if err != nil {
t.Fatalf("failed to list running containers: %s, %v", out, err)
c.Fatalf("failed to list running containers: %s, %v", out, err)
}
if strings.Contains(out, cleanedContainerID) {
t.Fatal("killed container is still running")
c.Fatal("killed container is still running")
}
deleteContainer(cleanedContainerID)
logDone("kill - kill container running top")
}
func TestKillDifferentUserContainer(t *testing.T) {
func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-u", "daemon", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("out should've been a container id: %s, %v", out, err)
c.Fatalf("out should've been a container id: %s, %v", out, err)
}
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
t.Fatalf("failed to kill container: %s, %v", out, err)
c.Fatalf("failed to kill container: %s, %v", out, err)
}
listRunningContainersCmd := exec.Command(dockerBinary, "ps", "-q")
out, _, err = runCommandWithOutput(listRunningContainersCmd)
if err != nil {
t.Fatalf("failed to list running containers: %s, %v", out, err)
c.Fatalf("failed to list running containers: %s, %v", out, err)
}
if strings.Contains(out, cleanedContainerID) {
t.Fatal("killed container is still running")
c.Fatal("killed container is still running")
}
deleteContainer(cleanedContainerID)
logDone("kill - kill container running top from a different user")
}

View file

@ -8,89 +8,81 @@ import (
"reflect"
"regexp"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/iptables"
"github.com/go-check/check"
)
func TestLinksEtcHostsRegularFile(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksEtcHostsRegularFile(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--net=host", "busybox", "ls", "-la", "/etc/hosts")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !strings.HasPrefix(out, "-") {
t.Errorf("/etc/hosts should be a regular file")
c.Errorf("/etc/hosts should be a regular file")
}
logDone("link - /etc/hosts is a regular file")
}
func TestLinksEtcHostsContentMatch(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestLinksEtcHostsContentMatch(c *check.C) {
testRequires(c, SameHostDaemon)
runCmd := exec.Command(dockerBinary, "run", "--net=host", "busybox", "cat", "/etc/hosts")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
hosts, err := ioutil.ReadFile("/etc/hosts")
if os.IsNotExist(err) {
t.Skip("/etc/hosts does not exist, skip this test")
c.Skip("/etc/hosts does not exist, skip this test")
}
if out != string(hosts) {
t.Errorf("container")
c.Errorf("container")
}
logDone("link - /etc/hosts matches hosts copy")
}
func TestLinksPingUnlinkedContainers(t *testing.T) {
func (s *DockerSuite) TestLinksPingUnlinkedContainers(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--rm", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
exitCode, err := runCommand(runCmd)
if exitCode == 0 {
t.Fatal("run ping did not fail")
c.Fatal("run ping did not fail")
} else if exitCode != 1 {
t.Fatalf("run ping failed with errors: %v", err)
c.Fatalf("run ping failed with errors: %v", err)
}
logDone("links - ping unlinked container")
}
// Test for appropriate error when calling --link with an invalid target container
func TestLinksInvalidContainerTarget(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksInvalidContainerTarget(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--link", "bogus:alias", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err == nil {
t.Fatal("an invalid container target should produce an error")
c.Fatal("an invalid container target should produce an error")
}
if !strings.Contains(out, "Could not get container") {
t.Fatalf("error output expected 'Could not get container', but got %q instead; err: %v", out, err)
c.Fatalf("error output expected 'Could not get container', but got %q instead; err: %v", out, err)
}
logDone("links - linking to non-existent container should not work")
}
func TestLinksPingLinkedContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksPingLinkedContainers(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "container1", "--hostname", "fred", "busybox", "top")
if _, err := runCommand(runCmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "run", "-d", "--name", "container2", "--hostname", "wilma", "busybox", "top")
if _, err := runCommand(runCmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
runArgs := []string{"run", "--rm", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "sh", "-c"}
@ -98,74 +90,68 @@ func TestLinksPingLinkedContainers(t *testing.T) {
// test ping by alias, ping by name, and ping by hostname
// 1. Ping by alias
dockerCmd(t, append(runArgs, fmt.Sprintf(pingCmd, "alias1", "alias2"))...)
dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "alias1", "alias2"))...)
// 2. Ping by container name
dockerCmd(t, append(runArgs, fmt.Sprintf(pingCmd, "container1", "container2"))...)
dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "container1", "container2"))...)
// 3. Ping by hostname
dockerCmd(t, append(runArgs, fmt.Sprintf(pingCmd, "fred", "wilma"))...)
dockerCmd(c, append(runArgs, fmt.Sprintf(pingCmd, "fred", "wilma"))...)
logDone("links - ping linked container")
}
func TestLinksPingLinkedContainersAfterRename(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksPingLinkedContainersAfterRename(c *check.C) {
out, _ := dockerCmd(t, "run", "-d", "--name", "container1", "busybox", "top")
out, _ := dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
idA := strings.TrimSpace(out)
out, _ = dockerCmd(t, "run", "-d", "--name", "container2", "busybox", "top")
out, _ = dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
idB := strings.TrimSpace(out)
dockerCmd(t, "rename", "container1", "container_new")
dockerCmd(t, "run", "--rm", "--link", "container_new:alias1", "--link", "container2:alias2", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
dockerCmd(t, "kill", idA)
dockerCmd(t, "kill", idB)
dockerCmd(c, "rename", "container1", "container_new")
dockerCmd(c, "run", "--rm", "--link", "container_new:alias1", "--link", "container2:alias2", "busybox", "sh", "-c", "ping -c 1 alias1 -W 1 && ping -c 1 alias2 -W 1")
dockerCmd(c, "kill", idA)
dockerCmd(c, "kill", idB)
logDone("links - ping linked container after rename")
}
func TestLinksIpTablesRulesWhenLinkAndUnlink(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestLinksIpTablesRulesWhenLinkAndUnlink(c *check.C) {
testRequires(c, SameHostDaemon)
dockerCmd(t, "run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "child", "--publish", "8080:80", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "parent", "--link", "child:http", "busybox", "top")
childIP := findContainerIP(t, "child")
parentIP := findContainerIP(t, "parent")
childIP := findContainerIP(c, "child")
parentIP := findContainerIP(c, "parent")
sourceRule := []string{"-i", "docker0", "-o", "docker0", "-p", "tcp", "-s", childIP, "--sport", "80", "-d", parentIP, "-j", "ACCEPT"}
destinationRule := []string{"-i", "docker0", "-o", "docker0", "-p", "tcp", "-s", parentIP, "--dport", "80", "-d", childIP, "-j", "ACCEPT"}
if !iptables.Exists("filter", "DOCKER", sourceRule...) || !iptables.Exists("filter", "DOCKER", destinationRule...) {
t.Fatal("Iptables rules not found")
c.Fatal("Iptables rules not found")
}
dockerCmd(t, "rm", "--link", "parent/http")
dockerCmd(c, "rm", "--link", "parent/http")
if iptables.Exists("filter", "DOCKER", sourceRule...) || iptables.Exists("filter", "DOCKER", destinationRule...) {
t.Fatal("Iptables rules should be removed when unlink")
c.Fatal("Iptables rules should be removed when unlink")
}
dockerCmd(t, "kill", "child")
dockerCmd(t, "kill", "parent")
dockerCmd(c, "kill", "child")
dockerCmd(c, "kill", "parent")
logDone("link - verify iptables when link and unlink")
}
func TestLinksInspectLinksStarted(t *testing.T) {
func (s *DockerSuite) TestLinksInspectLinksStarted(c *check.C) {
var (
expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
result []string
)
defer deleteAllContainers()
dockerCmd(t, "run", "-d", "--name", "container1", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "container2", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "top")
links, err := inspectFieldJSON("testinspectlink", "HostConfig.Links")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
err = unmarshalJSON([]byte(links), &result)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
output := convertSliceOfStringsToMap(result)
@ -173,28 +159,26 @@ func TestLinksInspectLinksStarted(t *testing.T) {
equal := reflect.DeepEqual(output, expected)
if !equal {
t.Fatalf("Links %s, expected %s", result, expected)
c.Fatalf("Links %s, expected %s", result, expected)
}
logDone("link - links in started container inspect")
}
func TestLinksInspectLinksStopped(t *testing.T) {
func (s *DockerSuite) TestLinksInspectLinksStopped(c *check.C) {
var (
expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
result []string
)
defer deleteAllContainers()
dockerCmd(t, "run", "-d", "--name", "container1", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "container2", "busybox", "top")
dockerCmd(t, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true")
dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true")
links, err := inspectFieldJSON("testinspectlink", "HostConfig.Links")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
err = unmarshalJSON([]byte(links), &result)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
output := convertSliceOfStringsToMap(result)
@ -202,47 +186,42 @@ func TestLinksInspectLinksStopped(t *testing.T) {
equal := reflect.DeepEqual(output, expected)
if !equal {
t.Fatalf("Links %s, but expected %s", result, expected)
c.Fatalf("Links %s, but expected %s", result, expected)
}
logDone("link - links in stopped container inspect")
}
func TestLinksNotStartedParentNotFail(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksNotStartedParentNotFail(c *check.C) {
runCmd := exec.Command(dockerBinary, "create", "--name=first", "busybox", "top")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "create", "--name=second", "--link=first:first", "busybox", "top")
out, _, _, err = runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "start", "first")
out, _, _, err = runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
logDone("link - container start successfully updating stopped parent links")
}
func TestLinksHostsFilesInject(t *testing.T) {
testRequires(t, SameHostDaemon, ExecSupport)
defer deleteAllContainers()
func (s *DockerSuite) TestLinksHostsFilesInject(c *check.C) {
testRequires(c, SameHostDaemon, ExecSupport)
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-itd", "--name", "one", "busybox", "top"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
idOne := strings.TrimSpace(out)
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "-itd", "--name", "two", "--link", "one:onetwo", "busybox", "top"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
idTwo := strings.TrimSpace(out)
@ -251,89 +230,83 @@ func TestLinksHostsFilesInject(t *testing.T) {
contentOne, err := readContainerFileWithExec(idOne, "/etc/hosts")
if err != nil {
t.Fatal(err, string(contentOne))
c.Fatal(err, string(contentOne))
}
contentTwo, err := readContainerFileWithExec(idTwo, "/etc/hosts")
if err != nil {
t.Fatal(err, string(contentTwo))
c.Fatal(err, string(contentTwo))
}
if !strings.Contains(string(contentTwo), "onetwo") {
t.Fatal("Host is not present in updated hosts file", string(contentTwo))
c.Fatal("Host is not present in updated hosts file", string(contentTwo))
}
logDone("link - ensure containers hosts files are updated with the link alias.")
}
func TestLinksNetworkHostContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestLinksNetworkHostContainer(c *check.C) {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--net", "host", "--name", "host_container", "busybox", "top"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "should_fail", "--link", "host_container:tester", "busybox", "true"))
if err == nil || !strings.Contains(out, "--net=host can't be used with links. This would result in undefined behavior.") {
t.Fatalf("Running container linking to a container with --net host should have failed: %s", out)
c.Fatalf("Running container linking to a container with --net host should have failed: %s", out)
}
logDone("link - error thrown when linking to container with --net host")
}
func TestLinksUpdateOnRestart(t *testing.T) {
testRequires(t, SameHostDaemon, ExecSupport)
defer deleteAllContainers()
func (s *DockerSuite) TestLinksUpdateOnRestart(c *check.C) {
testRequires(c, SameHostDaemon, ExecSupport)
if out, err := exec.Command(dockerBinary, "run", "-d", "--name", "one", "busybox", "top").CombinedOutput(); err != nil {
t.Fatal(err, string(out))
c.Fatal(err, string(out))
}
out, err := exec.Command(dockerBinary, "run", "-d", "--name", "two", "--link", "one:onetwo", "--link", "one:one", "busybox", "top").CombinedOutput()
if err != nil {
t.Fatal(err, string(out))
c.Fatal(err, string(out))
}
id := strings.TrimSpace(string(out))
realIP, err := inspectField("one", "NetworkSettings.IPAddress")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
content, err := readContainerFileWithExec(id, "/etc/hosts")
if err != nil {
t.Fatal(err, string(content))
c.Fatal(err, string(content))
}
getIP := func(hosts []byte, hostname string) string {
re := regexp.MustCompile(fmt.Sprintf(`(\S*)\t%s`, regexp.QuoteMeta(hostname)))
matches := re.FindSubmatch(hosts)
if matches == nil {
t.Fatalf("Hostname %s have no matches in hosts", hostname)
c.Fatalf("Hostname %s have no matches in hosts", hostname)
}
return string(matches[1])
}
if ip := getIP(content, "one"); ip != realIP {
t.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
c.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
}
if ip := getIP(content, "onetwo"); ip != realIP {
t.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
c.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
}
if out, err := exec.Command(dockerBinary, "restart", "one").CombinedOutput(); err != nil {
t.Fatal(err, string(out))
c.Fatal(err, string(out))
}
realIP, err = inspectField("one", "NetworkSettings.IPAddress")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
content, err = readContainerFileWithExec(id, "/etc/hosts")
if err != nil {
t.Fatal(err, string(content))
c.Fatal(err, string(content))
}
if ip := getIP(content, "one"); ip != realIP {
t.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
c.Fatalf("For 'one' alias expected IP: %s, got: %s", realIP, ip)
}
if ip := getIP(content, "onetwo"); ip != realIP {
t.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
c.Fatalf("For 'onetwo' alias expected IP: %s, got: %s", realIP, ip)
}
logDone("link - ensure containers hosts files are updated on restart")
}

View file

@ -3,10 +3,11 @@ package main
import (
"bytes"
"os/exec"
"testing"
"github.com/go-check/check"
)
func TestLoginWithoutTTY(t *testing.T) {
func (s *DockerSuite) TestLoginWithoutTTY(c *check.C) {
cmd := exec.Command(dockerBinary, "login")
// Send to stdin so the process does not get the TTY
@ -14,8 +15,7 @@ func TestLoginWithoutTTY(t *testing.T) {
// run the command and block until it's done
if err := cmd.Run(); err == nil {
t.Fatal("Expected non nil err when loginning in & TTY not available")
c.Fatal("Expected non nil err when loginning in & TTY not available")
}
logDone("login - login without TTY")
}

View file

@ -5,19 +5,19 @@ import (
"os/exec"
"regexp"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/timeutils"
"github.com/go-check/check"
)
// This used to work, it test a log of PageSize-1 (gh#4851)
func TestLogsContainerSmallerThanPage(t *testing.T) {
func (s *DockerSuite) TestLogsContainerSmallerThanPage(c *check.C) {
testLen := 32767
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -26,25 +26,24 @@ func TestLogsContainerSmallerThanPage(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if len(out) != testLen+1 {
t.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
deleteContainer(cleanedContainerID)
logDone("logs - logs container running echo smaller than page size")
}
// Regression test: When going over the PageSize, it used to panic (gh#4851)
func TestLogsContainerBiggerThanPage(t *testing.T) {
func (s *DockerSuite) TestLogsContainerBiggerThanPage(c *check.C) {
testLen := 32768
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -53,25 +52,24 @@ func TestLogsContainerBiggerThanPage(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if len(out) != testLen+1 {
t.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
deleteContainer(cleanedContainerID)
logDone("logs - logs container running echo bigger than page size")
}
// Regression test: When going much over the PageSize, it used to block (gh#4851)
func TestLogsContainerMuchBiggerThanPage(t *testing.T) {
func (s *DockerSuite) TestLogsContainerMuchBiggerThanPage(c *check.C) {
testLen := 33000
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo -n =; done; echo", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -80,25 +78,24 @@ func TestLogsContainerMuchBiggerThanPage(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if len(out) != testLen+1 {
t.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
c.Fatalf("Expected log length of %d, received %d\n", testLen+1, len(out))
}
deleteContainer(cleanedContainerID)
logDone("logs - logs container running echo much bigger than page size")
}
func TestLogsTimestamps(t *testing.T) {
func (s *DockerSuite) TestLogsTimestamps(c *check.C) {
testLen := 100
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -107,13 +104,13 @@ func TestLogsTimestamps(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", "-t", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
lines := strings.Split(out, "\n")
if len(lines) != testLen+1 {
t.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
ts := regexp.MustCompile(`^.* `)
@ -122,26 +119,25 @@ func TestLogsTimestamps(t *testing.T) {
if l != "" {
_, err := time.Parse(timeutils.RFC3339NanoFixed+" ", ts.FindString(l))
if err != nil {
t.Fatalf("Failed to parse timestamp from %v: %v", l, err)
c.Fatalf("Failed to parse timestamp from %v: %v", l, err)
}
if l[29] != 'Z' { // ensure we have padded 0's
t.Fatalf("Timestamp isn't padded properly: %s", l)
c.Fatalf("Timestamp isn't padded properly: %s", l)
}
}
}
deleteContainer(cleanedContainerID)
logDone("logs - logs with timestamps")
}
func TestLogsSeparateStderr(t *testing.T) {
func (s *DockerSuite) TestLogsSeparateStderr(c *check.C) {
msg := "stderr_log"
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -150,30 +146,29 @@ func TestLogsSeparateStderr(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
stdout, stderr, _, err := runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if stdout != "" {
t.Fatalf("Expected empty stdout stream, got %v", stdout)
c.Fatalf("Expected empty stdout stream, got %v", stdout)
}
stderr = strings.TrimSpace(stderr)
if stderr != msg {
t.Fatalf("Expected %v in stderr stream, got %v", msg, stderr)
c.Fatalf("Expected %v in stderr stream, got %v", msg, stderr)
}
deleteContainer(cleanedContainerID)
logDone("logs - separate stderr (without pseudo-tty)")
}
func TestLogsStderrInStdout(t *testing.T) {
func (s *DockerSuite) TestLogsStderrInStdout(c *check.C) {
msg := "stderr_log"
runCmd := exec.Command(dockerBinary, "run", "-d", "-t", "busybox", "sh", "-c", fmt.Sprintf("echo %s 1>&2", msg))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -182,30 +177,29 @@ func TestLogsStderrInStdout(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", cleanedContainerID)
stdout, stderr, _, err := runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
if stderr != "" {
t.Fatalf("Expected empty stderr stream, got %v", stdout)
c.Fatalf("Expected empty stderr stream, got %v", stdout)
}
stdout = strings.TrimSpace(stdout)
if stdout != msg {
t.Fatalf("Expected %v in stdout stream, got %v", msg, stdout)
c.Fatalf("Expected %v in stdout stream, got %v", msg, stdout)
}
deleteContainer(cleanedContainerID)
logDone("logs - stderr in stdout (with pseudo-tty)")
}
func TestLogsTail(t *testing.T) {
func (s *DockerSuite) TestLogsTail(c *check.C) {
testLen := 100
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", fmt.Sprintf("for i in $(seq 1 %d); do echo =; done;", testLen))
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -214,49 +208,48 @@ func TestLogsTail(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", "--tail", "5", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
lines := strings.Split(out, "\n")
if len(lines) != 6 {
t.Fatalf("Expected log %d lines, received %d\n", 6, len(lines))
c.Fatalf("Expected log %d lines, received %d\n", 6, len(lines))
}
logsCmd = exec.Command(dockerBinary, "logs", "--tail", "all", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
lines = strings.Split(out, "\n")
if len(lines) != testLen+1 {
t.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
logsCmd = exec.Command(dockerBinary, "logs", "--tail", "random", cleanedContainerID)
out, _, _, err = runCommandWithStdoutStderr(logsCmd)
if err != nil {
t.Fatalf("failed to log container: %s, %v", out, err)
c.Fatalf("failed to log container: %s, %v", out, err)
}
lines = strings.Split(out, "\n")
if len(lines) != testLen+1 {
t.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
c.Fatalf("Expected log %d lines, received %d\n", testLen+1, len(lines))
}
deleteContainer(cleanedContainerID)
logDone("logs - logs tail")
}
func TestLogsFollowStopped(t *testing.T) {
func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "hello")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -264,34 +257,33 @@ func TestLogsFollowStopped(t *testing.T) {
logsCmd := exec.Command(dockerBinary, "logs", "-f", cleanedContainerID)
if err := logsCmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
c := make(chan struct{})
ch := make(chan struct{})
go func() {
if err := logsCmd.Wait(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
close(c)
close(ch)
}()
select {
case <-c:
case <-ch:
case <-time.After(1 * time.Second):
t.Fatal("Following logs is hanged")
c.Fatal("Following logs is hanged")
}
deleteContainer(cleanedContainerID)
logDone("logs - logs follow stopped container")
}
// Regression test for #8832
func TestLogsFollowSlowStdoutConsumer(t *testing.T) {
func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", `usleep 200000;yes X | head -c 200000`)
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("run failed with errors: %s, %v", out, err)
c.Fatalf("run failed with errors: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -308,30 +300,29 @@ func TestLogsFollowSlowStdoutConsumer(t *testing.T) {
stdout, err := logCmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := logCmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
// First read slowly
bytes1, err := consumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// After the container has finished we can continue reading fast
bytes2, err := consumeWithSpeed(stdout, 32*1024, 0, nil)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
actual := bytes1 + bytes2
expected := 200000
if actual != expected {
t.Fatalf("Invalid bytes read: %d, expected %d", actual, expected)
c.Fatalf("Invalid bytes read: %d, expected %d", actual, expected)
}
logDone("logs - follow slow consumer")
}

View file

@ -5,32 +5,32 @@ import (
"net"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestNetworkNat(t *testing.T) {
testRequires(t, SameHostDaemon, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestNetworkNat(c *check.C) {
testRequires(c, SameHostDaemon, NativeExecDriver)
iface, err := net.InterfaceByName("eth0")
if err != nil {
t.Skipf("Test not running with `make test`. Interface eth0 not found: %s", err)
c.Skip(fmt.Sprintf("Test not running with `make test`. Interface eth0 not found: %v", err))
}
ifaceAddrs, err := iface.Addrs()
if err != nil || len(ifaceAddrs) == 0 {
t.Fatalf("Error retrieving addresses for eth0: %v (%d addresses)", err, len(ifaceAddrs))
c.Fatalf("Error retrieving addresses for eth0: %v (%d addresses)", err, len(ifaceAddrs))
}
ifaceIP, _, err := net.ParseCIDR(ifaceAddrs[0].String())
if err != nil {
t.Fatalf("Error retrieving the up for eth0: %s", err)
c.Fatalf("Error retrieving the up for eth0: %s", err)
}
runCmd := exec.Command(dockerBinary, "run", "-dt", "-p", "8080:8080", "busybox", "nc", "-lp", "8080")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -38,25 +38,24 @@ func TestNetworkNat(t *testing.T) {
runCmd = exec.Command(dockerBinary, "run", "busybox", "sh", "-c", fmt.Sprintf("echo hello world | nc -w 30 %s 8080", ifaceIP))
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to retrieve logs for container: %s, %v", out, err)
c.Fatalf("failed to retrieve logs for container: %s, %v", out, err)
}
out = strings.Trim(out, "\r\n")
if expected := "hello world"; out != expected {
t.Fatalf("Unexpected output. Expected: %q, received: %q for iface %s", expected, out, ifaceIP)
c.Fatalf("Unexpected output. Expected: %q, received: %q for iface %s", expected, out, ifaceIP)
}
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
t.Fatalf("failed to kill container: %s, %v", out, err)
c.Fatalf("failed to kill container: %s, %v", out, err)
}
logDone("network - make sure nat works through the host")
}

View file

@ -4,78 +4,76 @@ import (
"fmt"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestPause(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPause(c *check.C) {
defer unpauseAllContainers()
name := "testeventpause"
out, _ := dockerCmd(t, "images", "-q")
out, _ := dockerCmd(c, "images", "-q")
image := strings.Split(out, "\n")[0]
dockerCmd(t, "run", "-d", "--name", name, image, "top")
dockerCmd(c, "run", "-d", "--name", name, image, "top")
dockerCmd(t, "pause", name)
dockerCmd(c, "pause", name)
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != 1 {
t.Fatalf("there should be one paused container and not %d", len(pausedContainers))
c.Fatalf("there should be one paused container and not %d", len(pausedContainers))
}
dockerCmd(t, "unpause", name)
dockerCmd(c, "unpause", name)
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= 1 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
pauseEvent := strings.Fields(events[len(events)-3])
unpauseEvent := strings.Fields(events[len(events)-2])
if pauseEvent[len(pauseEvent)-1] != "pause" {
t.Fatalf("event should be pause, not %#v", pauseEvent)
c.Fatalf("event should be pause, not %#v", pauseEvent)
}
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
t.Fatalf("event should be unpause, not %#v", unpauseEvent)
c.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
logDone("pause - pause/unpause is logged")
}
func TestPauseMultipleContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPauseMultipleContainers(c *check.C) {
defer unpauseAllContainers()
containers := []string{
"testpausewithmorecontainers1",
"testpausewithmorecontainers2",
}
out, _ := dockerCmd(t, "images", "-q")
out, _ := dockerCmd(c, "images", "-q")
image := strings.Split(out, "\n")[0]
for _, name := range containers {
dockerCmd(t, "run", "-d", "--name", name, image, "top")
dockerCmd(c, "run", "-d", "--name", name, image, "top")
}
dockerCmd(t, append([]string{"pause"}, containers...)...)
dockerCmd(c, append([]string{"pause"}, containers...)...)
pausedContainers, err := getSliceOfPausedContainers()
if err != nil {
t.Fatalf("error thrown while checking if containers were paused: %v", err)
c.Fatalf("error thrown while checking if containers were paused: %v", err)
}
if len(pausedContainers) != len(containers) {
t.Fatalf("there should be %d paused container and not %d", len(containers), len(pausedContainers))
c.Fatalf("there should be %d paused container and not %d", len(containers), len(pausedContainers))
}
dockerCmd(t, append([]string{"unpause"}, containers...)...)
dockerCmd(c, append([]string{"unpause"}, containers...)...)
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(t).Unix()))
eventsCmd := exec.Command(dockerBinary, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()))
out, _, _ = runCommandWithOutput(eventsCmd)
events := strings.Split(out, "\n")
if len(events) <= len(containers)*3-2 {
t.Fatalf("Missing expected event")
c.Fatalf("Missing expected event")
}
pauseEvents := make([][]string, len(containers))
@ -87,14 +85,13 @@ func TestPauseMultipleContainers(t *testing.T) {
for _, pauseEvent := range pauseEvents {
if pauseEvent[len(pauseEvent)-1] != "pause" {
t.Fatalf("event should be pause, not %#v", pauseEvent)
c.Fatalf("event should be pause, not %#v", pauseEvent)
}
}
for _, unpauseEvent := range unpauseEvents {
if unpauseEvent[len(unpauseEvent)-1] != "unpause" {
t.Fatalf("event should be unpause, not %#v", unpauseEvent)
c.Fatalf("event should be unpause, not %#v", unpauseEvent)
}
}
logDone("pause - multi pause/unpause is logged")
}

View file

@ -5,42 +5,42 @@ import (
"os/exec"
"sort"
"strings"
"testing"
"github.com/go-check/check"
)
func TestPortList(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPortList(c *check.C) {
// one port
runCmd := exec.Command(dockerBinary, "run", "-d", "-p", "9876:80", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", firstID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"0.0.0.0:9876"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "port", firstID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"80/tcp -> 0.0.0.0:9876"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"80/tcp -> 0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "rm", "-f", firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// three port
@ -51,36 +51,36 @@ func TestPortList(t *testing.T) {
"busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", ID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"0.0.0.0:9876"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "port", ID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{
if !assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:9876",
"81/tcp -> 0.0.0.0:9877",
"82/tcp -> 0.0.0.0:9878"}) {
t.Error("Port list is not correct")
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "rm", "-f", ID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// more and one port mapped to the same container port
@ -92,46 +92,45 @@ func TestPortList(t *testing.T) {
"busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ID = strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", ID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"0.0.0.0:9876", "0.0.0.0:9999"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "port", ID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{
if !assertPortList(c, out, []string{
"80/tcp -> 0.0.0.0:9876",
"80/tcp -> 0.0.0.0:9999",
"81/tcp -> 0.0.0.0:9877",
"82/tcp -> 0.0.0.0:9878"}) {
t.Error("Port list is not correct\n", out)
c.Error("Port list is not correct\n", out)
}
runCmd = exec.Command(dockerBinary, "rm", "-f", ID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
logDone("port - test port list")
}
func assertPortList(t *testing.T, out string, expected []string) bool {
func assertPortList(c *check.C, out string, expected []string) bool {
//lines := strings.Split(out, "\n")
lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines) != len(expected) {
t.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
c.Errorf("different size lists %s, %d, %d", out, len(lines), len(expected))
return false
}
sort.Strings(lines)
@ -139,7 +138,7 @@ func assertPortList(t *testing.T, out string, expected []string) bool {
for i := 0; i < len(expected); i++ {
if lines[i] != expected[i] {
t.Error("|" + lines[i] + "!=" + expected[i] + "|")
c.Error("|" + lines[i] + "!=" + expected[i] + "|")
return false
}
}
@ -147,84 +146,78 @@ func assertPortList(t *testing.T, out string, expected []string) bool {
return true
}
func TestPortHostBinding(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPortHostBinding(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "-p", "9876:80", "busybox",
"nc", "-l", "-p", "80")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", firstID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertPortList(t, out, []string{"0.0.0.0:9876"}) {
t.Error("Port list is not correct")
if !assertPortList(c, out, []string{"0.0.0.0:9876"}) {
c.Error("Port list is not correct")
}
runCmd = exec.Command(dockerBinary, "run", "--net=host", "busybox",
"nc", "localhost", "9876")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "rm", "-f", firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "run", "--net=host", "busybox",
"nc", "localhost", "9876")
if out, _, err = runCommandWithOutput(runCmd); err == nil {
t.Error("Port is still bound after the Container is removed")
c.Error("Port is still bound after the Container is removed")
}
logDone("port - test host binding done")
}
func TestPortExposeHostBinding(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPortExposeHostBinding(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "-P", "--expose", "80", "busybox",
"nc", "-l", "-p", "80")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "port", firstID, "80")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
_, exposedPort, err := net.SplitHostPort(out)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "run", "--net=host", "busybox",
"nc", "localhost", strings.TrimSpace(exposedPort))
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "rm", "-f", firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "run", "--net=host", "busybox",
"nc", "localhost", strings.TrimSpace(exposedPort))
if out, _, err = runCommandWithOutput(runCmd); err == nil {
t.Error("Port is still bound after the Container is removed")
c.Error("Port is still bound after the Container is removed")
}
logDone("port - test port expose done")
}

View file

@ -4,30 +4,30 @@ import (
"net"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestCliProxyDisableProxyUnixSock(t *testing.T) {
testRequires(t, SameHostDaemon) // test is valid when DOCKER_HOST=unix://..
func (s *DockerSuite) TestCliProxyDisableProxyUnixSock(c *check.C) {
testRequires(c, SameHostDaemon) // test is valid when DOCKER_HOST=unix://..
cmd := exec.Command(dockerBinary, "info")
cmd.Env = appendBaseEnv([]string{"HTTP_PROXY=http://127.0.0.1:9999"})
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
logDone("cli proxy - HTTP_PROXY is not used when connecting to unix sock")
}
// Can't use localhost here since go has a special case to not use proxy if connecting to localhost
// See https://golang.org/pkg/net/http/#ProxyFromEnvironment
func TestCliProxyProxyTCPSock(t *testing.T) {
testRequires(t, SameHostDaemon)
func (s *DockerSuite) TestCliProxyProxyTCPSock(c *check.C) {
testRequires(c, SameHostDaemon)
// get the IP to use to connect since we can't use localhost
addrs, err := net.InterfaceAddrs()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
var ip string
for _, addr := range addrs {
@ -40,25 +40,24 @@ func TestCliProxyProxyTCPSock(t *testing.T) {
}
if ip == "" {
t.Fatal("could not find ip to connect to")
c.Fatal("could not find ip to connect to")
}
d := NewDaemon(t)
d := NewDaemon(c)
if err := d.Start("-H", "tcp://"+ip+":2375"); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd := exec.Command(dockerBinary, "info")
cmd.Env = []string{"DOCKER_HOST=tcp://" + ip + ":2375", "HTTP_PROXY=127.0.0.1:9999"}
if out, _, err := runCommandWithOutput(cmd); err == nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
// Test with no_proxy
cmd.Env = append(cmd.Env, "NO_PROXY="+ip)
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "info")); err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
logDone("cli proxy - HTTP_PROXY is used for TCP sock")
}

View file

@ -6,24 +6,24 @@ import (
"reflect"
"strconv"
"strings"
"testing"
"time"
"github.com/go-check/check"
)
func TestPsListContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainers(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
secondID := strings.TrimSpace(out)
@ -31,53 +31,53 @@ func TestPsListContainers(t *testing.T) {
runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
thirdID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "top")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
fourthID := strings.TrimSpace(out)
// make sure the second is running
if err := waitRun(secondID); err != nil {
t.Fatalf("waiting for container failed: %v", err)
c.Fatalf("waiting for container failed: %v", err)
}
// make sure third one is not running
runCmd = exec.Command(dockerBinary, "wait", thirdID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// make sure the forth is running
if err := waitRun(fourthID); err != nil {
t.Fatalf("waiting for container failed: %v", err)
c.Fatalf("waiting for container failed: %v", err)
}
// all
runCmd = exec.Command(dockerBinary, "ps", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, []string{fourthID, thirdID, secondID, firstID}) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// running
runCmd = exec.Command(dockerBinary, "ps")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, []string{fourthID, secondID, firstID}) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// from here all flag '-a' is ignored
@ -86,156 +86,155 @@ func TestPsListContainers(t *testing.T) {
runCmd = exec.Command(dockerBinary, "ps", "-n=2", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected := []string{fourthID, thirdID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "-n=2")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// since
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{fourthID, thirdID, secondID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// before
runCmd = exec.Command(dockerBinary, "ps", "--before", thirdID, "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{secondID, firstID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--before", thirdID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// since & before
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "--before", fourthID, "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{thirdID, secondID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "--before", fourthID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// since & limit
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "-n=2", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{fourthID, thirdID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "-n=2")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// before & limit
runCmd = exec.Command(dockerBinary, "ps", "--before", fourthID, "-n=1", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{thirdID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--before", fourthID, "-n=1")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
// since & before & limit
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "--before", fourthID, "-n=1", "-a")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
expected = []string{thirdID}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
runCmd = exec.Command(dockerBinary, "ps", "--since", firstID, "--before", fourthID, "-n=1")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if !assertContainerList(out, expected) {
t.Errorf("Container list is not in the correct order: %s", out)
c.Errorf("Container list is not in the correct order: %s", out)
}
logDone("ps - test ps options")
}
func assertContainerList(out string, expected []string) bool {
@ -255,8 +254,7 @@ func assertContainerList(out string, expected []string) bool {
return true
}
func TestPsListContainersSize(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "hello")
runCommandWithOutput(cmd)
@ -267,18 +265,18 @@ func TestPsListContainersSize(t *testing.T) {
baseFoundsize := baseLines[1][baseSizeIndex:]
baseBytes, err := strconv.Atoi(strings.Split(baseFoundsize, " ")[0])
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
name := "test_size"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sh", "-c", "echo 1 > test")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
id, err := getIDByName(name)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "ps", "-s", "-n=1")
@ -290,54 +288,52 @@ func TestPsListContainersSize(t *testing.T) {
select {
case <-wait:
case <-time.After(3 * time.Second):
t.Fatalf("Calling \"docker ps -s\" timed out!")
c.Fatalf("Calling \"docker ps -s\" timed out!")
}
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
lines := strings.Split(strings.Trim(out, "\n "), "\n")
if len(lines) != 2 {
t.Fatalf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines))
c.Fatalf("Expected 2 lines for 'ps -s -n=1' output, got %d", len(lines))
}
sizeIndex := strings.Index(lines[0], "SIZE")
idIndex := strings.Index(lines[0], "CONTAINER ID")
foundID := lines[1][idIndex : idIndex+12]
if foundID != id[:12] {
t.Fatalf("Expected id %s, got %s", id[:12], foundID)
c.Fatalf("Expected id %s, got %s", id[:12], foundID)
}
expectedSize := fmt.Sprintf("%d B", (2 + baseBytes))
foundSize := lines[1][sizeIndex:]
if foundSize != expectedSize {
t.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
c.Fatalf("Expected size %q, got %q", expectedSize, foundSize)
}
logDone("ps - test ps size")
}
func TestPsListContainersFilterStatus(t *testing.T) {
func (s *DockerSuite) TestPsListContainersFilterStatus(c *check.C) {
// FIXME: this should test paused, but it makes things hang and its wonky
// this is because paused containers can't be controlled by signals
defer deleteAllContainers()
// start exited container
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
// make sure the exited cintainer is not running
runCmd = exec.Command(dockerBinary, "wait", firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// start running container
runCmd = exec.Command(dockerBinary, "run", "-itd", "busybox")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
secondID := strings.TrimSpace(out)
@ -345,313 +341,302 @@ func TestPsListContainersFilterStatus(t *testing.T) {
runCmd = exec.Command(dockerBinary, "ps", "-q", "--filter=status=exited")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut := strings.TrimSpace(out)
if containerOut != firstID[:12] {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
}
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=status=running")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut = strings.TrimSpace(out)
if containerOut != secondID[:12] {
t.Fatalf("Expected id %s, got %s for running filter, output: %q", secondID[:12], containerOut, out)
c.Fatalf("Expected id %s, got %s for running filter, output: %q", secondID[:12], containerOut, out)
}
logDone("ps - test ps filter status")
}
func TestPsListContainersFilterID(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainersFilterID(c *check.C) {
// start container
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
// start another container
runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "top")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// filter containers by id
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=id="+firstID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut := strings.TrimSpace(out)
if containerOut != firstID[:12] {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
}
logDone("ps - test ps filter id")
}
func TestPsListContainersFilterName(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainersFilterName(c *check.C) {
// start container
runCmd := exec.Command(dockerBinary, "run", "-d", "--name=a_name_to_match", "busybox")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
// start another container
runCmd = exec.Command(dockerBinary, "run", "-d", "--name=b_name_to_match", "busybox", "top")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// filter containers by name
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--filter=name=a_name_to_match")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut := strings.TrimSpace(out)
if containerOut != firstID[:12] {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID[:12], containerOut, out)
}
logDone("ps - test ps filter name")
}
func TestPsListContainersFilterLabel(t *testing.T) {
func (s *DockerSuite) TestPsListContainersFilterLabel(c *check.C) {
// start container
runCmd := exec.Command(dockerBinary, "run", "-d", "-l", "match=me", "-l", "second=tag", "busybox")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstID := strings.TrimSpace(out)
// start another container
runCmd = exec.Command(dockerBinary, "run", "-d", "-l", "match=me too", "busybox")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
secondID := strings.TrimSpace(out)
// start third container
runCmd = exec.Command(dockerBinary, "run", "-d", "-l", "nomatch=me", "busybox")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
thirdID := strings.TrimSpace(out)
// filter containers by exact match
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut := strings.TrimSpace(out)
if containerOut != firstID {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
}
// filter containers by two labels
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut = strings.TrimSpace(out)
if containerOut != firstID {
t.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
c.Fatalf("Expected id %s, got %s for exited filter, output: %q", firstID, containerOut, out)
}
// filter containers by two labels, but expect not found because of AND behavior
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=label=match=me", "--filter=label=second=tag-no")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut = strings.TrimSpace(out)
if containerOut != "" {
t.Fatalf("Expected nothing, got %s for exited filter, output: %q", containerOut, out)
c.Fatalf("Expected nothing, got %s for exited filter, output: %q", containerOut, out)
}
// filter containers by exact key
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=label=match")
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerOut = strings.TrimSpace(out)
if (!strings.Contains(containerOut, firstID) || !strings.Contains(containerOut, secondID)) || strings.Contains(containerOut, thirdID) {
t.Fatalf("Expected ids %s,%s, got %s for exited filter, output: %q", firstID, secondID, containerOut, out)
c.Fatalf("Expected ids %s,%s, got %s for exited filter, output: %q", firstID, secondID, containerOut, out)
}
deleteAllContainers()
logDone("ps - test ps filter label")
}
func TestPsListContainersFilterExited(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsListContainersFilterExited(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "top", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "run", "--name", "zero1", "busybox", "true")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
firstZero, err := getIDByName("zero1")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "run", "--name", "zero2", "busybox", "true")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
secondZero, err := getIDByName("zero2")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "run", "--name", "nonzero1", "busybox", "false")
if out, _, err := runCommandWithOutput(runCmd); err == nil {
t.Fatal("Should fail.", out, err)
c.Fatal("Should fail.", out, err)
}
firstNonZero, err := getIDByName("nonzero1")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
runCmd = exec.Command(dockerBinary, "run", "--name", "nonzero2", "busybox", "false")
if out, _, err := runCommandWithOutput(runCmd); err == nil {
t.Fatal("Should fail.", out, err)
c.Fatal("Should fail.", out, err)
}
secondNonZero, err := getIDByName("nonzero2")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// filter containers by exited=0
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=exited=0")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ids := strings.Split(strings.TrimSpace(out), "\n")
if len(ids) != 2 {
t.Fatalf("Should be 2 zero exited containers got %d: %s", len(ids), out)
c.Fatalf("Should be 2 zero exited containers got %d: %s", len(ids), out)
}
if ids[0] != secondZero {
t.Fatalf("First in list should be %q, got %q", secondZero, ids[0])
c.Fatalf("First in list should be %q, got %q", secondZero, ids[0])
}
if ids[1] != firstZero {
t.Fatalf("Second in list should be %q, got %q", firstZero, ids[1])
c.Fatalf("Second in list should be %q, got %q", firstZero, ids[1])
}
runCmd = exec.Command(dockerBinary, "ps", "-a", "-q", "--no-trunc", "--filter=exited=1")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
ids = strings.Split(strings.TrimSpace(out), "\n")
if len(ids) != 2 {
t.Fatalf("Should be 2 zero exited containerst got %d", len(ids))
c.Fatalf("Should be 2 zero exited containerst got %d", len(ids))
}
if ids[0] != secondNonZero {
t.Fatalf("First in list should be %q, got %q", secondNonZero, ids[0])
c.Fatalf("First in list should be %q, got %q", secondNonZero, ids[0])
}
if ids[1] != firstNonZero {
t.Fatalf("Second in list should be %q, got %q", firstNonZero, ids[1])
c.Fatalf("Second in list should be %q, got %q", firstNonZero, ids[1])
}
logDone("ps - test ps filter exited")
}
func TestPsRightTagName(t *testing.T) {
func (s *DockerSuite) TestPsRightTagName(c *check.C) {
tag := "asybox:shmatest"
defer deleteAllContainers()
defer deleteImages(tag)
if out, err := exec.Command(dockerBinary, "tag", "busybox", tag).CombinedOutput(); err != nil {
t.Fatalf("Failed to tag image: %s, out: %q", err, out)
c.Fatalf("Failed to tag image: %s, out: %q", err, out)
}
var id1 string
if out, err := exec.Command(dockerBinary, "run", "-d", "busybox", "top").CombinedOutput(); err != nil {
t.Fatalf("Failed to run container: %s, out: %q", err, out)
c.Fatalf("Failed to run container: %s, out: %q", err, out)
} else {
id1 = strings.TrimSpace(string(out))
}
var id2 string
if out, err := exec.Command(dockerBinary, "run", "-d", tag, "top").CombinedOutput(); err != nil {
t.Fatalf("Failed to run container: %s, out: %q", err, out)
c.Fatalf("Failed to run container: %s, out: %q", err, out)
} else {
id2 = strings.TrimSpace(string(out))
}
var imageID string
if out, err := exec.Command(dockerBinary, "inspect", "-f", "{{.Id}}", "busybox").CombinedOutput(); err != nil {
t.Fatalf("failed to get the image ID of busybox: %s, %v", out, err)
c.Fatalf("failed to get the image ID of busybox: %s, %v", out, err)
} else {
imageID = strings.TrimSpace(string(out))
}
var id3 string
if out, err := exec.Command(dockerBinary, "run", "-d", imageID, "top").CombinedOutput(); err != nil {
t.Fatalf("Failed to run container: %s, out: %q", err, out)
c.Fatalf("Failed to run container: %s, out: %q", err, out)
} else {
id3 = strings.TrimSpace(string(out))
}
out, err := exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
if err != nil {
t.Fatalf("Failed to run 'ps': %s, out: %q", err, out)
c.Fatalf("Failed to run 'ps': %s, out: %q", err, out)
}
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
// skip header
lines = lines[1:]
if len(lines) != 3 {
t.Fatalf("There should be 3 running container, got %d", len(lines))
c.Fatalf("There should be 3 running container, got %d", len(lines))
}
for _, line := range lines {
f := strings.Fields(line)
switch f[0] {
case id1:
if f[1] != "busybox" {
t.Fatalf("Expected %s tag for id %s, got %s", "busybox", id1, f[1])
c.Fatalf("Expected %s tag for id %s, got %s", "busybox", id1, f[1])
}
case id2:
if f[1] != tag {
t.Fatalf("Expected %s tag for id %s, got %s", tag, id2, f[1])
c.Fatalf("Expected %s tag for id %s, got %s", tag, id2, f[1])
}
case id3:
if f[1] != imageID {
t.Fatalf("Expected %s imageID for id %s, got %s", tag, id3, f[1])
c.Fatalf("Expected %s imageID for id %s, got %s", tag, id3, f[1])
}
default:
t.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
c.Fatalf("Unexpected id %s, expected %s and %s and %s", f[0], id1, id2, id3)
}
}
logDone("ps - right tags for containers")
}
func TestPsLinkedWithNoTrunc(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsLinkedWithNoTrunc(c *check.C) {
if out, err := exec.Command(dockerBinary, "run", "--name=first", "-d", "busybox", "top").CombinedOutput(); err != nil {
t.Fatalf("Output: %s, err: %s", out, err)
c.Fatalf("Output: %s, err: %s", out, err)
}
if out, err := exec.Command(dockerBinary, "run", "--name=second", "--link=first:first", "-d", "busybox", "top").CombinedOutput(); err != nil {
t.Fatalf("Output: %s, err: %s", out, err)
c.Fatalf("Output: %s, err: %s", out, err)
}
out, err := exec.Command(dockerBinary, "ps", "--no-trunc").CombinedOutput()
if err != nil {
t.Fatalf("Output: %s, err: %s", out, err)
c.Fatalf("Output: %s, err: %s", out, err)
}
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
// strip header
@ -663,28 +648,26 @@ func TestPsLinkedWithNoTrunc(t *testing.T) {
names = append(names, fields[len(fields)-1])
}
if !reflect.DeepEqual(expected, names) {
t.Fatalf("Expected array: %v, got: %v", expected, names)
c.Fatalf("Expected array: %v, got: %v", expected, names)
}
}
func TestPsGroupPortRange(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestPsGroupPortRange(c *check.C) {
portRange := "3800-3900"
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "porttest", "-p", portRange+":"+portRange, "busybox", "top"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "ps"))
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
// check that the port range is in the output
if !strings.Contains(string(out), portRange) {
t.Fatalf("docker ps output should have had the port range %q: %s", portRange, string(out))
c.Fatalf("docker ps output should have had the port range %q: %s", portRange, string(out))
}
logDone("ps - port range")
}

View file

@ -4,12 +4,13 @@ import (
"fmt"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// See issue docker/docker#8141
func TestPullImageWithAliases(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPullImageWithAliases(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
defer deleteImages(repoName)
@ -22,40 +23,39 @@ func TestPullImageWithAliases(t *testing.T) {
// Tag and push the same image multiple times.
for _, repo := range repos {
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "tag", "busybox", repo)); err != nil {
t.Fatalf("Failed to tag image %v: error %v, output %q", repos, err, out)
c.Fatalf("Failed to tag image %v: error %v, output %q", repos, err, out)
}
defer deleteImages(repo)
if out, err := exec.Command(dockerBinary, "push", repo).CombinedOutput(); err != nil {
t.Fatalf("Failed to push image %v: error %v, output %q", repo, err, string(out))
c.Fatalf("Failed to push image %v: error %v, output %q", repo, err, string(out))
}
}
// Clear local images store.
args := append([]string{"rmi"}, repos...)
if out, err := exec.Command(dockerBinary, args...).CombinedOutput(); err != nil {
t.Fatalf("Failed to clean images: error %v, output %q", err, string(out))
c.Fatalf("Failed to clean images: error %v, output %q", err, string(out))
}
// Pull a single tag and verify it doesn't bring down all aliases.
pullCmd := exec.Command(dockerBinary, "pull", repos[0])
if out, _, err := runCommandWithOutput(pullCmd); err != nil {
t.Fatalf("Failed to pull %v: error %v, output %q", repoName, err, out)
c.Fatalf("Failed to pull %v: error %v, output %q", repoName, err, out)
}
if err := exec.Command(dockerBinary, "inspect", repos[0]).Run(); err != nil {
t.Fatalf("Image %v was not pulled down", repos[0])
c.Fatalf("Image %v was not pulled down", repos[0])
}
for _, repo := range repos[1:] {
if err := exec.Command(dockerBinary, "inspect", repo).Run(); err == nil {
t.Fatalf("Image %v shouldn't have been pulled down", repo)
c.Fatalf("Image %v shouldn't have been pulled down", repo)
}
}
logDone("pull - image with aliases")
}
// pulling library/hello-world should show verified message
func TestPullVerified(t *testing.T) {
t.Skip("Skipping hub dependent test")
func (s *DockerSuite) TestPullVerified(c *check.C) {
c.Skip("Skipping hub dependent test")
// Image must be pulled from central repository to get verified message
// unless keychain is manually updated to contain the daemon's sign key.
@ -68,49 +68,46 @@ func TestPullVerified(t *testing.T) {
pullCmd := exec.Command(dockerBinary, "pull", verifiedName)
if out, exitCode, err := runCommandWithOutput(pullCmd); err != nil || !strings.Contains(out, expected) {
if err != nil || exitCode != 0 {
t.Skipf("pulling the '%s' image from the registry has failed: %s", verifiedName, err)
c.Skip(fmt.Sprintf("pulling the '%s' image from the registry has failed: %v", verifiedName, err))
}
t.Fatalf("pulling a verified image failed. expected: %s\ngot: %s, %v", expected, out, err)
c.Fatalf("pulling a verified image failed. expected: %s\ngot: %s, %v", expected, out, err)
}
// pull it again
pullCmd = exec.Command(dockerBinary, "pull", verifiedName)
if out, exitCode, err := runCommandWithOutput(pullCmd); err != nil || strings.Contains(out, expected) {
if err != nil || exitCode != 0 {
t.Skipf("pulling the '%s' image from the registry has failed: %s", verifiedName, err)
c.Skip(fmt.Sprintf("pulling the '%s' image from the registry has failed: %v", verifiedName, err))
}
t.Fatalf("pulling a verified image failed. unexpected verify message\ngot: %s, %v", out, err)
c.Fatalf("pulling a verified image failed. unexpected verify message\ngot: %s, %v", out, err)
}
logDone("pull - pull verified")
}
// pulling an image from the central registry should work
func TestPullImageFromCentralRegistry(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestPullImageFromCentralRegistry(c *check.C) {
testRequires(c, Network)
defer deleteImages("hello-world")
pullCmd := exec.Command(dockerBinary, "pull", "hello-world")
if out, _, err := runCommandWithOutput(pullCmd); err != nil {
t.Fatalf("pulling the hello-world image from the registry has failed: %s, %v", out, err)
c.Fatalf("pulling the hello-world image from the registry has failed: %s, %v", out, err)
}
logDone("pull - pull hello-world")
}
// pulling a non-existing image from the central registry should return a non-zero exit code
func TestPullNonExistingImage(t *testing.T) {
func (s *DockerSuite) TestPullNonExistingImage(c *check.C) {
pullCmd := exec.Command(dockerBinary, "pull", "fooblahblah1234")
if out, _, err := runCommandWithOutput(pullCmd); err == nil {
t.Fatalf("expected non-zero exit status when pulling non-existing image: %s", out)
c.Fatalf("expected non-zero exit status when pulling non-existing image: %s", out)
}
logDone("pull - pull fooblahblah1234 (non-existing image)")
}
// pulling an image from the central registry using official names should work
// ensure all pulls result in the same image
func TestPullImageOfficialNames(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestPullImageOfficialNames(c *check.C) {
testRequires(c, Network)
names := []string{
"docker.io/hello-world",
@ -123,7 +120,7 @@ func TestPullImageOfficialNames(t *testing.T) {
pullCmd := exec.Command(dockerBinary, "pull", name)
out, exitCode, err := runCommandWithOutput(pullCmd)
if err != nil || exitCode != 0 {
t.Errorf("pulling the '%s' image from the registry has failed: %s", name, err)
c.Errorf("pulling the '%s' image from the registry has failed: %s", name, err)
continue
}
@ -131,10 +128,9 @@ func TestPullImageOfficialNames(t *testing.T) {
imagesCmd := exec.Command(dockerBinary, "images")
out, _, err = runCommandWithOutput(imagesCmd)
if err != nil {
t.Errorf("listing images failed with errors: %v", err)
c.Errorf("listing images failed with errors: %v", err)
} else if strings.Contains(out, name) {
t.Errorf("images should not have listed '%s'", name)
c.Errorf("images should not have listed '%s'", name)
}
}
logDone("pull - pull official names")
}

View file

@ -6,72 +6,68 @@ import (
"os"
"os/exec"
"strings"
"testing"
"time"
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
"github.com/go-check/check"
)
// pulling an image from the central registry should work
func TestPushBusyboxImage(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushBusyboxImage(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
// tag the image to upload it to the private registry
tagCmd := exec.Command(dockerBinary, "tag", "busybox", repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
c.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoName)
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err != nil {
t.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
}
logDone("push - busybox to private registry")
}
// pushing an image without a prefix should throw an error
func TestPushUnprefixedRepo(t *testing.T) {
func (s *DockerSuite) TestPushUnprefixedRepo(c *check.C) {
pushCmd := exec.Command(dockerBinary, "push", "busybox")
if out, _, err := runCommandWithOutput(pushCmd); err == nil {
t.Fatalf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out)
c.Fatalf("pushing an unprefixed repo didn't result in a non-zero exit status: %s", out)
}
logDone("push - unprefixed busybox repo must not pass")
}
func TestPushUntagged(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushUntagged(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
expected := "Repository does not exist"
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err == nil {
t.Fatalf("pushing the image to the private registry should have failed: outuput %q", out)
c.Fatalf("pushing the image to the private registry should have failed: outuput %q", out)
} else if !strings.Contains(out, expected) {
t.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
}
logDone("push - untagged image")
}
func TestPushBadTag(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushBadTag(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL)
expected := "does not exist"
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err == nil {
t.Fatalf("pushing the image to the private registry should have failed: outuput %q", out)
c.Fatalf("pushing the image to the private registry should have failed: outuput %q", out)
} else if !strings.Contains(out, expected) {
t.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
c.Fatalf("pushing the image failed with an unexpected message: expected %q, got %q", expected, out)
}
logDone("push - image with bad tag")
}
func TestPushMultipleTags(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushMultipleTags(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL)
@ -79,80 +75,79 @@ func TestPushMultipleTags(t *testing.T) {
// tag the image to upload it tot he private registry
tagCmd1 := exec.Command(dockerBinary, "tag", "busybox", repoTag1)
if out, _, err := runCommandWithOutput(tagCmd1); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
c.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoTag1)
tagCmd2 := exec.Command(dockerBinary, "tag", "busybox", repoTag2)
if out, _, err := runCommandWithOutput(tagCmd2); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
c.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoTag2)
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err != nil {
t.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
}
logDone("push - multiple tags to private registry")
}
func TestPushInterrupt(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushInterrupt(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
// tag the image to upload it tot he private registry
tagCmd := exec.Command(dockerBinary, "tag", "busybox", repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("image tagging failed: %s, %v", out, err)
c.Fatalf("image tagging failed: %s, %v", out, err)
}
defer deleteImages(repoName)
pushCmd := exec.Command(dockerBinary, "push", repoName)
if err := pushCmd.Start(); err != nil {
t.Fatalf("Failed to start pushing to private registry: %v", err)
c.Fatalf("Failed to start pushing to private registry: %v", err)
}
// Interrupt push (yes, we have no idea at what point it will get killed).
time.Sleep(200 * time.Millisecond)
if err := pushCmd.Process.Kill(); err != nil {
t.Fatalf("Failed to kill push process: %v", err)
c.Fatalf("Failed to kill push process: %v", err)
}
// Try agin
pushCmd = exec.Command(dockerBinary, "push", repoName)
if err := pushCmd.Start(); err != nil {
t.Fatalf("Failed to start pushing to private registry: %v", err)
if out, err := pushCmd.CombinedOutput(); err == nil {
str := string(out)
if !strings.Contains(str, "already in progress") {
c.Fatalf("Push should be continued on daemon side, but seems ok: %v, %s", err, out)
}
}
logDone("push - interrupted")
}
func TestPushEmptyLayer(t *testing.T) {
defer setupRegistry(t)()
func (s *DockerSuite) TestPushEmptyLayer(c *check.C) {
defer setupRegistry(c)()
repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL)
emptyTarball, err := ioutil.TempFile("", "empty_tarball")
if err != nil {
t.Fatalf("Unable to create test file: %v", err)
c.Fatalf("Unable to create test file: %v", err)
}
tw := tar.NewWriter(emptyTarball)
err = tw.Close()
if err != nil {
t.Fatalf("Error creating empty tarball: %v", err)
c.Fatalf("Error creating empty tarball: %v", err)
}
freader, err := os.Open(emptyTarball.Name())
if err != nil {
t.Fatalf("Could not open test tarball: %v", err)
c.Fatalf("Could not open test tarball: %v", err)
}
importCmd := exec.Command(dockerBinary, "import", "-", repoName)
importCmd.Stdin = freader
out, _, err := runCommandWithOutput(importCmd)
if err != nil {
t.Errorf("import failed with errors: %v, output: %q", err, out)
c.Errorf("import failed with errors: %v, output: %q", err, out)
}
// Now verify we can push it
pushCmd := exec.Command(dockerBinary, "push", repoName)
if out, _, err := runCommandWithOutput(pushCmd); err != nil {
t.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
c.Fatalf("pushing the image to the private registry has failed: %s, %v", out, err)
}
logDone("push - empty layer config to private registry")
}

View file

@ -3,16 +3,16 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestRenameStoppedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRenameStoppedContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--name", "first_name", "-d", "busybox", "sh")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -20,7 +20,7 @@ func TestRenameStoppedContainer(t *testing.T) {
runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
name, err := inspectField(cleanedContainerID, "Name")
@ -28,94 +28,87 @@ func TestRenameStoppedContainer(t *testing.T) {
runCmd = exec.Command(dockerBinary, "rename", "first_name", "new_name")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
name, err = inspectField(cleanedContainerID, "Name")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if name != "/new_name" {
t.Fatal("Failed to rename container ", name)
c.Fatal("Failed to rename container ", name)
}
logDone("rename - stopped container")
}
func TestRenameRunningContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRenameRunningContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--name", "first_name", "-d", "busybox", "sh")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "rename", "first_name", "new_name")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
name, err := inspectField(cleanedContainerID, "Name")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if name != "/new_name" {
t.Fatal("Failed to rename container ")
c.Fatal("Failed to rename container ")
}
logDone("rename - running container")
}
func TestRenameCheckNames(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRenameCheckNames(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--name", "first_name", "-d", "busybox", "sh")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
runCmd = exec.Command(dockerBinary, "rename", "first_name", "new_name")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
name, err := inspectField("new_name", "Name")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if name != "/new_name" {
t.Fatal("Failed to rename container ")
c.Fatal("Failed to rename container ")
}
name, err = inspectField("first_name", "Name")
if err == nil && !strings.Contains(err.Error(), "No such image or container: first_name") {
t.Fatal(err)
c.Fatal(err)
}
logDone("rename - old name released")
}
func TestRenameInvalidName(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRenameInvalidName(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--name", "myname", "-d", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatalf(out, err)
c.Fatalf(out, err)
}
runCmd = exec.Command(dockerBinary, "rename", "myname", "new:invalid")
if out, _, err := runCommandWithOutput(runCmd); err == nil || !strings.Contains(out, "Invalid container name") {
t.Fatalf("Renaming container to invalid name should have failed: %s\n%v", out, err)
c.Fatalf("Renaming container to invalid name should have failed: %s\n%v", out, err)
}
runCmd = exec.Command(dockerBinary, "ps", "-a")
if out, _, err := runCommandWithOutput(runCmd); err != nil || !strings.Contains(out, "myname") {
t.Fatalf("Output of docker ps should have included 'myname': %s\n%v", out, err)
c.Fatalf("Output of docker ps should have included 'myname': %s\n%v", out, err)
}
logDone("rename - invalid container name")
}

View file

@ -3,61 +3,59 @@ package main
import (
"os/exec"
"strings"
"testing"
"time"
"github.com/go-check/check"
)
func TestRestartStoppedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartStoppedContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "foobar")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "wait", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out != "foobar\n" {
t.Errorf("container should've printed 'foobar'")
c.Errorf("container should've printed 'foobar'")
}
runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out != "foobar\nfoobar\n" {
t.Errorf("container should've printed 'foobar' twice")
c.Errorf("container should've printed 'foobar' twice")
}
logDone("restart - echo foobar for stopped container")
}
func TestRestartRunningContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartRunningContainer(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "echo foobar && sleep 30 && echo 'should not print this'")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -67,41 +65,39 @@ func TestRestartRunningContainer(t *testing.T) {
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out != "foobar\n" {
t.Errorf("container should've printed 'foobar'")
c.Errorf("container should've printed 'foobar'")
}
runCmd = exec.Command(dockerBinary, "restart", "-t", "1", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "logs", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
time.Sleep(1 * time.Second)
if out != "foobar\nfoobar\n" {
t.Errorf("container should've printed 'foobar' twice")
c.Errorf("container should've printed 'foobar' twice")
}
logDone("restart - echo foobar for running container")
}
// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819.
func TestRestartWithVolumes(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartWithVolumes(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "-v", "/test", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -109,148 +105,139 @@ func TestRestartWithVolumes(t *testing.T) {
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out = strings.Trim(out, " \n\r"); out != "1" {
t.Errorf("expect 1 volume received %s", out)
c.Errorf("expect 1 volume received %s", out)
}
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
volumes, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(volumes, err)
c.Fatal(volumes, err)
}
runCmd = exec.Command(dockerBinary, "restart", cleanedContainerID)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ len .Volumes }}", cleanedContainerID)
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
if out = strings.Trim(out, " \n\r"); out != "1" {
t.Errorf("expect 1 volume after restart received %s", out)
c.Errorf("expect 1 volume after restart received %s", out)
}
runCmd = exec.Command(dockerBinary, "inspect", "--format", "{{ .Volumes }}", cleanedContainerID)
volumesAfterRestart, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(volumesAfterRestart, err)
c.Fatal(volumesAfterRestart, err)
}
if volumes != volumesAfterRestart {
volumes = strings.Trim(volumes, " \n\r")
volumesAfterRestart = strings.Trim(volumesAfterRestart, " \n\r")
t.Errorf("expected volume path: %s Actual path: %s", volumes, volumesAfterRestart)
c.Errorf("expected volume path: %s Actual path: %s", volumes, volumesAfterRestart)
}
logDone("restart - does not create a new volume on restart")
}
func TestRestartPolicyNO(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartPolicyNO(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "--restart=no", "busybox", "false")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if name != "no" {
t.Fatalf("Container restart policy name is %s, expected %s", name, "no")
c.Fatalf("Container restart policy name is %s, expected %s", name, "no")
}
logDone("restart - recording restart policy name for --restart=no")
}
func TestRestartPolicyAlways(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartPolicyAlways(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "--restart=always", "busybox", "false")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if name != "always" {
t.Fatalf("Container restart policy name is %s, expected %s", name, "always")
c.Fatalf("Container restart policy name is %s, expected %s", name, "always")
}
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// MaximumRetryCount=0 if the restart policy is always
if MaximumRetryCount != "0" {
t.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "0")
c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "0")
}
logDone("restart - recording restart policy name for --restart=always")
}
func TestRestartPolicyOnFailure(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRestartPolicyOnFailure(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "--restart=on-failure:1", "busybox", "false")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
id := strings.TrimSpace(string(out))
name, err := inspectField(id, "HostConfig.RestartPolicy.Name")
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if name != "on-failure" {
t.Fatalf("Container restart policy name is %s, expected %s", name, "on-failure")
c.Fatalf("Container restart policy name is %s, expected %s", name, "on-failure")
}
logDone("restart - recording restart policy name for --restart=on-failure")
}
// a good container with --restart=on-failure:3
// MaximumRetryCount!=0; RestartCount=0
func TestContainerRestartwithGoodContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestContainerRestartwithGoodContainer(c *check.C) {
out, err := exec.Command(dockerBinary, "run", "-d", "--restart=on-failure:3", "busybox", "true").CombinedOutput()
if err != nil {
t.Fatal(string(out), err)
c.Fatal(string(out), err)
}
id := strings.TrimSpace(string(out))
if err := waitInspect(id, "{{ .State.Restarting }} {{ .State.Running }}", "false false", 5); err != nil {
t.Fatal(err)
c.Fatal(err)
}
count, err := inspectField(id, "RestartCount")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if count != "0" {
t.Fatalf("Container was restarted %s times, expected %d", count, 0)
c.Fatalf("Container was restarted %s times, expected %d", count, 0)
}
MaximumRetryCount, err := inspectField(id, "HostConfig.RestartPolicy.MaximumRetryCount")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if MaximumRetryCount != "3" {
t.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
c.Fatalf("Container Maximum Retry Count is %s, expected %s", MaximumRetryCount, "3")
}
logDone("restart - for a good container with restart policy, MaximumRetryCount is not 0 and RestartCount is 0")
}

View file

@ -5,93 +5,83 @@ import (
"os"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestRmContainerWithRemovedVolume(t *testing.T) {
testRequires(t, SameHostDaemon)
defer deleteAllContainers()
func (s *DockerSuite) TestRmContainerWithRemovedVolume(c *check.C) {
testRequires(c, SameHostDaemon)
cmd := exec.Command(dockerBinary, "run", "--name", "losemyvolumes", "-v", "/tmp/testing:/test", "busybox", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := os.Remove("/tmp/testing"); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "rm", "-v", "losemyvolumes")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
logDone("rm - removed volume")
}
func TestRmContainerWithVolume(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmContainerWithVolume(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "--name", "foo", "-v", "/srv", "busybox", "true")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
cmd = exec.Command(dockerBinary, "rm", "-v", "foo")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
logDone("rm - volume")
}
func TestRmRunningContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmRunningContainer(c *check.C) {
createRunningContainer(t, "foo")
createRunningContainer(c, "foo")
// Test cannot remove running container
cmd := exec.Command(dockerBinary, "rm", "foo")
if _, err := runCommand(cmd); err == nil {
t.Fatalf("Expected error, can't rm a running container")
c.Fatalf("Expected error, can't rm a running container")
}
logDone("rm - running container")
}
func TestRmRunningContainerCheckError409(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmRunningContainerCheckError409(c *check.C) {
createRunningContainer(t, "foo")
createRunningContainer(c, "foo")
endpoint := "/containers/foo"
status, _, err := sockRequest("DELETE", endpoint, nil)
if err == nil {
t.Fatalf("Expected error, can't rm a running container")
c.Fatalf("Expected error, can't rm a running container")
} else if status != http.StatusConflict {
t.Fatalf("Expected error to contain '409 Conflict' but found %s", err)
c.Fatalf("Expected error to contain '409 Conflict' but found %s", err)
}
logDone("rm - running container with Error 409")
}
func TestRmForceRemoveRunningContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmForceRemoveRunningContainer(c *check.C) {
createRunningContainer(t, "foo")
createRunningContainer(c, "foo")
// Stop then remove with -s
cmd := exec.Command(dockerBinary, "rm", "-f", "foo")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
logDone("rm - running container with --force=true")
}
func TestRmContainerOrphaning(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmContainerOrphaning(c *check.C) {
dockerfile1 := `FROM busybox:latest
ENTRYPOINT ["/bin/true"]`
@ -104,45 +94,43 @@ func TestRmContainerOrphaning(t *testing.T) {
img1, err := buildImage(img, dockerfile1, true)
defer deleteImages(img1)
if err != nil {
t.Fatalf("Could not build image %s: %v", img, err)
c.Fatalf("Could not build image %s: %v", img, err)
}
// run container on first image
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", img)); err != nil {
t.Fatalf("Could not run image %s: %v: %s", img, err, out)
c.Fatalf("Could not run image %s: %v: %s", img, err, out)
}
// rebuild dockerfile with a small addition at the end
if _, err := buildImage(img, dockerfile2, true); err != nil {
t.Fatalf("Could not rebuild image %s: %v", img, err)
c.Fatalf("Could not rebuild image %s: %v", img, err)
}
// try to remove the image, should error out.
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rmi", img)); err == nil {
t.Fatalf("Expected to error out removing the image, but succeeded: %s", out)
c.Fatalf("Expected to error out removing the image, but succeeded: %s", out)
}
// check if we deleted the first image
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "images", "-q", "--no-trunc"))
if err != nil {
t.Fatalf("%v: %s", err, out)
c.Fatalf("%v: %s", err, out)
}
if !strings.Contains(out, img1) {
t.Fatalf("Orphaned container (could not find %q in docker images): %s", img1, out)
c.Fatalf("Orphaned container (could not find %q in docker images): %s", img1, out)
}
logDone("rm - container orphaning")
}
func TestRmInvalidContainer(t *testing.T) {
func (s *DockerSuite) TestRmInvalidContainer(c *check.C) {
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rm", "unknown")); err == nil {
t.Fatal("Expected error on rm unknown container, got none")
c.Fatal("Expected error on rm unknown container, got none")
} else if !strings.Contains(out, "failed to remove one or more containers") {
t.Fatalf("Expected output to contain 'failed to remove one or more containers', got %q", out)
c.Fatalf("Expected output to contain 'failed to remove one or more containers', got %q", out)
}
logDone("rm - delete unknown container")
}
func createRunningContainer(t *testing.T, name string) {
func createRunningContainer(c *check.C, name string) {
cmd := exec.Command(dockerBinary, "run", "-dt", "--name", name, "busybox", "top")
if _, err := runCommand(cmd); err != nil {
t.Fatal(err)
c.Fatal(err)
}
}

View file

@ -3,17 +3,18 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestRmiWithContainerFails(t *testing.T) {
func (s *DockerSuite) TestRmiWithContainerFails(c *check.C) {
errSubstr := "is using it"
// create a container
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -22,123 +23,117 @@ func TestRmiWithContainerFails(t *testing.T) {
runCmd = exec.Command(dockerBinary, "rmi", "busybox")
out, _, err = runCommandWithOutput(runCmd)
if err == nil {
t.Fatalf("Container %q is using image, should not be able to rmi: %q", cleanedContainerID, out)
c.Fatalf("Container %q is using image, should not be able to rmi: %q", cleanedContainerID, out)
}
if !strings.Contains(out, errSubstr) {
t.Fatalf("Container %q is using image, error message should contain %q: %v", cleanedContainerID, errSubstr, out)
c.Fatalf("Container %q is using image, error message should contain %q: %v", cleanedContainerID, errSubstr, out)
}
// make sure it didn't delete the busybox name
images, _ := dockerCmd(t, "images")
images, _ := dockerCmd(c, "images")
if !strings.Contains(images, "busybox") {
t.Fatalf("The name 'busybox' should not have been removed from images: %q", images)
c.Fatalf("The name 'busybox' should not have been removed from images: %q", images)
}
deleteContainer(cleanedContainerID)
logDone("rmi - container using image while rmi, should not remove image name")
}
func TestRmiTag(t *testing.T) {
imagesBefore, _ := dockerCmd(t, "images", "-a")
dockerCmd(t, "tag", "busybox", "utest:tag1")
dockerCmd(t, "tag", "busybox", "utest/docker:tag2")
dockerCmd(t, "tag", "busybox", "utest:5000/docker:tag3")
func (s *DockerSuite) TestRmiTag(c *check.C) {
imagesBefore, _ := dockerCmd(c, "images", "-a")
dockerCmd(c, "tag", "busybox", "utest:tag1")
dockerCmd(c, "tag", "busybox", "utest/docker:tag2")
dockerCmd(c, "tag", "busybox", "utest:5000/docker:tag3")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+3 {
t.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
}
dockerCmd(t, "rmi", "utest/docker:tag2")
dockerCmd(c, "rmi", "utest/docker:tag2")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+2 {
t.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
}
dockerCmd(t, "rmi", "utest:5000/docker:tag3")
dockerCmd(c, "rmi", "utest:5000/docker:tag3")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+1 {
t.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
}
dockerCmd(t, "rmi", "utest:tag1")
dockerCmd(c, "rmi", "utest:tag1")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+0 {
t.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
c.Fatalf("before: %q\n\nafter: %q\n", imagesBefore, imagesAfter)
}
}
logDone("rmi - tag,rmi - tagging the same images multiple times then removing tags")
}
func TestRmiImgIDForce(t *testing.T) {
func (s *DockerSuite) TestRmiImgIDForce(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", "mkdir '/busybox-test'")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container:%s, %v", out, err)
c.Fatalf("failed to create a container:%s, %v", out, err)
}
containerID := strings.TrimSpace(out)
runCmd = exec.Command(dockerBinary, "commit", containerID, "busybox-test")
out, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to commit a new busybox-test:%s, %v", out, err)
c.Fatalf("failed to commit a new busybox-test:%s, %v", out, err)
}
imagesBefore, _ := dockerCmd(t, "images", "-a")
dockerCmd(t, "tag", "busybox-test", "utest:tag1")
dockerCmd(t, "tag", "busybox-test", "utest:tag2")
dockerCmd(t, "tag", "busybox-test", "utest/docker:tag3")
dockerCmd(t, "tag", "busybox-test", "utest:5000/docker:tag4")
imagesBefore, _ := dockerCmd(c, "images", "-a")
dockerCmd(c, "tag", "busybox-test", "utest:tag1")
dockerCmd(c, "tag", "busybox-test", "utest:tag2")
dockerCmd(c, "tag", "busybox-test", "utest/docker:tag3")
dockerCmd(c, "tag", "busybox-test", "utest:5000/docker:tag4")
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Count(imagesAfter, "\n") != strings.Count(imagesBefore, "\n")+4 {
t.Fatalf("tag busybox to create 4 more images with same imageID; docker images shows: %q\n", imagesAfter)
c.Fatalf("tag busybox to create 4 more images with same imageID; docker images shows: %q\n", imagesAfter)
}
}
out, _ = dockerCmd(t, "inspect", "-f", "{{.Id}}", "busybox-test")
out, _ = dockerCmd(c, "inspect", "-f", "{{.Id}}", "busybox-test")
imgID := strings.TrimSpace(out)
dockerCmd(t, "rmi", "-f", imgID)
dockerCmd(c, "rmi", "-f", imgID)
{
imagesAfter, _ := dockerCmd(t, "images", "-a")
imagesAfter, _ := dockerCmd(c, "images", "-a")
if strings.Contains(imagesAfter, imgID[:12]) {
t.Fatalf("rmi -f %s failed, image still exists: %q\n\n", imgID, imagesAfter)
c.Fatalf("rmi -f %s failed, image still exists: %q\n\n", imgID, imagesAfter)
}
}
logDone("rmi - imgID,rmi -f imgID delete all tagged repos of specific imgID")
}
func TestRmiTagWithExistingContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmiTagWithExistingContainers(c *check.C) {
container := "test-delete-tag"
newtag := "busybox:newtag"
bb := "busybox:latest"
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "tag", bb, newtag)); err != nil {
t.Fatalf("Could not tag busybox: %v: %s", err, out)
c.Fatalf("Could not tag busybox: %v: %s", err, out)
}
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", container, bb, "/bin/true")); err != nil {
t.Fatalf("Could not run busybox: %v: %s", err, out)
c.Fatalf("Could not run busybox: %v: %s", err, out)
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rmi", newtag))
if err != nil {
t.Fatalf("Could not remove tag %s: %v: %s", newtag, err, out)
c.Fatalf("Could not remove tag %s: %v: %s", newtag, err, out)
}
if d := strings.Count(out, "Untagged: "); d != 1 {
t.Fatalf("Expected 1 untagged entry got %d: %q", d, out)
c.Fatalf("Expected 1 untagged entry got %d: %q", d, out)
}
logDone("rmi - delete tag with existing containers")
}
func TestRmiForceWithExistingContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmiForceWithExistingContainers(c *check.C) {
image := "busybox-clone"
@ -147,64 +142,60 @@ func TestRmiForceWithExistingContainers(t *testing.T) {
MAINTAINER foo`)
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatalf("Could not build %s: %s, %v", image, out, err)
c.Fatalf("Could not build %s: %s, %v", image, out, err)
}
if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name", "test-force-rmi", image, "/bin/true")); err != nil {
t.Fatalf("Could not run container: %s, %v", out, err)
c.Fatalf("Could not run container: %s, %v", out, err)
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "rmi", "-f", image))
if err != nil {
t.Fatalf("Could not remove image %s: %s, %v", image, out, err)
c.Fatalf("Could not remove image %s: %s, %v", image, out, err)
}
logDone("rmi - force delete with existing containers")
}
func TestRmiWithMultipleRepositories(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRmiWithMultipleRepositories(c *check.C) {
newRepo := "127.0.0.1:5000/busybox"
oldRepo := "busybox"
newTag := "busybox:test"
cmd := exec.Command(dockerBinary, "tag", oldRepo, newRepo)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("Could not tag busybox: %v: %s", err, out)
c.Fatalf("Could not tag busybox: %v: %s", err, out)
}
cmd = exec.Command(dockerBinary, "run", "--name", "test", oldRepo, "touch", "/home/abcd")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to run container: %v, output: %s", err, out)
c.Fatalf("failed to run container: %v, output: %s", err, out)
}
cmd = exec.Command(dockerBinary, "commit", "test", newTag)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to commit container: %v, output: %s", err, out)
c.Fatalf("failed to commit container: %v, output: %s", err, out)
}
cmd = exec.Command(dockerBinary, "rmi", newTag)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatalf("failed to remove image: %v, output: %s", err, out)
c.Fatalf("failed to remove image: %v, output: %s", err, out)
}
if !strings.Contains(out, "Untagged: "+newTag) {
t.Fatalf("Could not remove image %s: %s, %v", newTag, out, err)
c.Fatalf("Could not remove image %s: %s, %v", newTag, out, err)
}
logDone("rmi - delete a image which its dependency tagged to multiple repositories success")
}
func TestRmiBlank(t *testing.T) {
func (s *DockerSuite) TestRmiBlank(c *check.C) {
// try to delete a blank image name
runCmd := exec.Command(dockerBinary, "rmi", "")
out, _, err := runCommandWithOutput(runCmd)
if err == nil {
t.Fatal("Should have failed to delete '' image")
c.Fatal("Should have failed to delete '' image")
}
if strings.Contains(out, "No such image") {
t.Fatalf("Wrong error message generated: %s", out)
c.Fatalf("Wrong error message generated: %s", out)
}
logDone("rmi - blank image name")
}

File diff suppressed because it is too large Load diff

View file

@ -11,22 +11,19 @@ import (
"path"
"path/filepath"
"strings"
"testing"
"time"
"github.com/docker/docker/pkg/mount"
"github.com/go-check/check"
"github.com/kr/pty"
)
// #6509
func TestRunRedirectStdout(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRunRedirectStdout(c *check.C) {
checkRedirect := func(command string) {
_, tty, err := pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd := exec.Command("sh", "-c", command)
cmd.Stdin = tty
@ -34,35 +31,31 @@ func TestRunRedirectStdout(t *testing.T) {
cmd.Stderr = tty
ch := make(chan struct{})
if err := cmd.Start(); err != nil {
t.Fatalf("start err: %v", err)
c.Fatalf("start err: %v", err)
}
go func() {
if err := cmd.Wait(); err != nil {
t.Fatalf("wait err=%v", err)
c.Fatalf("wait err=%v", err)
}
close(ch)
}()
select {
case <-time.After(10 * time.Second):
t.Fatal("command timeout")
c.Fatal("command timeout")
case <-ch:
}
}
checkRedirect(dockerBinary + " run -i busybox cat /etc/passwd | grep -q root")
checkRedirect(dockerBinary + " run busybox cat /etc/passwd | grep -q root")
logDone("run - redirect stdout")
}
// Test recursive bind mount works by default
func TestRunWithVolumesIsRecursive(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRunWithVolumesIsRecursive(c *check.C) {
tmpDir, err := ioutil.TempDir("", "docker_recursive_mount_test")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer os.RemoveAll(tmpDir)
@ -70,68 +63,62 @@ func TestRunWithVolumesIsRecursive(t *testing.T) {
// Create a temporary tmpfs mount.
tmpfsDir := filepath.Join(tmpDir, "tmpfs")
if err := os.MkdirAll(tmpfsDir, 0777); err != nil {
t.Fatalf("failed to mkdir at %s - %s", tmpfsDir, err)
c.Fatalf("failed to mkdir at %s - %s", tmpfsDir, err)
}
if err := mount.Mount("tmpfs", tmpfsDir, "tmpfs", ""); err != nil {
t.Fatalf("failed to create a tmpfs mount at %s - %s", tmpfsDir, err)
c.Fatalf("failed to create a tmpfs mount at %s - %s", tmpfsDir, err)
}
f, err := ioutil.TempFile(tmpfsDir, "touch-me")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer f.Close()
runCmd := exec.Command(dockerBinary, "run", "--name", "test-data", "--volume", fmt.Sprintf("%s:/tmp:ro", tmpDir), "busybox:latest", "ls", "/tmp/tmpfs")
out, stderr, exitCode, err := runCommandWithStdoutStderr(runCmd)
if err != nil && exitCode != 0 {
t.Fatal(out, stderr, err)
c.Fatal(out, stderr, err)
}
if !strings.Contains(out, filepath.Base(f.Name())) {
t.Fatal("Recursive bind mount test failed. Expected file not found")
c.Fatal("Recursive bind mount test failed. Expected file not found")
}
logDone("run - volumes are bind mounted recursively")
}
func TestRunWithUlimits(t *testing.T) {
testRequires(t, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestRunWithUlimits(c *check.C) {
testRequires(c, NativeExecDriver)
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--name=testulimits", "--ulimit", "nofile=42", "busybox", "/bin/sh", "-c", "ulimit -n"))
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
ul := strings.TrimSpace(out)
if ul != "42" {
t.Fatalf("expected `ulimit -n` to be 42, got %s", ul)
c.Fatalf("expected `ulimit -n` to be 42, got %s", ul)
}
logDone("run - ulimits are set")
}
func TestRunContainerWithCgroupParent(t *testing.T) {
testRequires(t, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestRunContainerWithCgroupParent(c *check.C) {
testRequires(c, NativeExecDriver)
cgroupParent := "test"
data, err := ioutil.ReadFile("/proc/self/cgroup")
if err != nil {
t.Fatalf("failed to read '/proc/self/cgroup - %v", err)
c.Fatalf("failed to read '/proc/self/cgroup - %v", err)
}
selfCgroupPaths := parseCgroupPaths(string(data))
selfCpuCgroup, found := selfCgroupPaths["memory"]
if !found {
t.Fatalf("unable to find self cpu cgroup path. CgroupsPath: %v", selfCgroupPaths)
c.Fatalf("unable to find self cpu cgroup path. CgroupsPath: %v", selfCgroupPaths)
}
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--cgroup-parent", cgroupParent, "--rm", "busybox", "cat", "/proc/self/cgroup"))
if err != nil {
t.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
}
cgroupPaths := parseCgroupPaths(string(out))
if len(cgroupPaths) == 0 {
t.Fatalf("unexpected output - %q", string(out))
c.Fatalf("unexpected output - %q", string(out))
}
found = false
expectedCgroupPrefix := path.Join(selfCpuCgroup, cgroupParent)
@ -142,24 +129,22 @@ func TestRunContainerWithCgroupParent(t *testing.T) {
}
}
if !found {
t.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", expectedCgroupPrefix, cgroupPaths)
c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", expectedCgroupPrefix, cgroupPaths)
}
logDone("run - cgroup parent")
}
func TestRunContainerWithCgroupParentAbsPath(t *testing.T) {
testRequires(t, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestRunContainerWithCgroupParentAbsPath(c *check.C) {
testRequires(c, NativeExecDriver)
cgroupParent := "/cgroup-parent/test"
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--cgroup-parent", cgroupParent, "--rm", "busybox", "cat", "/proc/self/cgroup"))
if err != nil {
t.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
}
cgroupPaths := parseCgroupPaths(string(out))
if len(cgroupPaths) == 0 {
t.Fatalf("unexpected output - %q", string(out))
c.Fatalf("unexpected output - %q", string(out))
}
found := false
for _, path := range cgroupPaths {
@ -169,81 +154,75 @@ func TestRunContainerWithCgroupParentAbsPath(t *testing.T) {
}
}
if !found {
t.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", cgroupParent, cgroupPaths)
c.Fatalf("unexpected cgroup paths. Expected at least one cgroup path to have prefix %q. Cgroup Paths: %v", cgroupParent, cgroupPaths)
}
logDone("run - cgroup parent with absolute cgroup path")
}
func TestRunDeviceDirectory(t *testing.T) {
testRequires(t, NativeExecDriver)
defer deleteAllContainers()
func (s *DockerSuite) TestRunDeviceDirectory(c *check.C) {
testRequires(c, NativeExecDriver)
cmd := exec.Command(dockerBinary, "run", "--device", "/dev/snd:/dev/snd", "busybox", "sh", "-c", "ls /dev/snd/")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if actual := strings.Trim(out, "\r\n"); !strings.Contains(out, "timer") {
t.Fatalf("expected output /dev/snd/timer, received %s", actual)
c.Fatalf("expected output /dev/snd/timer, received %s", actual)
}
cmd = exec.Command(dockerBinary, "run", "--device", "/dev/snd:/dev/othersnd", "busybox", "sh", "-c", "ls /dev/othersnd/")
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
if actual := strings.Trim(out, "\r\n"); !strings.Contains(out, "seq") {
t.Fatalf("expected output /dev/othersnd/seq, received %s", actual)
c.Fatalf("expected output /dev/othersnd/seq, received %s", actual)
}
logDone("run - test --device directory mounts all internal devices")
}
// TestRunDetach checks attaching and detaching with the escape sequence.
func TestRunAttachDetach(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestRunAttachDetach(c *check.C) {
name := "attach-detach"
cmd := exec.Command(dockerBinary, "run", "--name", name, "-it", "busybox", "cat")
stdout, err := cmd.StdoutPipe()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
cpty, tty, err := pty.Open()
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
defer cpty.Close()
cmd.Stdin = tty
if err := cmd.Start(); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if err := waitRun(name); err != nil {
t.Fatal(err)
c.Fatal(err)
}
if _, err := cpty.Write([]byte("hello\n")); err != nil {
t.Fatal(err)
c.Fatal(err)
}
out, err := bufio.NewReader(stdout).ReadString('\n')
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if strings.TrimSpace(out) != "hello" {
t.Fatalf("exepected 'hello', got %q", out)
c.Fatalf("exepected 'hello', got %q", out)
}
// escape sequence
if _, err := cpty.Write([]byte{16}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
time.Sleep(100 * time.Millisecond)
if _, err := cpty.Write([]byte{17}); err != nil {
t.Fatal(err)
c.Fatal(err)
}
ch := make(chan struct{})
@ -254,21 +233,19 @@ func TestRunAttachDetach(t *testing.T) {
running, err := inspectField(name, "State.Running")
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if running != "true" {
t.Fatal("exepected container to still be running")
c.Fatal("exepected container to still be running")
}
go func() {
dockerCmd(t, "kill", name)
exec.Command(dockerBinary, "kill", name).Run()
}()
select {
case <-ch:
case <-time.After(10 * time.Millisecond):
t.Fatal("timed out waiting for container to exit")
c.Fatal("timed out waiting for container to exit")
}
logDone("run - attach detach")
}

View file

@ -9,15 +9,16 @@ import (
"reflect"
"sort"
"strings"
"testing"
"github.com/go-check/check"
)
// save a repo using gz compression and try to load it using stdout
func TestSaveXzAndLoadRepoStdout(t *testing.T) {
func (s *DockerSuite) TestSaveXzAndLoadRepoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %v %v", out, err)
c.Fatalf("failed to create a container: %v %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -27,19 +28,19 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
c.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container: %v %v", out, err)
c.Fatalf("failed to commit container: %v %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist before saving it: %v %v", before, err)
c.Fatalf("the repo should exist before saving it: %v %v", before, err)
}
repoTarball, _, err := runCommandPipelineWithOutput(
@ -47,7 +48,7 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
exec.Command("xz", "-c"),
exec.Command("gzip", "-c"))
if err != nil {
t.Fatalf("failed to save repo: %v %v", out, err)
c.Fatalf("failed to save repo: %v %v", out, err)
}
deleteImages(repoName)
@ -55,26 +56,25 @@ func TestSaveXzAndLoadRepoStdout(t *testing.T) {
loadCmd.Stdin = strings.NewReader(repoTarball)
out, _, err = runCommandWithOutput(loadCmd)
if err == nil {
t.Fatalf("expected error, but succeeded with no error and output: %v", out)
c.Fatalf("expected error, but succeeded with no error and output: %v", out)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
after, _, err := runCommandWithOutput(inspectCmd)
if err == nil {
t.Fatalf("the repo should not exist: %v", after)
c.Fatalf("the repo should not exist: %v", after)
}
deleteImages(repoName)
logDone("load - save a repo with xz compression & load it using stdout")
}
// save a repo using xz+gz compression and try to load it using stdout
func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
func (s *DockerSuite) TestSaveXzGzAndLoadRepoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %v %v", out, err)
c.Fatalf("failed to create a container: %v %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -84,19 +84,19 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
out, _, err = runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
c.Fatalf("output should've been a container id: %v %v", cleanedContainerID, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
out, _, err = runCommandWithOutput(commitCmd)
if err != nil {
t.Fatalf("failed to commit container: %v %v", out, err)
c.Fatalf("failed to commit container: %v %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist before saving it: %v %v", before, err)
c.Fatalf("the repo should exist before saving it: %v %v", before, err)
}
out, _, err = runCommandPipelineWithOutput(
@ -104,7 +104,7 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
exec.Command("xz", "-c"),
exec.Command("gzip", "-c"))
if err != nil {
t.Fatalf("failed to save repo: %v %v", out, err)
c.Fatalf("failed to save repo: %v %v", out, err)
}
deleteImages(repoName)
@ -113,34 +113,33 @@ func TestSaveXzGzAndLoadRepoStdout(t *testing.T) {
loadCmd.Stdin = strings.NewReader(out)
out, _, err = runCommandWithOutput(loadCmd)
if err == nil {
t.Fatalf("expected error, but succeeded with no error and output: %v", out)
c.Fatalf("expected error, but succeeded with no error and output: %v", out)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
after, _, err := runCommandWithOutput(inspectCmd)
if err == nil {
t.Fatalf("the repo should not exist: %v", after)
c.Fatalf("the repo should not exist: %v", after)
}
deleteContainer(cleanedContainerID)
deleteImages(repoName)
logDone("load - save a repo with xz+gz compression & load it using stdout")
}
func TestSaveSingleTag(t *testing.T) {
func (s *DockerSuite) TestSaveSingleTag(c *check.C) {
repoName := "foobar-save-single-tag-test"
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", fmt.Sprintf("%v:latest", repoName))
defer deleteImages(repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err)
c.Fatalf("failed to tag repo: %s, %v", out, err)
}
idCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName)
out, _, err := runCommandWithOutput(idCmd)
if err != nil {
t.Fatalf("failed to get repo ID: %s, %v", out, err)
c.Fatalf("failed to get repo ID: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
@ -149,25 +148,24 @@ func TestSaveSingleTag(t *testing.T) {
exec.Command("tar", "t"),
exec.Command("grep", "-E", fmt.Sprintf("(^repositories$|%v)", cleanedImageID)))
if err != nil {
t.Fatalf("failed to save repo with image ID and 'repositories' file: %s, %v", out, err)
c.Fatalf("failed to save repo with image ID and 'repositories' file: %s, %v", out, err)
}
logDone("save - save a specific image:tag")
}
func TestSaveImageId(t *testing.T) {
func (s *DockerSuite) TestSaveImageId(c *check.C) {
repoName := "foobar-save-image-id-test"
tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v:latest", repoName))
defer deleteImages(repoName)
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err)
c.Fatalf("failed to tag repo: %s, %v", out, err)
}
idLongCmd := exec.Command(dockerBinary, "images", "-q", "--no-trunc", repoName)
out, _, err := runCommandWithOutput(idLongCmd)
if err != nil {
t.Fatalf("failed to get repo ID: %s, %v", out, err)
c.Fatalf("failed to get repo ID: %s, %v", out, err)
}
cleanedLongImageID := strings.TrimSpace(out)
@ -175,7 +173,7 @@ func TestSaveImageId(t *testing.T) {
idShortCmd := exec.Command(dockerBinary, "images", "-q", repoName)
out, _, err = runCommandWithOutput(idShortCmd)
if err != nil {
t.Fatalf("failed to get repo short ID: %s, %v", out, err)
c.Fatalf("failed to get repo short ID: %s, %v", out, err)
}
cleanedShortImageID := strings.TrimSpace(out)
@ -184,19 +182,19 @@ func TestSaveImageId(t *testing.T) {
tarCmd := exec.Command("tar", "t")
tarCmd.Stdin, err = saveCmd.StdoutPipe()
if err != nil {
t.Fatalf("cannot set stdout pipe for tar: %v", err)
c.Fatalf("cannot set stdout pipe for tar: %v", err)
}
grepCmd := exec.Command("grep", cleanedLongImageID)
grepCmd.Stdin, err = tarCmd.StdoutPipe()
if err != nil {
t.Fatalf("cannot set stdout pipe for grep: %v", err)
c.Fatalf("cannot set stdout pipe for grep: %v", err)
}
if err = tarCmd.Start(); err != nil {
t.Fatalf("tar failed with error: %v", err)
c.Fatalf("tar failed with error: %v", err)
}
if err = saveCmd.Start(); err != nil {
t.Fatalf("docker save failed with error: %v", err)
c.Fatalf("docker save failed with error: %v", err)
}
defer saveCmd.Wait()
defer tarCmd.Wait()
@ -204,18 +202,17 @@ func TestSaveImageId(t *testing.T) {
out, _, err = runCommandWithOutput(grepCmd)
if err != nil {
t.Fatalf("failed to save repo with image ID: %s, %v", out, err)
c.Fatalf("failed to save repo with image ID: %s, %v", out, err)
}
logDone("save - save a image by ID")
}
// save a repo and try to load it using flags
func TestSaveAndLoadRepoFlags(t *testing.T) {
func (s *DockerSuite) TestSaveAndLoadRepoFlags(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -225,19 +222,19 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("output should've been a container id: %s, %v", out, err)
c.Fatalf("output should've been a container id: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
deleteImages(repoName)
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container: %s, %v", out, err)
c.Fatalf("failed to commit container: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist before saving it: %s, %v", before, err)
c.Fatalf("the repo should exist before saving it: %s, %v", before, err)
}
@ -245,29 +242,28 @@ func TestSaveAndLoadRepoFlags(t *testing.T) {
exec.Command(dockerBinary, "save", repoName),
exec.Command(dockerBinary, "load"))
if err != nil {
t.Fatalf("failed to save and load repo: %s, %v", out, err)
c.Fatalf("failed to save and load repo: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
after, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist after loading it: %s, %v", after, err)
c.Fatalf("the repo should exist after loading it: %s, %v", after, err)
}
if before != after {
t.Fatalf("inspect is not the same after a save / load")
c.Fatalf("inspect is not the same after a save / load")
}
logDone("save - save a repo using -o && load a repo using -i")
}
func TestSaveMultipleNames(t *testing.T) {
func (s *DockerSuite) TestSaveMultipleNames(c *check.C) {
repoName := "foobar-save-multi-name-test"
// Make one image
tagCmd := exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-one:latest", repoName))
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err)
c.Fatalf("failed to tag repo: %s, %v", out, err)
}
defer deleteImages(repoName + "-one")
@ -275,7 +271,7 @@ func TestSaveMultipleNames(t *testing.T) {
tagCmd = exec.Command(dockerBinary, "tag", "emptyfs:latest", fmt.Sprintf("%v-two:latest", repoName))
out, _, err := runCommandWithOutput(tagCmd)
if err != nil {
t.Fatalf("failed to tag repo: %s, %v", out, err)
c.Fatalf("failed to tag repo: %s, %v", out, err)
}
defer deleteImages(repoName + "-two")
@ -285,13 +281,12 @@ func TestSaveMultipleNames(t *testing.T) {
exec.Command("grep", "-q", "-E", "(-one|-two)"),
)
if err != nil {
t.Fatalf("failed to save multiple repos: %s, %v", out, err)
c.Fatalf("failed to save multiple repos: %s, %v", out, err)
}
logDone("save - save by multiple names")
}
func TestSaveRepoWithMultipleImages(t *testing.T) {
func (s *DockerSuite) TestSaveRepoWithMultipleImages(c *check.C) {
makeImage := func(from string, tag string) string {
runCmd := exec.Command(dockerBinary, "run", "-d", from, "true")
@ -300,14 +295,14 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
err error
)
if out, _, err = runCommandWithOutput(runCmd); err != nil {
t.Fatalf("failed to create a container: %v %v", out, err)
c.Fatalf("failed to create a container: %v %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
defer deleteContainer(cleanedContainerID)
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, tag)
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container: %v %v", out, err)
c.Fatalf("failed to commit container: %v %v", out, err)
}
imageID := strings.TrimSpace(out)
return imageID
@ -331,14 +326,14 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
exec.Command("grep", "VERSION"),
exec.Command("cut", "-d", "/", "-f1"))
if err != nil {
t.Fatalf("failed to save multiple images: %s, %v", out, err)
c.Fatalf("failed to save multiple images: %s, %v", out, err)
}
actual := strings.Split(strings.TrimSpace(out), "\n")
// make the list of expected layers
out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "history", "-q", "--no-trunc", "busybox:latest"))
if err != nil {
t.Fatalf("failed to get history: %s, %v", out, err)
c.Fatalf("failed to get history: %s, %v", out, err)
}
expected := append(strings.Split(strings.TrimSpace(out), "\n"), idFoo, idBar)
@ -346,21 +341,20 @@ func TestSaveRepoWithMultipleImages(t *testing.T) {
sort.Strings(actual)
sort.Strings(expected)
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("achive does not contains the right layers: got %v, expected %v", actual, expected)
c.Fatalf("achive does not contains the right layers: got %v, expected %v", actual, expected)
}
logDone("save - save repository with multiple images")
}
// Issue #6722 #5892 ensure directories are included in changes
func TestSaveDirectoryPermissions(t *testing.T) {
func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
layerEntries := []string{"opt/", "opt/a/", "opt/a/b/", "opt/a/b/c"}
layerEntriesAUFS := []string{"./", ".wh..wh.aufs", ".wh..wh.orph/", ".wh..wh.plnk/", "opt/", "opt/a/", "opt/a/b/", "opt/a/b/c"}
name := "save-directory-permissions"
tmpDir, err := ioutil.TempDir("", "save-layers-with-directories")
if err != nil {
t.Errorf("failed to create temporary directory: %s", err)
c.Errorf("failed to create temporary directory: %s", err)
}
extractionDirectory := filepath.Join(tmpDir, "image-extraction-dir")
os.Mkdir(extractionDirectory, 0777)
@ -373,19 +367,19 @@ func TestSaveDirectoryPermissions(t *testing.T) {
RUN touch /opt/a/b/c && chown user:user /opt/a/b/c`,
true)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
if out, _, err := runCommandPipelineWithOutput(
exec.Command(dockerBinary, "save", name),
exec.Command("tar", "-xf", "-", "-C", extractionDirectory),
); err != nil {
t.Errorf("failed to save and extract image: %s", out)
c.Errorf("failed to save and extract image: %s", out)
}
dirs, err := ioutil.ReadDir(extractionDirectory)
if err != nil {
t.Errorf("failed to get a listing of the layer directories: %s", err)
c.Errorf("failed to get a listing of the layer directories: %s", err)
}
found := false
@ -396,7 +390,7 @@ func TestSaveDirectoryPermissions(t *testing.T) {
f, err := os.Open(layerPath)
if err != nil {
t.Fatalf("failed to open %s: %s", layerPath, err)
c.Fatalf("failed to open %s: %s", layerPath, err)
}
entries, err := ListTar(f)
@ -406,7 +400,7 @@ func TestSaveDirectoryPermissions(t *testing.T) {
}
}
if err != nil {
t.Fatalf("encountered error while listing tar entries: %s", err)
c.Fatalf("encountered error while listing tar entries: %s", err)
}
if reflect.DeepEqual(entriesSansDev, layerEntries) || reflect.DeepEqual(entriesSansDev, layerEntriesAUFS) {
@ -417,8 +411,7 @@ func TestSaveDirectoryPermissions(t *testing.T) {
}
if !found {
t.Fatalf("failed to find the layer with the right content listing")
c.Fatalf("failed to find the layer with the right content listing")
}
logDone("save - ensure directories exist in exported layers")
}

View file

@ -8,17 +8,17 @@ import (
"os"
"os/exec"
"strings"
"testing"
"github.com/docker/docker/vendor/src/github.com/kr/pty"
"github.com/go-check/check"
)
// save a repo and try to load it using stdout
func TestSaveAndLoadRepoStdout(t *testing.T) {
func (s *DockerSuite) TestSaveAndLoadRepoStdout(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to create a container: %s, %v", out, err)
c.Fatalf("failed to create a container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -27,25 +27,25 @@ func TestSaveAndLoadRepoStdout(t *testing.T) {
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedContainerID)
if out, _, err = runCommandWithOutput(inspectCmd); err != nil {
t.Fatalf("output should've been a container id: %s, %v", out, err)
c.Fatalf("output should've been a container id: %s, %v", out, err)
}
commitCmd := exec.Command(dockerBinary, "commit", cleanedContainerID, repoName)
if out, _, err = runCommandWithOutput(commitCmd); err != nil {
t.Fatalf("failed to commit container: %s, %v", out, err)
c.Fatalf("failed to commit container: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
before, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist before saving it: %s, %v", before, err)
c.Fatalf("the repo should exist before saving it: %s, %v", before, err)
}
saveCmdTemplate := `%v save %v > /tmp/foobar-save-load-test.tar`
saveCmdFinal := fmt.Sprintf(saveCmdTemplate, dockerBinary, repoName)
saveCmd := exec.Command("bash", "-c", saveCmdFinal)
if out, _, err = runCommandWithOutput(saveCmd); err != nil {
t.Fatalf("failed to save repo: %s, %v", out, err)
c.Fatalf("failed to save repo: %s, %v", out, err)
}
deleteImages(repoName)
@ -53,17 +53,17 @@ func TestSaveAndLoadRepoStdout(t *testing.T) {
loadCmdFinal := `cat /tmp/foobar-save-load-test.tar | docker load`
loadCmd := exec.Command("bash", "-c", loadCmdFinal)
if out, _, err = runCommandWithOutput(loadCmd); err != nil {
t.Fatalf("failed to load repo: %s, %v", out, err)
c.Fatalf("failed to load repo: %s, %v", out, err)
}
inspectCmd = exec.Command(dockerBinary, "inspect", repoName)
after, _, err := runCommandWithOutput(inspectCmd)
if err != nil {
t.Fatalf("the repo should exist after loading it: %s %v", after, err)
c.Fatalf("the repo should exist after loading it: %s %v", after, err)
}
if before != after {
t.Fatalf("inspect is not the same after a save / load")
c.Fatalf("inspect is not the same after a save / load")
}
deleteContainer(cleanedContainerID)
@ -73,29 +73,28 @@ func TestSaveAndLoadRepoStdout(t *testing.T) {
pty, tty, err := pty.Open()
if err != nil {
t.Fatalf("Could not open pty: %v", err)
c.Fatalf("Could not open pty: %v", err)
}
cmd := exec.Command(dockerBinary, "save", repoName)
cmd.Stdin = tty
cmd.Stdout = tty
cmd.Stderr = tty
if err := cmd.Start(); err != nil {
t.Fatalf("start err: %v", err)
c.Fatalf("start err: %v", err)
}
if err := cmd.Wait(); err == nil {
t.Fatal("did not break writing to a TTY")
c.Fatal("did not break writing to a TTY")
}
buf := make([]byte, 1024)
n, err := pty.Read(buf)
if err != nil {
t.Fatal("could not read tty output")
c.Fatal("could not read tty output")
}
if !bytes.Contains(buf[:n], []byte("Cowardly refusing")) {
t.Fatal("help output is not being yielded", out)
c.Fatal("help output is not being yielded", out)
}
logDone("save - save/load a repo using stdout")
}

View file

@ -3,95 +3,93 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// search for repos named "registry" on the central registry
func TestSearchOnCentralRegistry(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestSearchOnCentralRegistry(c *check.C) {
testRequires(c, Network)
searchCmd := exec.Command(dockerBinary, "search", "busybox")
out, exitCode, err := runCommandWithOutput(searchCmd)
if err != nil || exitCode != 0 {
t.Fatalf("failed to search on the central registry: %s, %v", out, err)
c.Fatalf("failed to search on the central registry: %s, %v", out, err)
}
if !strings.Contains(out, "Busybox base image.") {
t.Fatal("couldn't find any repository named (or containing) 'Busybox base image.'")
c.Fatal("couldn't find any repository named (or containing) 'Busybox base image.'")
}
logDone("search - search for repositories named (or containing) 'Busybox base image.'")
}
func TestSearchStarsOptionWithWrongParameter(t *testing.T) {
func (s *DockerSuite) TestSearchStarsOptionWithWrongParameter(c *check.C) {
searchCmdStarsChars := exec.Command(dockerBinary, "search", "--stars=a", "busybox")
out, exitCode, err := runCommandWithOutput(searchCmdStarsChars)
if err == nil || exitCode == 0 {
t.Fatalf("Should not get right information: %s, %v", out, err)
c.Fatalf("Should not get right information: %s, %v", out, err)
}
if !strings.Contains(out, "invalid value") {
t.Fatal("couldn't find the invalid value warning")
c.Fatal("couldn't find the invalid value warning")
}
searchCmdStarsNegativeNumber := exec.Command(dockerBinary, "search", "-s=-1", "busybox")
out, exitCode, err = runCommandWithOutput(searchCmdStarsNegativeNumber)
if err == nil || exitCode == 0 {
t.Fatalf("Should not get right information: %s, %v", out, err)
c.Fatalf("Should not get right information: %s, %v", out, err)
}
if !strings.Contains(out, "invalid value") {
t.Fatal("couldn't find the invalid value warning")
c.Fatal("couldn't find the invalid value warning")
}
logDone("search - Verify search with wrong parameter.")
}
func TestSearchCmdOptions(t *testing.T) {
testRequires(t, Network)
func (s *DockerSuite) TestSearchCmdOptions(c *check.C) {
testRequires(c, Network)
searchCmdhelp := exec.Command(dockerBinary, "search", "--help")
out, exitCode, err := runCommandWithOutput(searchCmdhelp)
if err != nil || exitCode != 0 {
t.Fatalf("failed to get search help information: %s, %v", out, err)
c.Fatalf("failed to get search help information: %s, %v", out, err)
}
if !strings.Contains(out, "Usage: docker search [OPTIONS] TERM") {
t.Fatalf("failed to show docker search usage: %s, %v", out, err)
c.Fatalf("failed to show docker search usage: %s, %v", out, err)
}
searchCmd := exec.Command(dockerBinary, "search", "busybox")
outSearchCmd, exitCode, err := runCommandWithOutput(searchCmd)
if err != nil || exitCode != 0 {
t.Fatalf("failed to search on the central registry: %s, %v", outSearchCmd, err)
c.Fatalf("failed to search on the central registry: %s, %v", outSearchCmd, err)
}
searchCmdautomated := exec.Command(dockerBinary, "search", "--automated=true", "busybox")
outSearchCmdautomated, exitCode, err := runCommandWithOutput(searchCmdautomated) //The busybox is a busybox base image, not an AUTOMATED image.
if err != nil || exitCode != 0 {
t.Fatalf("failed to search with automated=true on the central registry: %s, %v", outSearchCmdautomated, err)
c.Fatalf("failed to search with automated=true on the central registry: %s, %v", outSearchCmdautomated, err)
}
outSearchCmdautomatedSlice := strings.Split(outSearchCmdautomated, "\n")
for i := range outSearchCmdautomatedSlice {
if strings.HasPrefix(outSearchCmdautomatedSlice[i], "busybox ") {
t.Fatalf("The busybox is not an AUTOMATED image: %s, %v", out, err)
c.Fatalf("The busybox is not an AUTOMATED image: %s, %v", out, err)
}
}
searchCmdStars := exec.Command(dockerBinary, "search", "-s=2", "busybox")
outSearchCmdStars, exitCode, err := runCommandWithOutput(searchCmdStars)
if err != nil || exitCode != 0 {
t.Fatalf("failed to search with stars=2 on the central registry: %s, %v", outSearchCmdStars, err)
c.Fatalf("failed to search with stars=2 on the central registry: %s, %v", outSearchCmdStars, err)
}
if strings.Count(outSearchCmdStars, "[OK]") > strings.Count(outSearchCmd, "[OK]") {
t.Fatalf("The quantity of images with stars should be less than that of all images: %s, %v", outSearchCmdStars, err)
c.Fatalf("The quantity of images with stars should be less than that of all images: %s, %v", outSearchCmdStars, err)
}
searchCmdOptions := exec.Command(dockerBinary, "search", "--stars=2", "--automated=true", "--no-trunc=true", "busybox")
out, exitCode, err = runCommandWithOutput(searchCmdOptions)
if err != nil || exitCode != 0 {
t.Fatalf("failed to search with stars&automated&no-trunc options on the central registry: %s, %v", out, err)
c.Fatalf("failed to search with stars&automated&no-trunc options on the central registry: %s, %v", out, err)
}
logDone("search - have a try for search options.")
}

View file

@ -4,20 +4,20 @@ import (
"fmt"
"os/exec"
"strings"
"testing"
"time"
"github.com/go-check/check"
)
// Regression test for https://github.com/docker/docker/issues/7843
func TestStartAttachReturnsOnError(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartAttachReturnsOnError(c *check.C) {
dockerCmd(t, "run", "-d", "--name", "test", "busybox")
dockerCmd(t, "wait", "test")
dockerCmd(c, "run", "-d", "--name", "test", "busybox")
dockerCmd(c, "wait", "test")
// Expect this to fail because the above container is stopped, this is what we want
if _, err := runCommand(exec.Command(dockerBinary, "run", "-d", "--name", "test2", "--link", "test:test", "busybox")); err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
ch := make(chan struct{})
@ -25,7 +25,7 @@ func TestStartAttachReturnsOnError(t *testing.T) {
// Attempt to start attached to the container that won't start
// This should return an error immediately since the container can't be started
if _, err := runCommand(exec.Command(dockerBinary, "start", "-a", "test2")); err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
close(ch)
}()
@ -33,20 +33,18 @@ func TestStartAttachReturnsOnError(t *testing.T) {
select {
case <-ch:
case <-time.After(time.Second):
t.Fatalf("Attach did not exit properly")
c.Fatalf("Attach did not exit properly")
}
logDone("start - error on start with attach exits")
}
// gh#8555: Exit code should be passed through when using start -a
func TestStartAttachCorrectExitCode(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartAttachCorrectExitCode(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "sleep 2; exit 1")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("failed to run container: %v, output: %q", err, out)
c.Fatalf("failed to run container: %v, output: %q", err, out)
}
out = strings.TrimSpace(out)
@ -54,167 +52,157 @@ func TestStartAttachCorrectExitCode(t *testing.T) {
// make sure the container has exited before trying the "start -a"
waitCmd := exec.Command(dockerBinary, "wait", out)
if _, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("Failed to wait on container: %v", err)
c.Fatalf("Failed to wait on container: %v", err)
}
startCmd := exec.Command(dockerBinary, "start", "-a", out)
startOut, exitCode, err := runCommandWithOutput(startCmd)
if err != nil && !strings.Contains("exit status 1", fmt.Sprintf("%s", err)) {
t.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
c.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
}
if exitCode != 1 {
t.Fatalf("start -a did not respond with proper exit code: expected 1, got %d", exitCode)
c.Fatalf("start -a did not respond with proper exit code: expected 1, got %d", exitCode)
}
logDone("start - correct exit code returned with -a")
}
func TestStartAttachSilent(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartAttachSilent(c *check.C) {
name := "teststartattachcorrectexitcode"
runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "echo", "test")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
if err != nil {
t.Fatalf("failed to run container: %v, output: %q", err, out)
c.Fatalf("failed to run container: %v, output: %q", err, out)
}
// make sure the container has exited before trying the "start -a"
waitCmd := exec.Command(dockerBinary, "wait", name)
if _, _, err = runCommandWithOutput(waitCmd); err != nil {
t.Fatalf("wait command failed with error: %v", err)
c.Fatalf("wait command failed with error: %v", err)
}
startCmd := exec.Command(dockerBinary, "start", "-a", name)
startOut, _, err := runCommandWithOutput(startCmd)
if err != nil {
t.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
c.Fatalf("start command failed unexpectedly with error: %v, output: %q", err, startOut)
}
if expected := "test\n"; startOut != expected {
t.Fatalf("start -a produced unexpected output: expected %q, got %q", expected, startOut)
c.Fatalf("start -a produced unexpected output: expected %q, got %q", expected, startOut)
}
logDone("start - don't echo container ID when attaching")
}
func TestStartRecordError(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartRecordError(c *check.C) {
// when container runs successfully, we should not have state.Error
dockerCmd(t, "run", "-d", "-p", "9999:9999", "--name", "test", "busybox", "top")
dockerCmd(c, "run", "-d", "-p", "9999:9999", "--name", "test", "busybox", "top")
stateErr, err := inspectField("test", "State.Error")
if err != nil {
t.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
c.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
}
if stateErr != "" {
t.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
c.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
}
// Expect this to fail and records error because of ports conflict
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", "test2", "-p", "9999:9999", "busybox", "top"))
if err == nil {
t.Fatalf("Expected error but got none, output %q", out)
c.Fatalf("Expected error but got none, output %q", out)
}
stateErr, err = inspectField("test2", "State.Error")
if err != nil {
t.Fatalf("Failed to inspect %q state's error, got error %q", "test2", err)
c.Fatalf("Failed to inspect %q state's error, got error %q", "test2", err)
}
expected := "port is already allocated"
if stateErr == "" || !strings.Contains(stateErr, expected) {
t.Fatalf("State.Error(%q) does not include %q", stateErr, expected)
c.Fatalf("State.Error(%q) does not include %q", stateErr, expected)
}
// Expect the conflict to be resolved when we stop the initial container
dockerCmd(t, "stop", "test")
dockerCmd(t, "start", "test2")
dockerCmd(c, "stop", "test")
dockerCmd(c, "start", "test2")
stateErr, err = inspectField("test2", "State.Error")
if err != nil {
t.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
c.Fatalf("Failed to inspect %q state's error, got error %q", "test", err)
}
if stateErr != "" {
t.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
c.Fatalf("Expected to not have state error but got state.Error(%q)", stateErr)
}
logDone("start - set state error when start is unsuccessful")
}
// gh#8726: a failed Start() breaks --volumes-from on subsequent Start()'s
func TestStartVolumesFromFailsCleanly(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartVolumesFromFailsCleanly(c *check.C) {
// Create the first data volume
dockerCmd(t, "run", "-d", "--name", "data_before", "-v", "/foo", "busybox")
dockerCmd(c, "run", "-d", "--name", "data_before", "-v", "/foo", "busybox")
// Expect this to fail because the data test after contaienr doesn't exist yet
if _, err := runCommand(exec.Command(dockerBinary, "run", "-d", "--name", "consumer", "--volumes-from", "data_before", "--volumes-from", "data_after", "busybox")); err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
// Create the second data volume
dockerCmd(t, "run", "-d", "--name", "data_after", "-v", "/bar", "busybox")
dockerCmd(c, "run", "-d", "--name", "data_after", "-v", "/bar", "busybox")
// Now, all the volumes should be there
dockerCmd(t, "start", "consumer")
dockerCmd(c, "start", "consumer")
// Check that we have the volumes we want
out, _ := dockerCmd(t, "inspect", "--format='{{ len .Volumes }}'", "consumer")
out, _ := dockerCmd(c, "inspect", "--format='{{ len .Volumes }}'", "consumer")
nVolumes := strings.Trim(out, " \r\n'")
if nVolumes != "2" {
t.Fatalf("Missing volumes: expected 2, got %s", nVolumes)
c.Fatalf("Missing volumes: expected 2, got %s", nVolumes)
}
logDone("start - missing containers in --volumes-from did not affect subsequent runs")
}
func TestStartPausedContainer(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartPausedContainer(c *check.C) {
defer unpauseAllContainers()
runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "testing", "busybox", "top")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "pause", "testing")
if out, _, err := runCommandWithOutput(runCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
runCmd = exec.Command(dockerBinary, "start", "testing")
if out, _, err := runCommandWithOutput(runCmd); err == nil || !strings.Contains(out, "Cannot start a paused container, try unpause instead.") {
t.Fatalf("an error should have been shown that you cannot start paused container: %s\n%v", out, err)
c.Fatalf("an error should have been shown that you cannot start paused container: %s\n%v", out, err)
}
logDone("start - error should show if trying to start paused container")
}
func TestStartMultipleContainers(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestStartMultipleContainers(c *check.C) {
// run a container named 'parent' and create two container link to `parent`
cmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "busybox", "top")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
for _, container := range []string{"child_first", "child_second"} {
cmd = exec.Command(dockerBinary, "create", "--name", container, "--link", "parent:parent", "busybox", "top")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
}
// stop 'parent' container
cmd = exec.Command(dockerBinary, "stop", "parent")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", "parent")
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
if out != "false" {
t.Fatal("Container should be stopped")
c.Fatal("Container should be stopped")
}
// start all the three containers, container `child_first` start first which should be faild
@ -222,35 +210,33 @@ func TestStartMultipleContainers(t *testing.T) {
cmd = exec.Command(dockerBinary, "start", "child_first", "parent", "child_second")
out, _, err = runCommandWithOutput(cmd)
if !strings.Contains(out, "Cannot start container child_first") || err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
for container, expected := range map[string]string{"parent": "true", "child_first": "false", "child_second": "true"} {
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", container)
out, _, err = runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
if out != expected {
t.Fatal("Container running state wrong")
c.Fatal("Container running state wrong")
}
}
logDone("start - start multiple containers continue on one failed")
}
func TestStartAttachMultipleContainers(t *testing.T) {
func (s *DockerSuite) TestStartAttachMultipleContainers(c *check.C) {
var cmd *exec.Cmd
defer deleteAllContainers()
// run multiple containers to test
for _, container := range []string{"test1", "test2", "test3"} {
cmd = exec.Command(dockerBinary, "run", "-d", "--name", container, "busybox", "top")
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
}
@ -258,7 +244,7 @@ func TestStartAttachMultipleContainers(t *testing.T) {
for _, container := range []string{"test1", "test2", "test3"} {
cmd = exec.Command(dockerBinary, "stop", container)
if out, _, err := runCommandWithOutput(cmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
}
@ -267,7 +253,7 @@ func TestStartAttachMultipleContainers(t *testing.T) {
cmd = exec.Command(dockerBinary, "start", option, "test1", "test2", "test3")
out, _, err := runCommandWithOutput(cmd)
if !strings.Contains(out, "You cannot start and attach multiple containers at once.") || err == nil {
t.Fatal("Expected error but got none")
c.Fatal("Expected error but got none")
}
}
@ -276,13 +262,12 @@ func TestStartAttachMultipleContainers(t *testing.T) {
cmd = exec.Command(dockerBinary, "inspect", "-f", "{{.State.Running}}", container)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
out = strings.Trim(out, "\r\n")
if out != expected {
t.Fatal("Container running state wrong")
c.Fatal("Container running state wrong")
}
}
logDone("start - error on start and attach multiple containers at once")
}

View file

@ -3,48 +3,46 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/docker/docker/pkg/stringutils"
"github.com/go-check/check"
)
// tagging a named image in a new unprefixed repo should work
func TestTagUnprefixedRepoByName(t *testing.T) {
func (s *DockerSuite) TestTagUnprefixedRepoByName(c *check.C) {
if err := pullImageIfNotExist("busybox:latest"); err != nil {
t.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
}
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", "testfoobarbaz")
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
deleteImages("testfoobarbaz")
logDone("tag - busybox -> testfoobarbaz")
}
// tagging an image by ID in a new unprefixed repo should work
func TestTagUnprefixedRepoByID(t *testing.T) {
func (s *DockerSuite) TestTagUnprefixedRepoByID(c *check.C) {
getIDCmd := exec.Command(dockerBinary, "inspect", "-f", "{{.Id}}", "busybox")
out, _, err := runCommandWithOutput(getIDCmd)
if err != nil {
t.Fatalf("failed to get the image ID of busybox: %s, %v", out, err)
c.Fatalf("failed to get the image ID of busybox: %s, %v", out, err)
}
cleanedImageID := strings.TrimSpace(out)
tagCmd := exec.Command(dockerBinary, "tag", cleanedImageID, "testfoobarbaz")
if out, _, err = runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
deleteImages("testfoobarbaz")
logDone("tag - busybox's image ID -> testfoobarbaz")
}
// ensure we don't allow the use of invalid repository names; these tag operations should fail
func TestTagInvalidUnprefixedRepo(t *testing.T) {
func (s *DockerSuite) TestTagInvalidUnprefixedRepo(c *check.C) {
invalidRepos := []string{"fo$z$", "Foo@3cc", "Foo$3", "Foo*3", "Fo^3", "Foo!3", "F)xcz(", "fo%asd"}
@ -52,14 +50,13 @@ func TestTagInvalidUnprefixedRepo(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "busybox", repo)
_, _, err := runCommandWithOutput(tagCmd)
if err == nil {
t.Fatalf("tag busybox %v should have failed", repo)
c.Fatalf("tag busybox %v should have failed", repo)
}
}
logDone("tag - busybox invalid repo names --> must not work")
}
// ensure we don't allow the use of invalid tags; these tag operations should fail
func TestTagInvalidPrefixedRepo(t *testing.T) {
func (s *DockerSuite) TestTagInvalidPrefixedRepo(c *check.C) {
longTag := stringutils.GenerateRandomAlphaOnlyString(121)
invalidTags := []string{"repo:fo$z$", "repo:Foo@3cc", "repo:Foo$3", "repo:Foo*3", "repo:Fo^3", "repo:Foo!3", "repo:%goodbye", "repo:#hashtagit", "repo:F)xcz(", "repo:-foo", "repo:..", longTag}
@ -68,16 +65,15 @@ func TestTagInvalidPrefixedRepo(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "busybox", repotag)
_, _, err := runCommandWithOutput(tagCmd)
if err == nil {
t.Fatalf("tag busybox %v should have failed", repotag)
c.Fatalf("tag busybox %v should have failed", repotag)
}
}
logDone("tag - busybox with invalid repo:tagnames --> must not work")
}
// ensure we allow the use of valid tags
func TestTagValidPrefixedRepo(t *testing.T) {
func (s *DockerSuite) TestTagValidPrefixedRepo(c *check.C) {
if err := pullImageIfNotExist("busybox:latest"); err != nil {
t.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
}
validRepos := []string{"fooo/bar", "fooaa/test", "foooo:t"}
@ -86,56 +82,53 @@ func TestTagValidPrefixedRepo(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", repo)
_, _, err := runCommandWithOutput(tagCmd)
if err != nil {
t.Errorf("tag busybox %v should have worked: %s", repo, err)
c.Errorf("tag busybox %v should have worked: %s", repo, err)
continue
}
deleteImages(repo)
}
logDone("tag - tag valid prefixed repo")
}
// tag an image with an existed tag name without -f option should fail
func TestTagExistedNameWithoutForce(t *testing.T) {
func (s *DockerSuite) TestTagExistedNameWithoutForce(c *check.C) {
if err := pullImageIfNotExist("busybox:latest"); err != nil {
t.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
}
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", "busybox:test")
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
tagCmd = exec.Command(dockerBinary, "tag", "busybox:latest", "busybox:test")
out, _, err := runCommandWithOutput(tagCmd)
if err == nil || !strings.Contains(out, "Conflict: Tag test is already set to image") {
t.Fatal("tag busybox busybox:test should have failed,because busybox:test is existed")
c.Fatal("tag busybox busybox:test should have failed,because busybox:test is existed")
}
deleteImages("busybox:test")
logDone("tag - busybox with an existed tag name without -f option --> must not work")
}
// tag an image with an existed tag name with -f option should work
func TestTagExistedNameWithForce(t *testing.T) {
func (s *DockerSuite) TestTagExistedNameWithForce(c *check.C) {
if err := pullImageIfNotExist("busybox:latest"); err != nil {
t.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
c.Fatal("couldn't find the busybox:latest image locally and failed to pull it")
}
tagCmd := exec.Command(dockerBinary, "tag", "busybox:latest", "busybox:test")
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
tagCmd = exec.Command(dockerBinary, "tag", "-f", "busybox:latest", "busybox:test")
if out, _, err := runCommandWithOutput(tagCmd); err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
deleteImages("busybox:test")
logDone("tag - busybox with an existed tag name with -f option work")
}
// ensure tagging using official names works
// ensure all tags result in the same name
func TestTagOfficialNames(t *testing.T) {
func (s *DockerSuite) TestTagOfficialNames(c *check.C) {
names := []string{
"docker.io/busybox",
"index.docker.io/busybox",
@ -148,7 +141,7 @@ func TestTagOfficialNames(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "-f", "busybox:latest", name+":latest")
out, exitCode, err := runCommandWithOutput(tagCmd)
if err != nil || exitCode != 0 {
t.Errorf("tag busybox %v should have worked: %s, %s", name, err, out)
c.Errorf("tag busybox %v should have worked: %s, %s", name, err, out)
continue
}
@ -156,9 +149,9 @@ func TestTagOfficialNames(t *testing.T) {
imagesCmd := exec.Command(dockerBinary, "images")
out, _, err = runCommandWithOutput(imagesCmd)
if err != nil {
t.Errorf("listing images failed with errors: %v, %s", err, out)
c.Errorf("listing images failed with errors: %v, %s", err, out)
} else if strings.Contains(out, name) {
t.Errorf("images should not have listed '%s'", name)
c.Errorf("images should not have listed '%s'", name)
deleteImages(name + ":latest")
}
}
@ -167,10 +160,9 @@ func TestTagOfficialNames(t *testing.T) {
tagCmd := exec.Command(dockerBinary, "tag", "-f", name+":latest", "fooo/bar:latest")
_, exitCode, err := runCommandWithOutput(tagCmd)
if err != nil || exitCode != 0 {
t.Errorf("tag %v fooo/bar should have worked: %s", name, err)
c.Errorf("tag %v fooo/bar should have worked: %s", name, err)
continue
}
deleteImages("fooo/bar:latest")
}
logDone("tag - tag official names")
}

View file

@ -3,14 +3,15 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
func TestTopMultipleArgs(t *testing.T) {
func (s *DockerSuite) TestTopMultipleArgs(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-i", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to start the container: %s, %v", out, err)
c.Fatalf("failed to start the container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -19,21 +20,20 @@ func TestTopMultipleArgs(t *testing.T) {
topCmd := exec.Command(dockerBinary, "top", cleanedContainerID, "-o", "pid")
out, _, err = runCommandWithOutput(topCmd)
if err != nil {
t.Fatalf("failed to run top: %s, %v", out, err)
c.Fatalf("failed to run top: %s, %v", out, err)
}
if !strings.Contains(out, "PID") {
t.Fatalf("did not see PID after top -o pid: %s", out)
c.Fatalf("did not see PID after top -o pid: %s", out)
}
logDone("top - multiple arguments")
}
func TestTopNonPrivileged(t *testing.T) {
func (s *DockerSuite) TestTopNonPrivileged(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-i", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to start the container: %s, %v", out, err)
c.Fatalf("failed to start the container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -41,38 +41,37 @@ func TestTopNonPrivileged(t *testing.T) {
topCmd := exec.Command(dockerBinary, "top", cleanedContainerID)
out1, _, err := runCommandWithOutput(topCmd)
if err != nil {
t.Fatalf("failed to run top: %s, %v", out1, err)
c.Fatalf("failed to run top: %s, %v", out1, err)
}
topCmd = exec.Command(dockerBinary, "top", cleanedContainerID)
out2, _, err := runCommandWithOutput(topCmd)
if err != nil {
t.Fatalf("failed to run top: %s, %v", out2, err)
c.Fatalf("failed to run top: %s, %v", out2, err)
}
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
t.Fatalf("failed to kill container: %s, %v", out, err)
c.Fatalf("failed to kill container: %s, %v", out, err)
}
deleteContainer(cleanedContainerID)
if !strings.Contains(out1, "top") && !strings.Contains(out2, "top") {
t.Fatal("top should've listed `top` in the process list, but failed twice")
c.Fatal("top should've listed `top` in the process list, but failed twice")
} else if !strings.Contains(out1, "top") {
t.Fatal("top should've listed `top` in the process list, but failed the first time")
c.Fatal("top should've listed `top` in the process list, but failed the first time")
} else if !strings.Contains(out2, "top") {
t.Fatal("top should've listed `top` in the process list, but failed the second itime")
c.Fatal("top should've listed `top` in the process list, but failed the second itime")
}
logDone("top - top process should be listed in non privileged mode")
}
func TestTopPrivileged(t *testing.T) {
func (s *DockerSuite) TestTopPrivileged(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "--privileged", "-i", "-d", "busybox", "top")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatalf("failed to start the container: %s, %v", out, err)
c.Fatalf("failed to start the container: %s, %v", out, err)
}
cleanedContainerID := strings.TrimSpace(out)
@ -80,29 +79,28 @@ func TestTopPrivileged(t *testing.T) {
topCmd := exec.Command(dockerBinary, "top", cleanedContainerID)
out1, _, err := runCommandWithOutput(topCmd)
if err != nil {
t.Fatalf("failed to run top: %s, %v", out1, err)
c.Fatalf("failed to run top: %s, %v", out1, err)
}
topCmd = exec.Command(dockerBinary, "top", cleanedContainerID)
out2, _, err := runCommandWithOutput(topCmd)
if err != nil {
t.Fatalf("failed to run top: %s, %v", out2, err)
c.Fatalf("failed to run top: %s, %v", out2, err)
}
killCmd := exec.Command(dockerBinary, "kill", cleanedContainerID)
if out, _, err = runCommandWithOutput(killCmd); err != nil {
t.Fatalf("failed to kill container: %s, %v", out, err)
c.Fatalf("failed to kill container: %s, %v", out, err)
}
deleteContainer(cleanedContainerID)
if !strings.Contains(out1, "top") && !strings.Contains(out2, "top") {
t.Fatal("top should've listed `top` in the process list, but failed twice")
c.Fatal("top should've listed `top` in the process list, but failed twice")
} else if !strings.Contains(out1, "top") {
t.Fatal("top should've listed `top` in the process list, but failed the first time")
c.Fatal("top should've listed `top` in the process list, but failed the first time")
} else if !strings.Contains(out2, "top") {
t.Fatal("top should've listed `top` in the process list, but failed the second itime")
c.Fatal("top should've listed `top` in the process list, but failed the second itime")
}
logDone("top - top process should be listed in privileged mode")
}

View file

@ -3,15 +3,16 @@ package main
import (
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
// ensure docker version works
func TestVersionEnsureSucceeds(t *testing.T) {
func (s *DockerSuite) TestVersionEnsureSucceeds(c *check.C) {
versionCmd := exec.Command(dockerBinary, "version")
out, _, err := runCommandWithOutput(versionCmd)
if err != nil {
t.Fatalf("failed to execute docker version: %s, %v", out, err)
c.Fatalf("failed to execute docker version: %s, %v", out, err)
}
stringsToCheck := []string{
@ -29,9 +30,8 @@ func TestVersionEnsureSucceeds(t *testing.T) {
for _, linePrefix := range stringsToCheck {
if !strings.Contains(out, linePrefix) {
t.Errorf("couldn't find string %v in output", linePrefix)
c.Errorf("couldn't find string %v in output", linePrefix)
}
}
logDone("version - verify that it works and that the output is properly formatted")
}

View file

@ -3,18 +3,18 @@ package main
import (
"os/exec"
"strings"
"testing"
"time"
"github.com/go-check/check"
)
// non-blocking wait with 0 exit code
func TestWaitNonBlockedExitZero(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestWaitNonBlockedExitZero(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "true")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerID := strings.TrimSpace(out)
@ -23,13 +23,13 @@ func TestWaitNonBlockedExitZero(t *testing.T) {
runCmd = exec.Command(dockerBinary, "inspect", "--format='{{.State.Running}}'", containerID)
status, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(status, err)
c.Fatal(status, err)
}
status = strings.TrimSpace(status)
time.Sleep(time.Second)
if i >= 60 {
t.Fatal("Container should have stopped by now")
c.Fatal("Container should have stopped by now")
}
}
@ -37,20 +37,18 @@ func TestWaitNonBlockedExitZero(t *testing.T) {
out, _, err = runCommandWithOutput(runCmd)
if err != nil || strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out, err)
c.Fatal("failed to set up container", out, err)
}
logDone("wait - non-blocking wait with 0 exit code")
}
// blocking wait with 0 exit code
func TestWaitBlockedExitZero(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestWaitBlockedExitZero(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "sleep 10")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerID := strings.TrimSpace(out)
@ -58,20 +56,18 @@ func TestWaitBlockedExitZero(t *testing.T) {
out, _, err = runCommandWithOutput(runCmd)
if err != nil || strings.TrimSpace(out) != "0" {
t.Fatal("failed to set up container", out, err)
c.Fatal("failed to set up container", out, err)
}
logDone("wait - blocking wait with 0 exit code")
}
// non-blocking wait with random exit code
func TestWaitNonBlockedExitRandom(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestWaitNonBlockedExitRandom(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "exit 99")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerID := strings.TrimSpace(out)
@ -80,13 +76,13 @@ func TestWaitNonBlockedExitRandom(t *testing.T) {
runCmd = exec.Command(dockerBinary, "inspect", "--format='{{.State.Running}}'", containerID)
status, _, err = runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(status, err)
c.Fatal(status, err)
}
status = strings.TrimSpace(status)
time.Sleep(time.Second)
if i >= 60 {
t.Fatal("Container should have stopped by now")
c.Fatal("Container should have stopped by now")
}
}
@ -94,20 +90,18 @@ func TestWaitNonBlockedExitRandom(t *testing.T) {
out, _, err = runCommandWithOutput(runCmd)
if err != nil || strings.TrimSpace(out) != "99" {
t.Fatal("failed to set up container", out, err)
c.Fatal("failed to set up container", out, err)
}
logDone("wait - non-blocking wait with random exit code")
}
// blocking wait with random exit code
func TestWaitBlockedExitRandom(t *testing.T) {
defer deleteAllContainers()
func (s *DockerSuite) TestWaitBlockedExitRandom(c *check.C) {
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sh", "-c", "sleep 10; exit 99")
out, _, err := runCommandWithOutput(runCmd)
if err != nil {
t.Fatal(out, err)
c.Fatal(out, err)
}
containerID := strings.TrimSpace(out)
@ -115,8 +109,7 @@ func TestWaitBlockedExitRandom(t *testing.T) {
out, _, err = runCommandWithOutput(runCmd)
if err != nil || strings.TrimSpace(out) != "99" {
t.Fatal("failed to set up container", out, err)
c.Fatal("failed to set up container", out, err)
}
logDone("wait - blocking wait with random exit code")
}

View file

@ -18,17 +18,17 @@ import (
"path/filepath"
"strconv"
"strings"
"testing"
"time"
"github.com/docker/docker/api"
"github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/stringutils"
"github.com/go-check/check"
)
// Daemon represents a Docker daemon for the testing framework.
type Daemon struct {
t *testing.T
c *check.C
logFile *os.File
folder string
stdin io.WriteCloser
@ -42,24 +42,24 @@ type Daemon struct {
// NewDaemon returns a Daemon instance to be used for testing.
// This will create a directory such as daemon123456789 in the folder specified by $DEST.
// The daemon will not automatically start.
func NewDaemon(t *testing.T) *Daemon {
func NewDaemon(c *check.C) *Daemon {
dest := os.Getenv("DEST")
if dest == "" {
t.Fatal("Please set the DEST environment variable")
c.Fatal("Please set the DEST environment variable")
}
dir := filepath.Join(dest, fmt.Sprintf("daemon%d", time.Now().UnixNano()%100000000))
daemonFolder, err := filepath.Abs(dir)
if err != nil {
t.Fatalf("Could not make %q an absolute path: %v", dir, err)
c.Fatalf("Could not make %q an absolute path: %v", dir, err)
}
if err := os.MkdirAll(filepath.Join(daemonFolder, "graph"), 0600); err != nil {
t.Fatalf("Could not create %s/graph directory", daemonFolder)
c.Fatalf("Could not create %s/graph directory", daemonFolder)
}
return &Daemon{
t: t,
c: c,
folder: daemonFolder,
storageDriver: os.Getenv("DOCKER_GRAPHDRIVER"),
execDriver: os.Getenv("DOCKER_EXECDRIVER"),
@ -71,7 +71,7 @@ func NewDaemon(t *testing.T) *Daemon {
func (d *Daemon) Start(arg ...string) error {
dockerBinary, err := exec.LookPath(dockerBinary)
if err != nil {
d.t.Fatalf("could not find docker binary in $PATH: %v", err)
d.c.Fatalf("could not find docker binary in $PATH: %v", err)
}
args := []string{
@ -105,7 +105,7 @@ func (d *Daemon) Start(arg ...string) error {
d.logFile, err = os.OpenFile(filepath.Join(d.folder, "docker.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0600)
if err != nil {
d.t.Fatalf("Could not create %s/docker.log: %v", d.folder, err)
d.c.Fatalf("Could not create %s/docker.log: %v", d.folder, err)
}
d.cmd.Stdout = d.logFile
@ -119,7 +119,7 @@ func (d *Daemon) Start(arg ...string) error {
go func() {
wait <- d.cmd.Wait()
d.t.Log("exiting daemon")
d.c.Log("exiting daemon")
close(wait)
}()
@ -129,7 +129,7 @@ func (d *Daemon) Start(arg ...string) error {
// make sure daemon is ready to receive requests
startTime := time.Now().Unix()
for {
d.t.Log("waiting for daemon to start")
d.c.Log("waiting for daemon to start")
if time.Now().Unix()-startTime > 5 {
// After 5 seconds, give up
return errors.New("Daemon exited and never started")
@ -148,7 +148,7 @@ func (d *Daemon) Start(arg ...string) error {
req, err := http.NewRequest("GET", "/_ping", nil)
if err != nil {
d.t.Fatalf("could not create new request: %v", err)
d.c.Fatalf("could not create new request: %v", err)
}
resp, err := client.Do(req)
@ -156,10 +156,10 @@ func (d *Daemon) Start(arg ...string) error {
continue
}
if resp.StatusCode != http.StatusOK {
d.t.Logf("received status != 200 OK: %s", resp.Status)
d.c.Logf("received status != 200 OK: %s", resp.Status)
}
d.t.Log("daemon started")
d.c.Log("daemon started")
return nil
}
}
@ -186,7 +186,7 @@ func (d *Daemon) StartWithBusybox(arg ...string) error {
return fmt.Errorf("could not load busybox image: %v", err)
}
if err := os.Remove(bb); err != nil {
d.t.Logf("Could not remove %s: %v", bb, err)
d.c.Logf("Could not remove %s: %v", bb, err)
}
return nil
}
@ -218,7 +218,7 @@ out1:
return err
case <-time.After(15 * time.Second):
// time for stopping jobs and run onShutdown hooks
d.t.Log("timeout")
d.c.Log("timeout")
break out1
}
}
@ -231,10 +231,10 @@ out2:
case <-tick:
i++
if i > 4 {
d.t.Logf("tried to interrupt daemon for %d times, now try to kill it", i)
d.c.Logf("tried to interrupt daemon for %d times, now try to kill it", i)
break out2
}
d.t.Logf("Attempt #%d: daemon is still running with pid %d", i, d.cmd.Process.Pid)
d.c.Logf("Attempt #%d: daemon is still running with pid %d", i, d.cmd.Process.Pid)
if err := d.cmd.Process.Signal(os.Interrupt); err != nil {
return fmt.Errorf("could not send signal: %v", err)
}
@ -242,7 +242,7 @@ out2:
}
if err := d.cmd.Process.Kill(); err != nil {
d.t.Logf("Could not kill daemon: %v", err)
d.c.Logf("Could not kill daemon: %v", err)
return err
}
@ -478,10 +478,10 @@ func pullImageIfNotExist(image string) (err error) {
return
}
func dockerCmd(t *testing.T, args ...string) (string, int) {
func dockerCmd(c *check.C, args ...string) (string, int) {
out, status, err := runCommandWithOutput(exec.Command(dockerBinary, args...))
if err != nil {
t.Fatalf("%q failed with errors: %s, %v", strings.Join(args, " "), out, err)
c.Fatalf("%q failed with errors: %s, %v", strings.Join(args, " "), out, err)
}
return out, status
}
@ -496,7 +496,7 @@ func dockerCmdWithTimeout(timeout time.Duration, args ...string) (string, int, e
}
// execute a docker command in a directory
func dockerCmdInDir(t *testing.T, path string, args ...string) (string, int, error) {
func dockerCmdInDir(c *check.C, path string, args ...string) (string, int, error) {
dockerCommand := exec.Command(dockerBinary, args...)
dockerCommand.Dir = path
out, status, err := runCommandWithOutput(dockerCommand)
@ -517,11 +517,11 @@ func dockerCmdInDirWithTimeout(timeout time.Duration, path string, args ...strin
return out, status, err
}
func findContainerIP(t *testing.T, id string) string {
func findContainerIP(c *check.C, id string) string {
cmd := exec.Command(dockerBinary, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
out, _, err := runCommandWithOutput(cmd)
if err != nil {
t.Fatal(err, out)
c.Fatal(err, out)
}
return strings.Trim(out, " \r\n'")
@ -779,12 +779,12 @@ func getIDByName(name string) (string, error) {
// getContainerState returns the exit code of the container
// and true if it's running
// the exit code should be ignored if it's running
func getContainerState(t *testing.T, id string) (int, bool, error) {
func getContainerState(c *check.C, id string) (int, bool, error) {
var (
exitStatus int
running bool
)
out, exitCode := dockerCmd(t, "inspect", "--format={{.State.Running}} {{.State.ExitCode}}", id)
out, exitCode := dockerCmd(c, "inspect", "--format={{.State.Running}} {{.State.ExitCode}}", id)
if exitCode != 0 {
return 0, false, fmt.Errorf("%q doesn't exist: %s", id, out)
}
@ -985,28 +985,28 @@ func fakeGIT(name string, files map[string]string, enforceLocalServer bool) (*Fa
// 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) {
// Call c.Fatal() at the first error.
func writeFile(dst, content string, c *check.C) {
// Create subdirectories if necessary
if err := os.MkdirAll(path.Dir(dst), 0700); err != nil && !os.IsExist(err) {
t.Fatal(err)
c.Fatal(err)
}
f, err := os.OpenFile(dst, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0700)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// Write content (truncate if it exists)
if _, err := io.Copy(f, strings.NewReader(content)); err != nil {
t.Fatal(err)
c.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) {
// Call c.Fatal() at the first error (including if the file doesn't exist)
func readFile(src string, c *check.C) (content string) {
data, err := ioutil.ReadFile(src)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
return string(data)
@ -1051,14 +1051,14 @@ func readContainerFileWithExec(containerId, filename string) ([]byte, error) {
}
// daemonTime provides the current time on the daemon host
func daemonTime(t *testing.T) time.Time {
func daemonTime(c *check.C) time.Time {
if isLocalDaemon {
return time.Now()
}
_, body, err := sockRequest("GET", "/info", nil)
if err != nil {
t.Fatalf("daemonTime: failed to get /info: %v", err)
c.Fatalf("daemonTime: failed to get /info: %v", err)
}
type infoJSON struct {
@ -1066,21 +1066,21 @@ func daemonTime(t *testing.T) time.Time {
}
var info infoJSON
if err = json.Unmarshal(body, &info); err != nil {
t.Fatalf("unable to unmarshal /info response: %v", err)
c.Fatalf("unable to unmarshal /info response: %v", err)
}
dt, err := time.Parse(time.RFC3339Nano, info.SystemTime)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
return dt
}
func setupRegistry(t *testing.T) func() {
testRequires(t, RegistryHosting)
reg, err := newTestRegistryV2(t)
func setupRegistry(c *check.C) func() {
testRequires(c, RegistryHosting)
reg, err := newTestRegistryV2(c)
if err != nil {
t.Fatal(err)
c.Fatal(err)
}
// Wait for registry to be ready to serve requests.
@ -1092,7 +1092,7 @@ func setupRegistry(t *testing.T) func() {
}
if err != nil {
t.Fatal("Timeout waiting for test registry to become available")
c.Fatal("Timeout waiting for test registry to become available")
}
return func() { reg.Close() }

View file

@ -7,7 +7,8 @@ import (
"os"
"os/exec"
"path/filepath"
"testing"
"github.com/go-check/check"
)
const v2binary = "registry-v2"
@ -17,7 +18,7 @@ type testRegistryV2 struct {
dir string
}
func newTestRegistryV2(t *testing.T) (*testRegistryV2, error) {
func newTestRegistryV2(c *check.C) (*testRegistryV2, error) {
template := `version: 0.1
loglevel: debug
storage:
@ -43,7 +44,7 @@ http:
if err := cmd.Start(); err != nil {
os.RemoveAll(tmp)
if os.IsNotExist(err) {
t.Skip()
c.Skip(err.Error())
}
return nil, err
}

View file

@ -7,7 +7,8 @@ import (
"net/http"
"os/exec"
"strings"
"testing"
"github.com/go-check/check"
)
type TestCondition func() bool
@ -92,10 +93,10 @@ var (
// testRequires checks if the environment satisfies the requirements
// for the test to run or skips the tests.
func testRequires(t *testing.T, requirements ...TestRequirement) {
func testRequires(c *check.C, requirements ...TestRequirement) {
for _, r := range requirements {
if !r.Condition() {
t.Skip(r.SkipMessage)
c.Skip(r.SkipMessage)
}
}
}

View file

@ -168,10 +168,6 @@ func runCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, exitCode in
return runCommandWithOutput(cmds[len(cmds)-1])
}
func logDone(message string) {
fmt.Printf("[PASSED]: %.69s\n", message)
}
func unmarshalJSON(data []byte, result interface{}) error {
err := json.Unmarshal(data, result)
if err != nil {

View file

@ -0,0 +1,4 @@
_*
*.swp
*.[568]
[568].out

View file

@ -0,0 +1,25 @@
Gocheck - A rich testing framework for Go
Copyright (c) 2010-2013 Gustavo Niemeyer <gustavo@niemeyer.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,20 @@
Instructions
============
Install the package with:
go get gopkg.in/check.v1
Import it with:
import "gopkg.in/check.v1"
and use _check_ as the package name inside the code.
For more details, visit the project page:
* http://labix.org/gocheck
and the API documentation:
* https://gopkg.in/check.v1

View file

@ -0,0 +1,2 @@
- Assert(slice, Contains, item)
- Parallel test support

View file

@ -0,0 +1,163 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package check
import (
"fmt"
"runtime"
"time"
)
var memStats runtime.MemStats
// testingB is a type passed to Benchmark functions to manage benchmark
// timing and to specify the number of iterations to run.
type timer struct {
start time.Time // Time test or benchmark started
duration time.Duration
N int
bytes int64
timerOn bool
benchTime time.Duration
// The initial states of memStats.Mallocs and memStats.TotalAlloc.
startAllocs uint64
startBytes uint64
// The net total of this test after being run.
netAllocs uint64
netBytes uint64
}
// StartTimer starts timing a test. This function is called automatically
// before a benchmark starts, but it can also used to resume timing after
// a call to StopTimer.
func (c *C) StartTimer() {
if !c.timerOn {
c.start = time.Now()
c.timerOn = true
runtime.ReadMemStats(&memStats)
c.startAllocs = memStats.Mallocs
c.startBytes = memStats.TotalAlloc
}
}
// StopTimer stops timing a test. This can be used to pause the timer
// while performing complex initialization that you don't
// want to measure.
func (c *C) StopTimer() {
if c.timerOn {
c.duration += time.Now().Sub(c.start)
c.timerOn = false
runtime.ReadMemStats(&memStats)
c.netAllocs += memStats.Mallocs - c.startAllocs
c.netBytes += memStats.TotalAlloc - c.startBytes
}
}
// ResetTimer sets the elapsed benchmark time to zero.
// It does not affect whether the timer is running.
func (c *C) ResetTimer() {
if c.timerOn {
c.start = time.Now()
runtime.ReadMemStats(&memStats)
c.startAllocs = memStats.Mallocs
c.startBytes = memStats.TotalAlloc
}
c.duration = 0
c.netAllocs = 0
c.netBytes = 0
}
// SetBytes informs the number of bytes that the benchmark processes
// on each iteration. If this is called in a benchmark it will also
// report MB/s.
func (c *C) SetBytes(n int64) {
c.bytes = n
}
func (c *C) nsPerOp() int64 {
if c.N <= 0 {
return 0
}
return c.duration.Nanoseconds() / int64(c.N)
}
func (c *C) mbPerSec() float64 {
if c.bytes <= 0 || c.duration <= 0 || c.N <= 0 {
return 0
}
return (float64(c.bytes) * float64(c.N) / 1e6) / c.duration.Seconds()
}
func (c *C) timerString() string {
if c.N <= 0 {
return fmt.Sprintf("%3.3fs", float64(c.duration.Nanoseconds())/1e9)
}
mbs := c.mbPerSec()
mb := ""
if mbs != 0 {
mb = fmt.Sprintf("\t%7.2f MB/s", mbs)
}
nsop := c.nsPerOp()
ns := fmt.Sprintf("%10d ns/op", nsop)
if c.N > 0 && nsop < 100 {
// The format specifiers here make sure that
// the ones digits line up for all three possible formats.
if nsop < 10 {
ns = fmt.Sprintf("%13.2f ns/op", float64(c.duration.Nanoseconds())/float64(c.N))
} else {
ns = fmt.Sprintf("%12.1f ns/op", float64(c.duration.Nanoseconds())/float64(c.N))
}
}
memStats := ""
if c.benchMem {
allocedBytes := fmt.Sprintf("%8d B/op", int64(c.netBytes)/int64(c.N))
allocs := fmt.Sprintf("%8d allocs/op", int64(c.netAllocs)/int64(c.N))
memStats = fmt.Sprintf("\t%s\t%s", allocedBytes, allocs)
}
return fmt.Sprintf("%8d\t%s%s%s", c.N, ns, mb, memStats)
}
func min(x, y int) int {
if x > y {
return y
}
return x
}
func max(x, y int) int {
if x < y {
return y
}
return x
}
// roundDown10 rounds a number down to the nearest power of 10.
func roundDown10(n int) int {
var tens = 0
// tens = floor(log_10(n))
for n > 10 {
n = n / 10
tens++
}
// result = 10^tens
result := 1
for i := 0; i < tens; i++ {
result *= 10
}
return result
}
// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX].
func roundUp(n int) int {
base := roundDown10(n)
if n < (2 * base) {
return 2 * base
}
if n < (5 * base) {
return 5 * base
}
return 10 * base
}

View file

@ -0,0 +1,91 @@
// These tests verify the test running logic.
package check_test
import (
"time"
. "gopkg.in/check.v1"
)
var benchmarkS = Suite(&BenchmarkS{})
type BenchmarkS struct{}
func (s *BenchmarkS) TestCountSuite(c *C) {
suitesRun += 1
}
func (s *BenchmarkS) TestBasicTestTiming(c *C) {
helper := FixtureHelper{sleepOn: "Test1", sleep: 1000000 * time.Nanosecond}
output := String{}
runConf := RunConf{Output: &output, Verbose: true}
Run(&helper, &runConf)
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test1\t0\\.001s\n" +
"PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t0\\.000s\n"
c.Assert(output.value, Matches, expected)
}
func (s *BenchmarkS) TestStreamTestTiming(c *C) {
helper := FixtureHelper{sleepOn: "SetUpSuite", sleep: 1000000 * time.Nanosecond}
output := String{}
runConf := RunConf{Output: &output, Stream: true}
Run(&helper, &runConf)
expected := "(?s).*\nPASS: check_test\\.go:[0-9]+: FixtureHelper\\.SetUpSuite\t *0\\.001s\n.*"
c.Assert(output.value, Matches, expected)
}
func (s *BenchmarkS) TestBenchmark(c *C) {
helper := FixtureHelper{sleep: 100000}
output := String{}
runConf := RunConf{
Output: &output,
Benchmark: true,
BenchmarkTime: 10000000,
Filter: "Benchmark1",
}
Run(&helper, &runConf)
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "Benchmark1")
c.Check(helper.calls[3], Equals, "TearDownTest")
c.Check(helper.calls[4], Equals, "SetUpTest")
c.Check(helper.calls[5], Equals, "Benchmark1")
c.Check(helper.calls[6], Equals, "TearDownTest")
// ... and more.
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark1\t *100\t *[12][0-9]{5} ns/op\n"
c.Assert(output.value, Matches, expected)
}
func (s *BenchmarkS) TestBenchmarkBytes(c *C) {
helper := FixtureHelper{sleep: 100000}
output := String{}
runConf := RunConf{
Output: &output,
Benchmark: true,
BenchmarkTime: 10000000,
Filter: "Benchmark2",
}
Run(&helper, &runConf)
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark2\t *100\t *[12][0-9]{5} ns/op\t *[4-9]\\.[0-9]{2} MB/s\n"
c.Assert(output.value, Matches, expected)
}
func (s *BenchmarkS) TestBenchmarkMem(c *C) {
helper := FixtureHelper{sleep: 100000}
output := String{}
runConf := RunConf{
Output: &output,
Benchmark: true,
BenchmarkMem: true,
BenchmarkTime: 10000000,
Filter: "Benchmark3",
}
Run(&helper, &runConf)
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark3\t *100\t *[12][0-9]{5} ns/op\t *[0-9]+ B/op\t *[1-9] allocs/op\n"
c.Assert(output.value, Matches, expected)
}

View file

@ -0,0 +1,82 @@
// These initial tests are for bootstrapping. They verify that we can
// basically use the testing infrastructure itself to check if the test
// system is working.
//
// These tests use will break down the test runner badly in case of
// errors because if they simply fail, we can't be sure the developer
// will ever see anything (because failing means the failing system
// somehow isn't working! :-)
//
// Do not assume *any* internal functionality works as expected besides
// what's actually tested here.
package check_test
import (
"fmt"
"gopkg.in/check.v1"
"strings"
)
type BootstrapS struct{}
var boostrapS = check.Suite(&BootstrapS{})
func (s *BootstrapS) TestCountSuite(c *check.C) {
suitesRun += 1
}
func (s *BootstrapS) TestFailedAndFail(c *check.C) {
if c.Failed() {
critical("c.Failed() must be false first!")
}
c.Fail()
if !c.Failed() {
critical("c.Fail() didn't put the test in a failed state!")
}
c.Succeed()
}
func (s *BootstrapS) TestFailedAndSucceed(c *check.C) {
c.Fail()
c.Succeed()
if c.Failed() {
critical("c.Succeed() didn't put the test back in a non-failed state")
}
}
func (s *BootstrapS) TestLogAndGetTestLog(c *check.C) {
c.Log("Hello there!")
log := c.GetTestLog()
if log != "Hello there!\n" {
critical(fmt.Sprintf("Log() or GetTestLog() is not working! Got: %#v", log))
}
}
func (s *BootstrapS) TestLogfAndGetTestLog(c *check.C) {
c.Logf("Hello %v", "there!")
log := c.GetTestLog()
if log != "Hello there!\n" {
critical(fmt.Sprintf("Logf() or GetTestLog() is not working! Got: %#v", log))
}
}
func (s *BootstrapS) TestRunShowsErrors(c *check.C) {
output := String{}
check.Run(&FailHelper{}, &check.RunConf{Output: &output})
if strings.Index(output.value, "Expected failure!") == -1 {
critical(fmt.Sprintf("RunWithWriter() output did not contain the "+
"expected failure! Got: %#v",
output.value))
}
}
func (s *BootstrapS) TestRunDoesntShowSuccesses(c *check.C) {
output := String{}
check.Run(&SuccessHelper{}, &check.RunConf{Output: &output})
if strings.Index(output.value, "Expected success!") != -1 {
critical(fmt.Sprintf("RunWithWriter() output contained a successful "+
"test! Got: %#v",
output.value))
}
}

View file

@ -0,0 +1,945 @@
// Package check is a rich testing extension for Go's testing package.
//
// For details about the project, see:
//
// http://labix.org/gocheck
//
package check
import (
"bytes"
"errors"
"fmt"
"io"
"math/rand"
"os"
"path"
"path/filepath"
"reflect"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"time"
)
// -----------------------------------------------------------------------
// Internal type which deals with suite method calling.
const (
fixtureKd = iota
testKd
)
type funcKind int
const (
succeededSt = iota
failedSt
skippedSt
panickedSt
fixturePanickedSt
missedSt
)
type funcStatus int
// A method value can't reach its own Method structure.
type methodType struct {
reflect.Value
Info reflect.Method
}
func newMethod(receiver reflect.Value, i int) *methodType {
return &methodType{receiver.Method(i), receiver.Type().Method(i)}
}
func (method *methodType) PC() uintptr {
return method.Info.Func.Pointer()
}
func (method *methodType) suiteName() string {
t := method.Info.Type.In(0)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
return t.Name()
}
func (method *methodType) String() string {
return method.suiteName() + "." + method.Info.Name
}
func (method *methodType) matches(re *regexp.Regexp) bool {
return (re.MatchString(method.Info.Name) ||
re.MatchString(method.suiteName()) ||
re.MatchString(method.String()))
}
type C struct {
method *methodType
kind funcKind
testName string
status funcStatus
logb *logger
logw io.Writer
done chan *C
reason string
mustFail bool
tempDir *tempDir
benchMem bool
startTime time.Time
timer
}
func (c *C) stopNow() {
runtime.Goexit()
}
// logger is a concurrency safe byte.Buffer
type logger struct {
sync.Mutex
writer bytes.Buffer
}
func (l *logger) Write(buf []byte) (int, error) {
l.Lock()
defer l.Unlock()
return l.writer.Write(buf)
}
func (l *logger) WriteTo(w io.Writer) (int64, error) {
l.Lock()
defer l.Unlock()
return l.writer.WriteTo(w)
}
func (l *logger) String() string {
l.Lock()
defer l.Unlock()
return l.writer.String()
}
// -----------------------------------------------------------------------
// Handling of temporary files and directories.
type tempDir struct {
sync.Mutex
path string
counter int
}
func (td *tempDir) newPath() string {
td.Lock()
defer td.Unlock()
if td.path == "" {
var err error
for i := 0; i != 100; i++ {
path := fmt.Sprintf("%s%ccheck-%d", os.TempDir(), os.PathSeparator, rand.Int())
if err = os.Mkdir(path, 0700); err == nil {
td.path = path
break
}
}
if td.path == "" {
panic("Couldn't create temporary directory: " + err.Error())
}
}
result := filepath.Join(td.path, strconv.Itoa(td.counter))
td.counter += 1
return result
}
func (td *tempDir) removeAll() {
td.Lock()
defer td.Unlock()
if td.path != "" {
err := os.RemoveAll(td.path)
if err != nil {
fmt.Fprintf(os.Stderr, "WARNING: Error cleaning up temporaries: "+err.Error())
}
}
}
// Create a new temporary directory which is automatically removed after
// the suite finishes running.
func (c *C) MkDir() string {
path := c.tempDir.newPath()
if err := os.Mkdir(path, 0700); err != nil {
panic(fmt.Sprintf("Couldn't create temporary directory %s: %s", path, err.Error()))
}
return path
}
// -----------------------------------------------------------------------
// Low-level logging functions.
func (c *C) log(args ...interface{}) {
c.writeLog([]byte(fmt.Sprint(args...) + "\n"))
}
func (c *C) logf(format string, args ...interface{}) {
c.writeLog([]byte(fmt.Sprintf(format+"\n", args...)))
}
func (c *C) logNewLine() {
c.writeLog([]byte{'\n'})
}
func (c *C) writeLog(buf []byte) {
c.logb.Write(buf)
if c.logw != nil {
c.logw.Write(buf)
}
}
func hasStringOrError(x interface{}) (ok bool) {
_, ok = x.(fmt.Stringer)
if ok {
return
}
_, ok = x.(error)
return
}
func (c *C) logValue(label string, value interface{}) {
if label == "" {
if hasStringOrError(value) {
c.logf("... %#v (%q)", value, value)
} else {
c.logf("... %#v", value)
}
} else if value == nil {
c.logf("... %s = nil", label)
} else {
if hasStringOrError(value) {
fv := fmt.Sprintf("%#v", value)
qv := fmt.Sprintf("%q", value)
if fv != qv {
c.logf("... %s %s = %s (%s)", label, reflect.TypeOf(value), fv, qv)
return
}
}
if s, ok := value.(string); ok && isMultiLine(s) {
c.logf(`... %s %s = "" +`, label, reflect.TypeOf(value))
c.logMultiLine(s)
} else {
c.logf("... %s %s = %#v", label, reflect.TypeOf(value), value)
}
}
}
func (c *C) logMultiLine(s string) {
b := make([]byte, 0, len(s)*2)
i := 0
n := len(s)
for i < n {
j := i + 1
for j < n && s[j-1] != '\n' {
j++
}
b = append(b, "... "...)
b = strconv.AppendQuote(b, s[i:j])
if j < n {
b = append(b, " +"...)
}
b = append(b, '\n')
i = j
}
c.writeLog(b)
}
func isMultiLine(s string) bool {
for i := 0; i+1 < len(s); i++ {
if s[i] == '\n' {
return true
}
}
return false
}
func (c *C) logString(issue string) {
c.log("... ", issue)
}
func (c *C) logCaller(skip int) {
// This is a bit heavier than it ought to be.
skip += 1 // Our own frame.
pc, callerFile, callerLine, ok := runtime.Caller(skip)
if !ok {
return
}
var testFile string
var testLine int
testFunc := runtime.FuncForPC(c.method.PC())
if runtime.FuncForPC(pc) != testFunc {
for {
skip += 1
if pc, file, line, ok := runtime.Caller(skip); ok {
// Note that the test line may be different on
// distinct calls for the same test. Showing
// the "internal" line is helpful when debugging.
if runtime.FuncForPC(pc) == testFunc {
testFile, testLine = file, line
break
}
} else {
break
}
}
}
if testFile != "" && (testFile != callerFile || testLine != callerLine) {
c.logCode(testFile, testLine)
}
c.logCode(callerFile, callerLine)
}
func (c *C) logCode(path string, line int) {
c.logf("%s:%d:", nicePath(path), line)
code, err := printLine(path, line)
if code == "" {
code = "..." // XXX Open the file and take the raw line.
if err != nil {
code += err.Error()
}
}
c.log(indent(code, " "))
}
var valueGo = filepath.Join("reflect", "value.go")
var asmGo = filepath.Join("runtime", "asm_")
func (c *C) logPanic(skip int, value interface{}) {
skip++ // Our own frame.
initialSkip := skip
for ; ; skip++ {
if pc, file, line, ok := runtime.Caller(skip); ok {
if skip == initialSkip {
c.logf("... Panic: %s (PC=0x%X)\n", value, pc)
}
name := niceFuncName(pc)
path := nicePath(file)
if strings.Contains(path, "/gopkg.in/check.v") {
continue
}
if name == "Value.call" && strings.HasSuffix(path, valueGo) {
continue
}
if name == "call16" && strings.Contains(path, asmGo) {
continue
}
c.logf("%s:%d\n in %s", nicePath(file), line, name)
} else {
break
}
}
}
func (c *C) logSoftPanic(issue string) {
c.log("... Panic: ", issue)
}
func (c *C) logArgPanic(method *methodType, expectedType string) {
c.logf("... Panic: %s argument should be %s",
niceFuncName(method.PC()), expectedType)
}
// -----------------------------------------------------------------------
// Some simple formatting helpers.
var initWD, initWDErr = os.Getwd()
func init() {
if initWDErr == nil {
initWD = strings.Replace(initWD, "\\", "/", -1) + "/"
}
}
func nicePath(path string) string {
if initWDErr == nil {
if strings.HasPrefix(path, initWD) {
return path[len(initWD):]
}
}
return path
}
func niceFuncPath(pc uintptr) string {
function := runtime.FuncForPC(pc)
if function != nil {
filename, line := function.FileLine(pc)
return fmt.Sprintf("%s:%d", nicePath(filename), line)
}
return "<unknown path>"
}
func niceFuncName(pc uintptr) string {
function := runtime.FuncForPC(pc)
if function != nil {
name := path.Base(function.Name())
if i := strings.Index(name, "."); i > 0 {
name = name[i+1:]
}
if strings.HasPrefix(name, "(*") {
if i := strings.Index(name, ")"); i > 0 {
name = name[2:i] + name[i+1:]
}
}
if i := strings.LastIndex(name, ".*"); i != -1 {
name = name[:i] + "." + name[i+2:]
}
if i := strings.LastIndex(name, "·"); i != -1 {
name = name[:i] + "." + name[i+2:]
}
return name
}
return "<unknown function>"
}
// -----------------------------------------------------------------------
// Result tracker to aggregate call results.
type Result struct {
Succeeded int
Failed int
Skipped int
Panicked int
FixturePanicked int
ExpectedFailures int
Missed int // Not even tried to run, related to a panic in the fixture.
RunError error // Houston, we've got a problem.
WorkDir string // If KeepWorkDir is true
}
type resultTracker struct {
result Result
_lastWasProblem bool
_waiting int
_missed int
_expectChan chan *C
_doneChan chan *C
_stopChan chan bool
}
func newResultTracker() *resultTracker {
return &resultTracker{_expectChan: make(chan *C), // Synchronous
_doneChan: make(chan *C, 32), // Asynchronous
_stopChan: make(chan bool)} // Synchronous
}
func (tracker *resultTracker) start() {
go tracker._loopRoutine()
}
func (tracker *resultTracker) waitAndStop() {
<-tracker._stopChan
}
func (tracker *resultTracker) expectCall(c *C) {
tracker._expectChan <- c
}
func (tracker *resultTracker) callDone(c *C) {
tracker._doneChan <- c
}
func (tracker *resultTracker) _loopRoutine() {
for {
var c *C
if tracker._waiting > 0 {
// Calls still running. Can't stop.
select {
// XXX Reindent this (not now to make diff clear)
case c = <-tracker._expectChan:
tracker._waiting += 1
case c = <-tracker._doneChan:
tracker._waiting -= 1
switch c.status {
case succeededSt:
if c.kind == testKd {
if c.mustFail {
tracker.result.ExpectedFailures++
} else {
tracker.result.Succeeded++
}
}
case failedSt:
tracker.result.Failed++
case panickedSt:
if c.kind == fixtureKd {
tracker.result.FixturePanicked++
} else {
tracker.result.Panicked++
}
case fixturePanickedSt:
// Track it as missed, since the panic
// was on the fixture, not on the test.
tracker.result.Missed++
case missedSt:
tracker.result.Missed++
case skippedSt:
if c.kind == testKd {
tracker.result.Skipped++
}
}
}
} else {
// No calls. Can stop, but no done calls here.
select {
case tracker._stopChan <- true:
return
case c = <-tracker._expectChan:
tracker._waiting += 1
case c = <-tracker._doneChan:
panic("Tracker got an unexpected done call.")
}
}
}
}
// -----------------------------------------------------------------------
// The underlying suite runner.
type suiteRunner struct {
suite interface{}
setUpSuite, tearDownSuite *methodType
setUpTest, tearDownTest *methodType
tests []*methodType
tracker *resultTracker
tempDir *tempDir
keepDir bool
output *outputWriter
reportedProblemLast bool
benchTime time.Duration
benchMem bool
}
type RunConf struct {
Output io.Writer
Stream bool
Verbose bool
Filter string
Benchmark bool
BenchmarkTime time.Duration // Defaults to 1 second
BenchmarkMem bool
KeepWorkDir bool
}
// Create a new suiteRunner able to run all methods in the given suite.
func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner {
var conf RunConf
if runConf != nil {
conf = *runConf
}
if conf.Output == nil {
conf.Output = os.Stdout
}
if conf.Benchmark {
conf.Verbose = true
}
suiteType := reflect.TypeOf(suite)
suiteNumMethods := suiteType.NumMethod()
suiteValue := reflect.ValueOf(suite)
runner := &suiteRunner{
suite: suite,
output: newOutputWriter(conf.Output, conf.Stream, conf.Verbose),
tracker: newResultTracker(),
benchTime: conf.BenchmarkTime,
benchMem: conf.BenchmarkMem,
tempDir: &tempDir{},
keepDir: conf.KeepWorkDir,
tests: make([]*methodType, 0, suiteNumMethods),
}
if runner.benchTime == 0 {
runner.benchTime = 1 * time.Second
}
var filterRegexp *regexp.Regexp
if conf.Filter != "" {
if regexp, err := regexp.Compile(conf.Filter); err != nil {
msg := "Bad filter expression: " + err.Error()
runner.tracker.result.RunError = errors.New(msg)
return runner
} else {
filterRegexp = regexp
}
}
for i := 0; i != suiteNumMethods; i++ {
method := newMethod(suiteValue, i)
switch method.Info.Name {
case "SetUpSuite":
runner.setUpSuite = method
case "TearDownSuite":
runner.tearDownSuite = method
case "SetUpTest":
runner.setUpTest = method
case "TearDownTest":
runner.tearDownTest = method
default:
prefix := "Test"
if conf.Benchmark {
prefix = "Benchmark"
}
if !strings.HasPrefix(method.Info.Name, prefix) {
continue
}
if filterRegexp == nil || method.matches(filterRegexp) {
runner.tests = append(runner.tests, method)
}
}
}
return runner
}
// Run all methods in the given suite.
func (runner *suiteRunner) run() *Result {
if runner.tracker.result.RunError == nil && len(runner.tests) > 0 {
runner.tracker.start()
if runner.checkFixtureArgs() {
c := runner.runFixture(runner.setUpSuite, "", nil)
if c == nil || c.status == succeededSt {
for i := 0; i != len(runner.tests); i++ {
c := runner.runTest(runner.tests[i])
if c.status == fixturePanickedSt {
runner.skipTests(missedSt, runner.tests[i+1:])
break
}
}
} else if c != nil && c.status == skippedSt {
runner.skipTests(skippedSt, runner.tests)
} else {
runner.skipTests(missedSt, runner.tests)
}
runner.runFixture(runner.tearDownSuite, "", nil)
} else {
runner.skipTests(missedSt, runner.tests)
}
runner.tracker.waitAndStop()
if runner.keepDir {
runner.tracker.result.WorkDir = runner.tempDir.path
} else {
runner.tempDir.removeAll()
}
}
return &runner.tracker.result
}
// Create a call object with the given suite method, and fork a
// goroutine with the provided dispatcher for running it.
func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C {
var logw io.Writer
if runner.output.Stream {
logw = runner.output
}
if logb == nil {
logb = new(logger)
}
c := &C{
method: method,
kind: kind,
testName: testName,
logb: logb,
logw: logw,
tempDir: runner.tempDir,
done: make(chan *C, 1),
timer: timer{benchTime: runner.benchTime},
startTime: time.Now(),
benchMem: runner.benchMem,
}
runner.tracker.expectCall(c)
go (func() {
runner.reportCallStarted(c)
defer runner.callDone(c)
dispatcher(c)
})()
return c
}
// Same as forkCall(), but wait for call to finish before returning.
func (runner *suiteRunner) runFunc(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C {
c := runner.forkCall(method, kind, testName, logb, dispatcher)
<-c.done
return c
}
// Handle a finished call. If there were any panics, update the call status
// accordingly. Then, mark the call as done and report to the tracker.
func (runner *suiteRunner) callDone(c *C) {
value := recover()
if value != nil {
switch v := value.(type) {
case *fixturePanic:
if v.status == skippedSt {
c.status = skippedSt
} else {
c.logSoftPanic("Fixture has panicked (see related PANIC)")
c.status = fixturePanickedSt
}
default:
c.logPanic(1, value)
c.status = panickedSt
}
}
if c.mustFail {
switch c.status {
case failedSt:
c.status = succeededSt
case succeededSt:
c.status = failedSt
c.logString("Error: Test succeeded, but was expected to fail")
c.logString("Reason: " + c.reason)
}
}
runner.reportCallDone(c)
c.done <- c
}
// Runs a fixture call synchronously. The fixture will still be run in a
// goroutine like all suite methods, but this method will not return
// while the fixture goroutine is not done, because the fixture must be
// run in a desired order.
func (runner *suiteRunner) runFixture(method *methodType, testName string, logb *logger) *C {
if method != nil {
c := runner.runFunc(method, fixtureKd, testName, logb, func(c *C) {
c.ResetTimer()
c.StartTimer()
defer c.StopTimer()
c.method.Call([]reflect.Value{reflect.ValueOf(c)})
})
return c
}
return nil
}
// Run the fixture method with runFixture(), but panic with a fixturePanic{}
// in case the fixture method panics. This makes it easier to track the
// fixture panic together with other call panics within forkTest().
func (runner *suiteRunner) runFixtureWithPanic(method *methodType, testName string, logb *logger, skipped *bool) *C {
if skipped != nil && *skipped {
return nil
}
c := runner.runFixture(method, testName, logb)
if c != nil && c.status != succeededSt {
if skipped != nil {
*skipped = c.status == skippedSt
}
panic(&fixturePanic{c.status, method})
}
return c
}
type fixturePanic struct {
status funcStatus
method *methodType
}
// Run the suite test method, together with the test-specific fixture,
// asynchronously.
func (runner *suiteRunner) forkTest(method *methodType) *C {
testName := method.String()
return runner.forkCall(method, testKd, testName, nil, func(c *C) {
var skipped bool
defer runner.runFixtureWithPanic(runner.tearDownTest, testName, nil, &skipped)
defer c.StopTimer()
benchN := 1
for {
runner.runFixtureWithPanic(runner.setUpTest, testName, c.logb, &skipped)
mt := c.method.Type()
if mt.NumIn() != 1 || mt.In(0) != reflect.TypeOf(c) {
// Rather than a plain panic, provide a more helpful message when
// the argument type is incorrect.
c.status = panickedSt
c.logArgPanic(c.method, "*check.C")
return
}
if strings.HasPrefix(c.method.Info.Name, "Test") {
c.ResetTimer()
c.StartTimer()
c.method.Call([]reflect.Value{reflect.ValueOf(c)})
return
}
if !strings.HasPrefix(c.method.Info.Name, "Benchmark") {
panic("unexpected method prefix: " + c.method.Info.Name)
}
runtime.GC()
c.N = benchN
c.ResetTimer()
c.StartTimer()
c.method.Call([]reflect.Value{reflect.ValueOf(c)})
c.StopTimer()
if c.status != succeededSt || c.duration >= c.benchTime || benchN >= 1e9 {
return
}
perOpN := int(1e9)
if c.nsPerOp() != 0 {
perOpN = int(c.benchTime.Nanoseconds() / c.nsPerOp())
}
// Logic taken from the stock testing package:
// - Run more iterations than we think we'll need for a second (1.5x).
// - Don't grow too fast in case we had timing errors previously.
// - Be sure to run at least one more than last time.
benchN = max(min(perOpN+perOpN/2, 100*benchN), benchN+1)
benchN = roundUp(benchN)
skipped = true // Don't run the deferred one if this panics.
runner.runFixtureWithPanic(runner.tearDownTest, testName, nil, nil)
skipped = false
}
})
}
// Same as forkTest(), but wait for the test to finish before returning.
func (runner *suiteRunner) runTest(method *methodType) *C {
c := runner.forkTest(method)
<-c.done
return c
}
// Helper to mark tests as skipped or missed. A bit heavy for what
// it does, but it enables homogeneous handling of tracking, including
// nice verbose output.
func (runner *suiteRunner) skipTests(status funcStatus, methods []*methodType) {
for _, method := range methods {
runner.runFunc(method, testKd, "", nil, func(c *C) {
c.status = status
})
}
}
// Verify if the fixture arguments are *check.C. In case of errors,
// log the error as a panic in the fixture method call, and return false.
func (runner *suiteRunner) checkFixtureArgs() bool {
succeeded := true
argType := reflect.TypeOf(&C{})
for _, method := range []*methodType{runner.setUpSuite, runner.tearDownSuite, runner.setUpTest, runner.tearDownTest} {
if method != nil {
mt := method.Type()
if mt.NumIn() != 1 || mt.In(0) != argType {
succeeded = false
runner.runFunc(method, fixtureKd, "", nil, func(c *C) {
c.logArgPanic(method, "*check.C")
c.status = panickedSt
})
}
}
}
return succeeded
}
func (runner *suiteRunner) reportCallStarted(c *C) {
runner.output.WriteCallStarted("START", c)
}
func (runner *suiteRunner) reportCallDone(c *C) {
runner.tracker.callDone(c)
switch c.status {
case succeededSt:
if c.mustFail {
runner.output.WriteCallSuccess("FAIL EXPECTED", c)
} else {
runner.output.WriteCallSuccess("PASS", c)
}
case skippedSt:
runner.output.WriteCallSuccess("SKIP", c)
case failedSt:
runner.output.WriteCallProblem("FAIL", c)
case panickedSt:
runner.output.WriteCallProblem("PANIC", c)
case fixturePanickedSt:
// That's a testKd call reporting that its fixture
// has panicked. The fixture call which caused the
// panic itself was tracked above. We'll report to
// aid debugging.
runner.output.WriteCallProblem("PANIC", c)
case missedSt:
runner.output.WriteCallSuccess("MISS", c)
}
}
// -----------------------------------------------------------------------
// Output writer manages atomic output writing according to settings.
type outputWriter struct {
m sync.Mutex
writer io.Writer
wroteCallProblemLast bool
Stream bool
Verbose bool
}
func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter {
return &outputWriter{writer: writer, Stream: stream, Verbose: verbose}
}
func (ow *outputWriter) Write(content []byte) (n int, err error) {
ow.m.Lock()
n, err = ow.writer.Write(content)
ow.m.Unlock()
return
}
func (ow *outputWriter) WriteCallStarted(label string, c *C) {
if ow.Stream {
header := renderCallHeader(label, c, "", "\n")
ow.m.Lock()
ow.writer.Write([]byte(header))
ow.m.Unlock()
}
}
func (ow *outputWriter) WriteCallProblem(label string, c *C) {
var prefix string
if !ow.Stream {
prefix = "\n-----------------------------------" +
"-----------------------------------\n"
}
header := renderCallHeader(label, c, prefix, "\n\n")
ow.m.Lock()
ow.wroteCallProblemLast = true
ow.writer.Write([]byte(header))
if !ow.Stream {
c.logb.WriteTo(ow.writer)
}
ow.m.Unlock()
}
func (ow *outputWriter) WriteCallSuccess(label string, c *C) {
if ow.Stream || (ow.Verbose && c.kind == testKd) {
// TODO Use a buffer here.
var suffix string
if c.reason != "" {
suffix = " (" + c.reason + ")"
}
if c.status == succeededSt {
suffix += "\t" + c.timerString()
}
suffix += "\n"
if ow.Stream {
suffix += "\n"
}
header := renderCallHeader(label, c, "", suffix)
ow.m.Lock()
// Resist temptation of using line as prefix above due to race.
if !ow.Stream && ow.wroteCallProblemLast {
header = "\n-----------------------------------" +
"-----------------------------------\n" +
header
}
ow.wroteCallProblemLast = false
ow.writer.Write([]byte(header))
ow.m.Unlock()
}
}
func renderCallHeader(label string, c *C, prefix, suffix string) string {
pc := c.method.PC()
return fmt.Sprintf("%s%s: %s: %s%s", prefix, label, niceFuncPath(pc),
niceFuncName(pc), suffix)
}

View file

@ -0,0 +1,207 @@
// This file contains just a few generic helpers which are used by the
// other test files.
package check_test
import (
"flag"
"fmt"
"os"
"regexp"
"runtime"
"testing"
"time"
"gopkg.in/check.v1"
)
// We count the number of suites run at least to get a vague hint that the
// test suite is behaving as it should. Otherwise a bug introduced at the
// very core of the system could go unperceived.
const suitesRunExpected = 8
var suitesRun int = 0
func Test(t *testing.T) {
check.TestingT(t)
if suitesRun != suitesRunExpected && flag.Lookup("check.f").Value.String() == "" {
critical(fmt.Sprintf("Expected %d suites to run rather than %d",
suitesRunExpected, suitesRun))
}
}
// -----------------------------------------------------------------------
// Helper functions.
// Break down badly. This is used in test cases which can't yet assume
// that the fundamental bits are working.
func critical(error string) {
fmt.Fprintln(os.Stderr, "CRITICAL: "+error)
os.Exit(1)
}
// Return the file line where it's called.
func getMyLine() int {
if _, _, line, ok := runtime.Caller(1); ok {
return line
}
return -1
}
// -----------------------------------------------------------------------
// Helper type implementing a basic io.Writer for testing output.
// Type implementing the io.Writer interface for analyzing output.
type String struct {
value string
}
// The only function required by the io.Writer interface. Will append
// written data to the String.value string.
func (s *String) Write(p []byte) (n int, err error) {
s.value += string(p)
return len(p), nil
}
// Trivial wrapper to test errors happening on a different file
// than the test itself.
func checkEqualWrapper(c *check.C, obtained, expected interface{}) (result bool, line int) {
return c.Check(obtained, check.Equals, expected), getMyLine()
}
// -----------------------------------------------------------------------
// Helper suite for testing basic fail behavior.
type FailHelper struct {
testLine int
}
func (s *FailHelper) TestLogAndFail(c *check.C) {
s.testLine = getMyLine() - 1
c.Log("Expected failure!")
c.Fail()
}
// -----------------------------------------------------------------------
// Helper suite for testing basic success behavior.
type SuccessHelper struct{}
func (s *SuccessHelper) TestLogAndSucceed(c *check.C) {
c.Log("Expected success!")
}
// -----------------------------------------------------------------------
// Helper suite for testing ordering and behavior of fixture.
type FixtureHelper struct {
calls []string
panicOn string
skip bool
skipOnN int
sleepOn string
sleep time.Duration
bytes int64
}
func (s *FixtureHelper) trace(name string, c *check.C) {
s.calls = append(s.calls, name)
if name == s.panicOn {
panic(name)
}
if s.sleep > 0 && s.sleepOn == name {
time.Sleep(s.sleep)
}
if s.skip && s.skipOnN == len(s.calls)-1 {
c.Skip("skipOnN == n")
}
}
func (s *FixtureHelper) SetUpSuite(c *check.C) {
s.trace("SetUpSuite", c)
}
func (s *FixtureHelper) TearDownSuite(c *check.C) {
s.trace("TearDownSuite", c)
}
func (s *FixtureHelper) SetUpTest(c *check.C) {
s.trace("SetUpTest", c)
}
func (s *FixtureHelper) TearDownTest(c *check.C) {
s.trace("TearDownTest", c)
}
func (s *FixtureHelper) Test1(c *check.C) {
s.trace("Test1", c)
}
func (s *FixtureHelper) Test2(c *check.C) {
s.trace("Test2", c)
}
func (s *FixtureHelper) Benchmark1(c *check.C) {
s.trace("Benchmark1", c)
for i := 0; i < c.N; i++ {
time.Sleep(s.sleep)
}
}
func (s *FixtureHelper) Benchmark2(c *check.C) {
s.trace("Benchmark2", c)
c.SetBytes(1024)
for i := 0; i < c.N; i++ {
time.Sleep(s.sleep)
}
}
func (s *FixtureHelper) Benchmark3(c *check.C) {
var x []int64
s.trace("Benchmark3", c)
for i := 0; i < c.N; i++ {
time.Sleep(s.sleep)
x = make([]int64, 5)
_ = x
}
}
// -----------------------------------------------------------------------
// Helper which checks the state of the test and ensures that it matches
// the given expectations. Depends on c.Errorf() working, so shouldn't
// be used to test this one function.
type expectedState struct {
name string
result interface{}
failed bool
log string
}
// Verify the state of the test. Note that since this also verifies if
// the test is supposed to be in a failed state, no other checks should
// be done in addition to what is being tested.
func checkState(c *check.C, result interface{}, expected *expectedState) {
failed := c.Failed()
c.Succeed()
log := c.GetTestLog()
matched, matchError := regexp.MatchString("^"+expected.log+"$", log)
if matchError != nil {
c.Errorf("Error in matching expression used in testing %s",
expected.name)
} else if !matched {
c.Errorf("%s logged:\n----------\n%s----------\n\nExpected:\n----------\n%s\n----------",
expected.name, log, expected.log)
}
if result != expected.result {
c.Errorf("%s returned %#v rather than %#v",
expected.name, result, expected.result)
}
if failed != expected.failed {
if failed {
c.Errorf("%s has failed when it shouldn't", expected.name)
} else {
c.Errorf("%s has not failed when it should", expected.name)
}
}
}

View file

@ -0,0 +1,458 @@
package check
import (
"fmt"
"reflect"
"regexp"
)
// -----------------------------------------------------------------------
// CommentInterface and Commentf helper, to attach extra information to checks.
type comment struct {
format string
args []interface{}
}
// Commentf returns an infomational value to use with Assert or Check calls.
// If the checker test fails, the provided arguments will be passed to
// fmt.Sprintf, and will be presented next to the logged failure.
//
// For example:
//
// c.Assert(v, Equals, 42, Commentf("Iteration #%d failed.", i))
//
// Note that if the comment is constant, a better option is to
// simply use a normal comment right above or next to the line, as
// it will also get printed with any errors:
//
// c.Assert(l, Equals, 8192) // Ensure buffer size is correct (bug #123)
//
func Commentf(format string, args ...interface{}) CommentInterface {
return &comment{format, args}
}
// CommentInterface must be implemented by types that attach extra
// information to failed checks. See the Commentf function for details.
type CommentInterface interface {
CheckCommentString() string
}
func (c *comment) CheckCommentString() string {
return fmt.Sprintf(c.format, c.args...)
}
// -----------------------------------------------------------------------
// The Checker interface.
// The Checker interface must be provided by checkers used with
// the Assert and Check verification methods.
type Checker interface {
Info() *CheckerInfo
Check(params []interface{}, names []string) (result bool, error string)
}
// See the Checker interface.
type CheckerInfo struct {
Name string
Params []string
}
func (info *CheckerInfo) Info() *CheckerInfo {
return info
}
// -----------------------------------------------------------------------
// Not checker logic inverter.
// The Not checker inverts the logic of the provided checker. The
// resulting checker will succeed where the original one failed, and
// vice-versa.
//
// For example:
//
// c.Assert(a, Not(Equals), b)
//
func Not(checker Checker) Checker {
return &notChecker{checker}
}
type notChecker struct {
sub Checker
}
func (checker *notChecker) Info() *CheckerInfo {
info := *checker.sub.Info()
info.Name = "Not(" + info.Name + ")"
return &info
}
func (checker *notChecker) Check(params []interface{}, names []string) (result bool, error string) {
result, error = checker.sub.Check(params, names)
result = !result
return
}
// -----------------------------------------------------------------------
// IsNil checker.
type isNilChecker struct {
*CheckerInfo
}
// The IsNil checker tests whether the obtained value is nil.
//
// For example:
//
// c.Assert(err, IsNil)
//
var IsNil Checker = &isNilChecker{
&CheckerInfo{Name: "IsNil", Params: []string{"value"}},
}
func (checker *isNilChecker) Check(params []interface{}, names []string) (result bool, error string) {
return isNil(params[0]), ""
}
func isNil(obtained interface{}) (result bool) {
if obtained == nil {
result = true
} else {
switch v := reflect.ValueOf(obtained); v.Kind() {
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return v.IsNil()
}
}
return
}
// -----------------------------------------------------------------------
// NotNil checker. Alias for Not(IsNil), since it's so common.
type notNilChecker struct {
*CheckerInfo
}
// The NotNil checker verifies that the obtained value is not nil.
//
// For example:
//
// c.Assert(iface, NotNil)
//
// This is an alias for Not(IsNil), made available since it's a
// fairly common check.
//
var NotNil Checker = &notNilChecker{
&CheckerInfo{Name: "NotNil", Params: []string{"value"}},
}
func (checker *notNilChecker) Check(params []interface{}, names []string) (result bool, error string) {
return !isNil(params[0]), ""
}
// -----------------------------------------------------------------------
// Equals checker.
type equalsChecker struct {
*CheckerInfo
}
// The Equals checker verifies that the obtained value is equal to
// the expected value, according to usual Go semantics for ==.
//
// For example:
//
// c.Assert(value, Equals, 42)
//
var Equals Checker = &equalsChecker{
&CheckerInfo{Name: "Equals", Params: []string{"obtained", "expected"}},
}
func (checker *equalsChecker) Check(params []interface{}, names []string) (result bool, error string) {
defer func() {
if v := recover(); v != nil {
result = false
error = fmt.Sprint(v)
}
}()
return params[0] == params[1], ""
}
// -----------------------------------------------------------------------
// DeepEquals checker.
type deepEqualsChecker struct {
*CheckerInfo
}
// The DeepEquals checker verifies that the obtained value is deep-equal to
// the expected value. The check will work correctly even when facing
// slices, interfaces, and values of different types (which always fail
// the test).
//
// For example:
//
// c.Assert(value, DeepEquals, 42)
// c.Assert(array, DeepEquals, []string{"hi", "there"})
//
var DeepEquals Checker = &deepEqualsChecker{
&CheckerInfo{Name: "DeepEquals", Params: []string{"obtained", "expected"}},
}
func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) {
return reflect.DeepEqual(params[0], params[1]), ""
}
// -----------------------------------------------------------------------
// HasLen checker.
type hasLenChecker struct {
*CheckerInfo
}
// The HasLen checker verifies that the obtained value has the
// provided length. In many cases this is superior to using Equals
// in conjuction with the len function because in case the check
// fails the value itself will be printed, instead of its length,
// providing more details for figuring the problem.
//
// For example:
//
// c.Assert(list, HasLen, 5)
//
var HasLen Checker = &hasLenChecker{
&CheckerInfo{Name: "HasLen", Params: []string{"obtained", "n"}},
}
func (checker *hasLenChecker) Check(params []interface{}, names []string) (result bool, error string) {
n, ok := params[1].(int)
if !ok {
return false, "n must be an int"
}
value := reflect.ValueOf(params[0])
switch value.Kind() {
case reflect.Map, reflect.Array, reflect.Slice, reflect.Chan, reflect.String:
default:
return false, "obtained value type has no length"
}
return value.Len() == n, ""
}
// -----------------------------------------------------------------------
// ErrorMatches checker.
type errorMatchesChecker struct {
*CheckerInfo
}
// The ErrorMatches checker verifies that the error value
// is non nil and matches the regular expression provided.
//
// For example:
//
// c.Assert(err, ErrorMatches, "perm.*denied")
//
var ErrorMatches Checker = errorMatchesChecker{
&CheckerInfo{Name: "ErrorMatches", Params: []string{"value", "regex"}},
}
func (checker errorMatchesChecker) Check(params []interface{}, names []string) (result bool, errStr string) {
if params[0] == nil {
return false, "Error value is nil"
}
err, ok := params[0].(error)
if !ok {
return false, "Value is not an error"
}
params[0] = err.Error()
names[0] = "error"
return matches(params[0], params[1])
}
// -----------------------------------------------------------------------
// Matches checker.
type matchesChecker struct {
*CheckerInfo
}
// The Matches checker verifies that the string provided as the obtained
// value (or the string resulting from obtained.String()) matches the
// regular expression provided.
//
// For example:
//
// c.Assert(err, Matches, "perm.*denied")
//
var Matches Checker = &matchesChecker{
&CheckerInfo{Name: "Matches", Params: []string{"value", "regex"}},
}
func (checker *matchesChecker) Check(params []interface{}, names []string) (result bool, error string) {
return matches(params[0], params[1])
}
func matches(value, regex interface{}) (result bool, error string) {
reStr, ok := regex.(string)
if !ok {
return false, "Regex must be a string"
}
valueStr, valueIsStr := value.(string)
if !valueIsStr {
if valueWithStr, valueHasStr := value.(fmt.Stringer); valueHasStr {
valueStr, valueIsStr = valueWithStr.String(), true
}
}
if valueIsStr {
matches, err := regexp.MatchString("^"+reStr+"$", valueStr)
if err != nil {
return false, "Can't compile regex: " + err.Error()
}
return matches, ""
}
return false, "Obtained value is not a string and has no .String()"
}
// -----------------------------------------------------------------------
// Panics checker.
type panicsChecker struct {
*CheckerInfo
}
// The Panics checker verifies that calling the provided zero-argument
// function will cause a panic which is deep-equal to the provided value.
//
// For example:
//
// c.Assert(func() { f(1, 2) }, Panics, &SomeErrorType{"BOOM"}).
//
//
var Panics Checker = &panicsChecker{
&CheckerInfo{Name: "Panics", Params: []string{"function", "expected"}},
}
func (checker *panicsChecker) Check(params []interface{}, names []string) (result bool, error string) {
f := reflect.ValueOf(params[0])
if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
return false, "Function must take zero arguments"
}
defer func() {
// If the function has not panicked, then don't do the check.
if error != "" {
return
}
params[0] = recover()
names[0] = "panic"
result = reflect.DeepEqual(params[0], params[1])
}()
f.Call(nil)
return false, "Function has not panicked"
}
type panicMatchesChecker struct {
*CheckerInfo
}
// The PanicMatches checker verifies that calling the provided zero-argument
// function will cause a panic with an error value matching
// the regular expression provided.
//
// For example:
//
// c.Assert(func() { f(1, 2) }, PanicMatches, `open.*: no such file or directory`).
//
//
var PanicMatches Checker = &panicMatchesChecker{
&CheckerInfo{Name: "PanicMatches", Params: []string{"function", "expected"}},
}
func (checker *panicMatchesChecker) Check(params []interface{}, names []string) (result bool, errmsg string) {
f := reflect.ValueOf(params[0])
if f.Kind() != reflect.Func || f.Type().NumIn() != 0 {
return false, "Function must take zero arguments"
}
defer func() {
// If the function has not panicked, then don't do the check.
if errmsg != "" {
return
}
obtained := recover()
names[0] = "panic"
if e, ok := obtained.(error); ok {
params[0] = e.Error()
} else if _, ok := obtained.(string); ok {
params[0] = obtained
} else {
errmsg = "Panic value is not a string or an error"
return
}
result, errmsg = matches(params[0], params[1])
}()
f.Call(nil)
return false, "Function has not panicked"
}
// -----------------------------------------------------------------------
// FitsTypeOf checker.
type fitsTypeChecker struct {
*CheckerInfo
}
// The FitsTypeOf checker verifies that the obtained value is
// assignable to a variable with the same type as the provided
// sample value.
//
// For example:
//
// c.Assert(value, FitsTypeOf, int64(0))
// c.Assert(value, FitsTypeOf, os.Error(nil))
//
var FitsTypeOf Checker = &fitsTypeChecker{
&CheckerInfo{Name: "FitsTypeOf", Params: []string{"obtained", "sample"}},
}
func (checker *fitsTypeChecker) Check(params []interface{}, names []string) (result bool, error string) {
obtained := reflect.ValueOf(params[0])
sample := reflect.ValueOf(params[1])
if !obtained.IsValid() {
return false, ""
}
if !sample.IsValid() {
return false, "Invalid sample value"
}
return obtained.Type().AssignableTo(sample.Type()), ""
}
// -----------------------------------------------------------------------
// Implements checker.
type implementsChecker struct {
*CheckerInfo
}
// The Implements checker verifies that the obtained value
// implements the interface specified via a pointer to an interface
// variable.
//
// For example:
//
// var e os.Error
// c.Assert(err, Implements, &e)
//
var Implements Checker = &implementsChecker{
&CheckerInfo{Name: "Implements", Params: []string{"obtained", "ifaceptr"}},
}
func (checker *implementsChecker) Check(params []interface{}, names []string) (result bool, error string) {
obtained := reflect.ValueOf(params[0])
ifaceptr := reflect.ValueOf(params[1])
if !obtained.IsValid() {
return false, ""
}
if !ifaceptr.IsValid() || ifaceptr.Kind() != reflect.Ptr || ifaceptr.Elem().Kind() != reflect.Interface {
return false, "ifaceptr should be a pointer to an interface variable"
}
return obtained.Type().Implements(ifaceptr.Elem().Type()), ""
}

View file

@ -0,0 +1,272 @@
package check_test
import (
"errors"
"gopkg.in/check.v1"
"reflect"
"runtime"
)
type CheckersS struct{}
var _ = check.Suite(&CheckersS{})
func testInfo(c *check.C, checker check.Checker, name string, paramNames []string) {
info := checker.Info()
if info.Name != name {
c.Fatalf("Got name %s, expected %s", info.Name, name)
}
if !reflect.DeepEqual(info.Params, paramNames) {
c.Fatalf("Got param names %#v, expected %#v", info.Params, paramNames)
}
}
func testCheck(c *check.C, checker check.Checker, result bool, error string, params ...interface{}) ([]interface{}, []string) {
info := checker.Info()
if len(params) != len(info.Params) {
c.Fatalf("unexpected param count in test; expected %d got %d", len(info.Params), len(params))
}
names := append([]string{}, info.Params...)
result_, error_ := checker.Check(params, names)
if result_ != result || error_ != error {
c.Fatalf("%s.Check(%#v) returned (%#v, %#v) rather than (%#v, %#v)",
info.Name, params, result_, error_, result, error)
}
return params, names
}
func (s *CheckersS) TestComment(c *check.C) {
bug := check.Commentf("a %d bc", 42)
comment := bug.CheckCommentString()
if comment != "a 42 bc" {
c.Fatalf("Commentf returned %#v", comment)
}
}
func (s *CheckersS) TestIsNil(c *check.C) {
testInfo(c, check.IsNil, "IsNil", []string{"value"})
testCheck(c, check.IsNil, true, "", nil)
testCheck(c, check.IsNil, false, "", "a")
testCheck(c, check.IsNil, true, "", (chan int)(nil))
testCheck(c, check.IsNil, false, "", make(chan int))
testCheck(c, check.IsNil, true, "", (error)(nil))
testCheck(c, check.IsNil, false, "", errors.New(""))
testCheck(c, check.IsNil, true, "", ([]int)(nil))
testCheck(c, check.IsNil, false, "", make([]int, 1))
testCheck(c, check.IsNil, false, "", int(0))
}
func (s *CheckersS) TestNotNil(c *check.C) {
testInfo(c, check.NotNil, "NotNil", []string{"value"})
testCheck(c, check.NotNil, false, "", nil)
testCheck(c, check.NotNil, true, "", "a")
testCheck(c, check.NotNil, false, "", (chan int)(nil))
testCheck(c, check.NotNil, true, "", make(chan int))
testCheck(c, check.NotNil, false, "", (error)(nil))
testCheck(c, check.NotNil, true, "", errors.New(""))
testCheck(c, check.NotNil, false, "", ([]int)(nil))
testCheck(c, check.NotNil, true, "", make([]int, 1))
}
func (s *CheckersS) TestNot(c *check.C) {
testInfo(c, check.Not(check.IsNil), "Not(IsNil)", []string{"value"})
testCheck(c, check.Not(check.IsNil), false, "", nil)
testCheck(c, check.Not(check.IsNil), true, "", "a")
}
type simpleStruct struct {
i int
}
func (s *CheckersS) TestEquals(c *check.C) {
testInfo(c, check.Equals, "Equals", []string{"obtained", "expected"})
// The simplest.
testCheck(c, check.Equals, true, "", 42, 42)
testCheck(c, check.Equals, false, "", 42, 43)
// Different native types.
testCheck(c, check.Equals, false, "", int32(42), int64(42))
// With nil.
testCheck(c, check.Equals, false, "", 42, nil)
// Slices
testCheck(c, check.Equals, false, "runtime error: comparing uncomparable type []uint8", []byte{1, 2}, []byte{1, 2})
// Struct values
testCheck(c, check.Equals, true, "", simpleStruct{1}, simpleStruct{1})
testCheck(c, check.Equals, false, "", simpleStruct{1}, simpleStruct{2})
// Struct pointers
testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{1})
testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{2})
}
func (s *CheckersS) TestDeepEquals(c *check.C) {
testInfo(c, check.DeepEquals, "DeepEquals", []string{"obtained", "expected"})
// The simplest.
testCheck(c, check.DeepEquals, true, "", 42, 42)
testCheck(c, check.DeepEquals, false, "", 42, 43)
// Different native types.
testCheck(c, check.DeepEquals, false, "", int32(42), int64(42))
// With nil.
testCheck(c, check.DeepEquals, false, "", 42, nil)
// Slices
testCheck(c, check.DeepEquals, true, "", []byte{1, 2}, []byte{1, 2})
testCheck(c, check.DeepEquals, false, "", []byte{1, 2}, []byte{1, 3})
// Struct values
testCheck(c, check.DeepEquals, true, "", simpleStruct{1}, simpleStruct{1})
testCheck(c, check.DeepEquals, false, "", simpleStruct{1}, simpleStruct{2})
// Struct pointers
testCheck(c, check.DeepEquals, true, "", &simpleStruct{1}, &simpleStruct{1})
testCheck(c, check.DeepEquals, false, "", &simpleStruct{1}, &simpleStruct{2})
}
func (s *CheckersS) TestHasLen(c *check.C) {
testInfo(c, check.HasLen, "HasLen", []string{"obtained", "n"})
testCheck(c, check.HasLen, true, "", "abcd", 4)
testCheck(c, check.HasLen, true, "", []int{1, 2}, 2)
testCheck(c, check.HasLen, false, "", []int{1, 2}, 3)
testCheck(c, check.HasLen, false, "n must be an int", []int{1, 2}, "2")
testCheck(c, check.HasLen, false, "obtained value type has no length", nil, 2)
}
func (s *CheckersS) TestErrorMatches(c *check.C) {
testInfo(c, check.ErrorMatches, "ErrorMatches", []string{"value", "regex"})
testCheck(c, check.ErrorMatches, false, "Error value is nil", nil, "some error")
testCheck(c, check.ErrorMatches, false, "Value is not an error", 1, "some error")
testCheck(c, check.ErrorMatches, true, "", errors.New("some error"), "some error")
testCheck(c, check.ErrorMatches, true, "", errors.New("some error"), "so.*or")
// Verify params mutation
params, names := testCheck(c, check.ErrorMatches, false, "", errors.New("some error"), "other error")
c.Assert(params[0], check.Equals, "some error")
c.Assert(names[0], check.Equals, "error")
}
func (s *CheckersS) TestMatches(c *check.C) {
testInfo(c, check.Matches, "Matches", []string{"value", "regex"})
// Simple matching
testCheck(c, check.Matches, true, "", "abc", "abc")
testCheck(c, check.Matches, true, "", "abc", "a.c")
// Must match fully
testCheck(c, check.Matches, false, "", "abc", "ab")
testCheck(c, check.Matches, false, "", "abc", "bc")
// String()-enabled values accepted
testCheck(c, check.Matches, true, "", reflect.ValueOf("abc"), "a.c")
testCheck(c, check.Matches, false, "", reflect.ValueOf("abc"), "a.d")
// Some error conditions.
testCheck(c, check.Matches, false, "Obtained value is not a string and has no .String()", 1, "a.c")
testCheck(c, check.Matches, false, "Can't compile regex: error parsing regexp: missing closing ]: `[c$`", "abc", "a[c")
}
func (s *CheckersS) TestPanics(c *check.C) {
testInfo(c, check.Panics, "Panics", []string{"function", "expected"})
// Some errors.
testCheck(c, check.Panics, false, "Function has not panicked", func() bool { return false }, "BOOM")
testCheck(c, check.Panics, false, "Function must take zero arguments", 1, "BOOM")
// Plain strings.
testCheck(c, check.Panics, true, "", func() { panic("BOOM") }, "BOOM")
testCheck(c, check.Panics, false, "", func() { panic("KABOOM") }, "BOOM")
testCheck(c, check.Panics, true, "", func() bool { panic("BOOM") }, "BOOM")
// Error values.
testCheck(c, check.Panics, true, "", func() { panic(errors.New("BOOM")) }, errors.New("BOOM"))
testCheck(c, check.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM"))
type deep struct{ i int }
// Deep value
testCheck(c, check.Panics, true, "", func() { panic(&deep{99}) }, &deep{99})
// Verify params/names mutation
params, names := testCheck(c, check.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM"))
c.Assert(params[0], check.ErrorMatches, "KABOOM")
c.Assert(names[0], check.Equals, "panic")
// Verify a nil panic
testCheck(c, check.Panics, true, "", func() { panic(nil) }, nil)
testCheck(c, check.Panics, false, "", func() { panic(nil) }, "NOPE")
}
func (s *CheckersS) TestPanicMatches(c *check.C) {
testInfo(c, check.PanicMatches, "PanicMatches", []string{"function", "expected"})
// Error matching.
testCheck(c, check.PanicMatches, true, "", func() { panic(errors.New("BOOM")) }, "BO.M")
testCheck(c, check.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BO.M")
// Some errors.
testCheck(c, check.PanicMatches, false, "Function has not panicked", func() bool { return false }, "BOOM")
testCheck(c, check.PanicMatches, false, "Function must take zero arguments", 1, "BOOM")
// Plain strings.
testCheck(c, check.PanicMatches, true, "", func() { panic("BOOM") }, "BO.M")
testCheck(c, check.PanicMatches, false, "", func() { panic("KABOOM") }, "BOOM")
testCheck(c, check.PanicMatches, true, "", func() bool { panic("BOOM") }, "BO.M")
// Verify params/names mutation
params, names := testCheck(c, check.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BOOM")
c.Assert(params[0], check.Equals, "KABOOM")
c.Assert(names[0], check.Equals, "panic")
// Verify a nil panic
testCheck(c, check.PanicMatches, false, "Panic value is not a string or an error", func() { panic(nil) }, "")
}
func (s *CheckersS) TestFitsTypeOf(c *check.C) {
testInfo(c, check.FitsTypeOf, "FitsTypeOf", []string{"obtained", "sample"})
// Basic types
testCheck(c, check.FitsTypeOf, true, "", 1, 0)
testCheck(c, check.FitsTypeOf, false, "", 1, int64(0))
// Aliases
testCheck(c, check.FitsTypeOf, false, "", 1, errors.New(""))
testCheck(c, check.FitsTypeOf, false, "", "error", errors.New(""))
testCheck(c, check.FitsTypeOf, true, "", errors.New("error"), errors.New(""))
// Structures
testCheck(c, check.FitsTypeOf, false, "", 1, simpleStruct{})
testCheck(c, check.FitsTypeOf, false, "", simpleStruct{42}, &simpleStruct{})
testCheck(c, check.FitsTypeOf, true, "", simpleStruct{42}, simpleStruct{})
testCheck(c, check.FitsTypeOf, true, "", &simpleStruct{42}, &simpleStruct{})
// Some bad values
testCheck(c, check.FitsTypeOf, false, "Invalid sample value", 1, interface{}(nil))
testCheck(c, check.FitsTypeOf, false, "", interface{}(nil), 0)
}
func (s *CheckersS) TestImplements(c *check.C) {
testInfo(c, check.Implements, "Implements", []string{"obtained", "ifaceptr"})
var e error
var re runtime.Error
testCheck(c, check.Implements, true, "", errors.New(""), &e)
testCheck(c, check.Implements, false, "", errors.New(""), &re)
// Some bad values
testCheck(c, check.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, errors.New(""))
testCheck(c, check.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, interface{}(nil))
testCheck(c, check.Implements, false, "", interface{}(nil), &e)
}

View file

@ -0,0 +1,9 @@
package check
func PrintLine(filename string, line int) (string, error) {
return printLine(filename, line)
}
func Indent(s, with string) string {
return indent(s, with)
}

View file

@ -0,0 +1,484 @@
// Tests for the behavior of the test fixture system.
package check_test
import (
. "gopkg.in/check.v1"
)
// -----------------------------------------------------------------------
// Fixture test suite.
type FixtureS struct{}
var fixtureS = Suite(&FixtureS{})
func (s *FixtureS) TestCountSuite(c *C) {
suitesRun += 1
}
// -----------------------------------------------------------------------
// Basic fixture ordering verification.
func (s *FixtureS) TestOrder(c *C) {
helper := FixtureHelper{}
Run(&helper, nil)
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "Test1")
c.Check(helper.calls[3], Equals, "TearDownTest")
c.Check(helper.calls[4], Equals, "SetUpTest")
c.Check(helper.calls[5], Equals, "Test2")
c.Check(helper.calls[6], Equals, "TearDownTest")
c.Check(helper.calls[7], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 8)
}
// -----------------------------------------------------------------------
// Check the behavior when panics occur within tests and fixtures.
func (s *FixtureS) TestPanicOnTest(c *C) {
helper := FixtureHelper{panicOn: "Test1"}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "Test1")
c.Check(helper.calls[3], Equals, "TearDownTest")
c.Check(helper.calls[4], Equals, "SetUpTest")
c.Check(helper.calls[5], Equals, "Test2")
c.Check(helper.calls[6], Equals, "TearDownTest")
c.Check(helper.calls[7], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 8)
expected := "^\n-+\n" +
"PANIC: check_test\\.go:[0-9]+: FixtureHelper.Test1\n\n" +
"\\.\\.\\. Panic: Test1 \\(PC=[xA-F0-9]+\\)\n\n" +
".+:[0-9]+\n" +
" in (go)?panic\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.trace\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.Test1\n" +
"(.|\n)*$"
c.Check(output.value, Matches, expected)
}
func (s *FixtureS) TestPanicOnSetUpTest(c *C) {
helper := FixtureHelper{panicOn: "SetUpTest"}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "TearDownTest")
c.Check(helper.calls[3], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 4)
expected := "^\n-+\n" +
"PANIC: check_test\\.go:[0-9]+: " +
"FixtureHelper\\.SetUpTest\n\n" +
"\\.\\.\\. Panic: SetUpTest \\(PC=[xA-F0-9]+\\)\n\n" +
".+:[0-9]+\n" +
" in (go)?panic\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.trace\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.SetUpTest\n" +
"(.|\n)*" +
"\n-+\n" +
"PANIC: check_test\\.go:[0-9]+: " +
"FixtureHelper\\.Test1\n\n" +
"\\.\\.\\. Panic: Fixture has panicked " +
"\\(see related PANIC\\)\n$"
c.Check(output.value, Matches, expected)
}
func (s *FixtureS) TestPanicOnTearDownTest(c *C) {
helper := FixtureHelper{panicOn: "TearDownTest"}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "Test1")
c.Check(helper.calls[3], Equals, "TearDownTest")
c.Check(helper.calls[4], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 5)
expected := "^\n-+\n" +
"PANIC: check_test\\.go:[0-9]+: " +
"FixtureHelper.TearDownTest\n\n" +
"\\.\\.\\. Panic: TearDownTest \\(PC=[xA-F0-9]+\\)\n\n" +
".+:[0-9]+\n" +
" in (go)?panic\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.trace\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.TearDownTest\n" +
"(.|\n)*" +
"\n-+\n" +
"PANIC: check_test\\.go:[0-9]+: " +
"FixtureHelper\\.Test1\n\n" +
"\\.\\.\\. Panic: Fixture has panicked " +
"\\(see related PANIC\\)\n$"
c.Check(output.value, Matches, expected)
}
func (s *FixtureS) TestPanicOnSetUpSuite(c *C) {
helper := FixtureHelper{panicOn: "SetUpSuite"}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 2)
expected := "^\n-+\n" +
"PANIC: check_test\\.go:[0-9]+: " +
"FixtureHelper.SetUpSuite\n\n" +
"\\.\\.\\. Panic: SetUpSuite \\(PC=[xA-F0-9]+\\)\n\n" +
".+:[0-9]+\n" +
" in (go)?panic\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.trace\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.SetUpSuite\n" +
"(.|\n)*$"
c.Check(output.value, Matches, expected)
}
func (s *FixtureS) TestPanicOnTearDownSuite(c *C) {
helper := FixtureHelper{panicOn: "TearDownSuite"}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "Test1")
c.Check(helper.calls[3], Equals, "TearDownTest")
c.Check(helper.calls[4], Equals, "SetUpTest")
c.Check(helper.calls[5], Equals, "Test2")
c.Check(helper.calls[6], Equals, "TearDownTest")
c.Check(helper.calls[7], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 8)
expected := "^\n-+\n" +
"PANIC: check_test\\.go:[0-9]+: " +
"FixtureHelper.TearDownSuite\n\n" +
"\\.\\.\\. Panic: TearDownSuite \\(PC=[xA-F0-9]+\\)\n\n" +
".+:[0-9]+\n" +
" in (go)?panic\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.trace\n" +
".*check_test.go:[0-9]+\n" +
" in FixtureHelper.TearDownSuite\n" +
"(.|\n)*$"
c.Check(output.value, Matches, expected)
}
// -----------------------------------------------------------------------
// A wrong argument on a test or fixture will produce a nice error.
func (s *FixtureS) TestPanicOnWrongTestArg(c *C) {
helper := WrongTestArgHelper{}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "TearDownTest")
c.Check(helper.calls[3], Equals, "SetUpTest")
c.Check(helper.calls[4], Equals, "Test2")
c.Check(helper.calls[5], Equals, "TearDownTest")
c.Check(helper.calls[6], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 7)
expected := "^\n-+\n" +
"PANIC: fixture_test\\.go:[0-9]+: " +
"WrongTestArgHelper\\.Test1\n\n" +
"\\.\\.\\. Panic: WrongTestArgHelper\\.Test1 argument " +
"should be \\*check\\.C\n"
c.Check(output.value, Matches, expected)
}
func (s *FixtureS) TestPanicOnWrongSetUpTestArg(c *C) {
helper := WrongSetUpTestArgHelper{}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(len(helper.calls), Equals, 0)
expected :=
"^\n-+\n" +
"PANIC: fixture_test\\.go:[0-9]+: " +
"WrongSetUpTestArgHelper\\.SetUpTest\n\n" +
"\\.\\.\\. Panic: WrongSetUpTestArgHelper\\.SetUpTest argument " +
"should be \\*check\\.C\n"
c.Check(output.value, Matches, expected)
}
func (s *FixtureS) TestPanicOnWrongSetUpSuiteArg(c *C) {
helper := WrongSetUpSuiteArgHelper{}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(len(helper.calls), Equals, 0)
expected :=
"^\n-+\n" +
"PANIC: fixture_test\\.go:[0-9]+: " +
"WrongSetUpSuiteArgHelper\\.SetUpSuite\n\n" +
"\\.\\.\\. Panic: WrongSetUpSuiteArgHelper\\.SetUpSuite argument " +
"should be \\*check\\.C\n"
c.Check(output.value, Matches, expected)
}
// -----------------------------------------------------------------------
// Nice errors also when tests or fixture have wrong arg count.
func (s *FixtureS) TestPanicOnWrongTestArgCount(c *C) {
helper := WrongTestArgCountHelper{}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "TearDownTest")
c.Check(helper.calls[3], Equals, "SetUpTest")
c.Check(helper.calls[4], Equals, "Test2")
c.Check(helper.calls[5], Equals, "TearDownTest")
c.Check(helper.calls[6], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 7)
expected := "^\n-+\n" +
"PANIC: fixture_test\\.go:[0-9]+: " +
"WrongTestArgCountHelper\\.Test1\n\n" +
"\\.\\.\\. Panic: WrongTestArgCountHelper\\.Test1 argument " +
"should be \\*check\\.C\n"
c.Check(output.value, Matches, expected)
}
func (s *FixtureS) TestPanicOnWrongSetUpTestArgCount(c *C) {
helper := WrongSetUpTestArgCountHelper{}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(len(helper.calls), Equals, 0)
expected :=
"^\n-+\n" +
"PANIC: fixture_test\\.go:[0-9]+: " +
"WrongSetUpTestArgCountHelper\\.SetUpTest\n\n" +
"\\.\\.\\. Panic: WrongSetUpTestArgCountHelper\\.SetUpTest argument " +
"should be \\*check\\.C\n"
c.Check(output.value, Matches, expected)
}
func (s *FixtureS) TestPanicOnWrongSetUpSuiteArgCount(c *C) {
helper := WrongSetUpSuiteArgCountHelper{}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(len(helper.calls), Equals, 0)
expected :=
"^\n-+\n" +
"PANIC: fixture_test\\.go:[0-9]+: " +
"WrongSetUpSuiteArgCountHelper\\.SetUpSuite\n\n" +
"\\.\\.\\. Panic: WrongSetUpSuiteArgCountHelper" +
"\\.SetUpSuite argument should be \\*check\\.C\n"
c.Check(output.value, Matches, expected)
}
// -----------------------------------------------------------------------
// Helper test suites with wrong function arguments.
type WrongTestArgHelper struct {
FixtureHelper
}
func (s *WrongTestArgHelper) Test1(t int) {
}
type WrongSetUpTestArgHelper struct {
FixtureHelper
}
func (s *WrongSetUpTestArgHelper) SetUpTest(t int) {
}
type WrongSetUpSuiteArgHelper struct {
FixtureHelper
}
func (s *WrongSetUpSuiteArgHelper) SetUpSuite(t int) {
}
type WrongTestArgCountHelper struct {
FixtureHelper
}
func (s *WrongTestArgCountHelper) Test1(c *C, i int) {
}
type WrongSetUpTestArgCountHelper struct {
FixtureHelper
}
func (s *WrongSetUpTestArgCountHelper) SetUpTest(c *C, i int) {
}
type WrongSetUpSuiteArgCountHelper struct {
FixtureHelper
}
func (s *WrongSetUpSuiteArgCountHelper) SetUpSuite(c *C, i int) {
}
// -----------------------------------------------------------------------
// Ensure fixture doesn't run without tests.
type NoTestsHelper struct {
hasRun bool
}
func (s *NoTestsHelper) SetUpSuite(c *C) {
s.hasRun = true
}
func (s *NoTestsHelper) TearDownSuite(c *C) {
s.hasRun = true
}
func (s *FixtureS) TestFixtureDoesntRunWithoutTests(c *C) {
helper := NoTestsHelper{}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Check(helper.hasRun, Equals, false)
}
// -----------------------------------------------------------------------
// Verify that checks and assertions work correctly inside the fixture.
type FixtureCheckHelper struct {
fail string
completed bool
}
func (s *FixtureCheckHelper) SetUpSuite(c *C) {
switch s.fail {
case "SetUpSuiteAssert":
c.Assert(false, Equals, true)
case "SetUpSuiteCheck":
c.Check(false, Equals, true)
}
s.completed = true
}
func (s *FixtureCheckHelper) SetUpTest(c *C) {
switch s.fail {
case "SetUpTestAssert":
c.Assert(false, Equals, true)
case "SetUpTestCheck":
c.Check(false, Equals, true)
}
s.completed = true
}
func (s *FixtureCheckHelper) Test(c *C) {
// Do nothing.
}
func (s *FixtureS) TestSetUpSuiteCheck(c *C) {
helper := FixtureCheckHelper{fail: "SetUpSuiteCheck"}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Assert(output.value, Matches,
"\n---+\n"+
"FAIL: fixture_test\\.go:[0-9]+: "+
"FixtureCheckHelper\\.SetUpSuite\n\n"+
"fixture_test\\.go:[0-9]+:\n"+
" c\\.Check\\(false, Equals, true\\)\n"+
"\\.+ obtained bool = false\n"+
"\\.+ expected bool = true\n\n")
c.Assert(helper.completed, Equals, true)
}
func (s *FixtureS) TestSetUpSuiteAssert(c *C) {
helper := FixtureCheckHelper{fail: "SetUpSuiteAssert"}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Assert(output.value, Matches,
"\n---+\n"+
"FAIL: fixture_test\\.go:[0-9]+: "+
"FixtureCheckHelper\\.SetUpSuite\n\n"+
"fixture_test\\.go:[0-9]+:\n"+
" c\\.Assert\\(false, Equals, true\\)\n"+
"\\.+ obtained bool = false\n"+
"\\.+ expected bool = true\n\n")
c.Assert(helper.completed, Equals, false)
}
// -----------------------------------------------------------------------
// Verify that logging within SetUpTest() persists within the test log itself.
type FixtureLogHelper struct {
c *C
}
func (s *FixtureLogHelper) SetUpTest(c *C) {
s.c = c
c.Log("1")
}
func (s *FixtureLogHelper) Test(c *C) {
c.Log("2")
s.c.Log("3")
c.Log("4")
c.Fail()
}
func (s *FixtureLogHelper) TearDownTest(c *C) {
s.c.Log("5")
}
func (s *FixtureS) TestFixtureLogging(c *C) {
helper := FixtureLogHelper{}
output := String{}
Run(&helper, &RunConf{Output: &output})
c.Assert(output.value, Matches,
"\n---+\n"+
"FAIL: fixture_test\\.go:[0-9]+: "+
"FixtureLogHelper\\.Test\n\n"+
"1\n2\n3\n4\n5\n")
}
// -----------------------------------------------------------------------
// Skip() within fixture methods.
func (s *FixtureS) TestSkipSuite(c *C) {
helper := FixtureHelper{skip: true, skipOnN: 0}
output := String{}
result := Run(&helper, &RunConf{Output: &output})
c.Assert(output.value, Equals, "")
c.Assert(helper.calls[0], Equals, "SetUpSuite")
c.Assert(helper.calls[1], Equals, "TearDownSuite")
c.Assert(len(helper.calls), Equals, 2)
c.Assert(result.Skipped, Equals, 2)
}
func (s *FixtureS) TestSkipTest(c *C) {
helper := FixtureHelper{skip: true, skipOnN: 1}
output := String{}
result := Run(&helper, &RunConf{Output: &output})
c.Assert(helper.calls[0], Equals, "SetUpSuite")
c.Assert(helper.calls[1], Equals, "SetUpTest")
c.Assert(helper.calls[2], Equals, "SetUpTest")
c.Assert(helper.calls[3], Equals, "Test2")
c.Assert(helper.calls[4], Equals, "TearDownTest")
c.Assert(helper.calls[5], Equals, "TearDownSuite")
c.Assert(len(helper.calls), Equals, 6)
c.Assert(result.Skipped, Equals, 1)
}

View file

@ -0,0 +1,335 @@
// These tests check that the foundations of gocheck are working properly.
// They already assume that fundamental failing is working already, though,
// since this was tested in bootstrap_test.go. Even then, some care may
// still have to be taken when using external functions, since they should
// of course not rely on functionality tested here.
package check_test
import (
"fmt"
"gopkg.in/check.v1"
"log"
"os"
"regexp"
"strings"
)
// -----------------------------------------------------------------------
// Foundation test suite.
type FoundationS struct{}
var foundationS = check.Suite(&FoundationS{})
func (s *FoundationS) TestCountSuite(c *check.C) {
suitesRun += 1
}
func (s *FoundationS) TestErrorf(c *check.C) {
// Do not use checkState() here. It depends on Errorf() working.
expectedLog := fmt.Sprintf("foundation_test.go:%d:\n"+
" c.Errorf(\"Error %%v!\", \"message\")\n"+
"... Error: Error message!\n\n",
getMyLine()+1)
c.Errorf("Error %v!", "message")
failed := c.Failed()
c.Succeed()
if log := c.GetTestLog(); log != expectedLog {
c.Logf("Errorf() logged %#v rather than %#v", log, expectedLog)
c.Fail()
}
if !failed {
c.Logf("Errorf() didn't put the test in a failed state")
c.Fail()
}
}
func (s *FoundationS) TestError(c *check.C) {
expectedLog := fmt.Sprintf("foundation_test.go:%d:\n"+
" c\\.Error\\(\"Error \", \"message!\"\\)\n"+
"\\.\\.\\. Error: Error message!\n\n",
getMyLine()+1)
c.Error("Error ", "message!")
checkState(c, nil,
&expectedState{
name: "Error(`Error `, `message!`)",
failed: true,
log: expectedLog,
})
}
func (s *FoundationS) TestFailNow(c *check.C) {
defer (func() {
if !c.Failed() {
c.Error("FailNow() didn't fail the test")
} else {
c.Succeed()
if c.GetTestLog() != "" {
c.Error("Something got logged:\n" + c.GetTestLog())
}
}
})()
c.FailNow()
c.Log("FailNow() didn't stop the test")
}
func (s *FoundationS) TestSucceedNow(c *check.C) {
defer (func() {
if c.Failed() {
c.Error("SucceedNow() didn't succeed the test")
}
if c.GetTestLog() != "" {
c.Error("Something got logged:\n" + c.GetTestLog())
}
})()
c.Fail()
c.SucceedNow()
c.Log("SucceedNow() didn't stop the test")
}
func (s *FoundationS) TestFailureHeader(c *check.C) {
output := String{}
failHelper := FailHelper{}
check.Run(&failHelper, &check.RunConf{Output: &output})
header := fmt.Sprintf(""+
"\n-----------------------------------"+
"-----------------------------------\n"+
"FAIL: check_test.go:%d: FailHelper.TestLogAndFail\n",
failHelper.testLine)
if strings.Index(output.value, header) == -1 {
c.Errorf(""+
"Failure didn't print a proper header.\n"+
"... Got:\n%s... Expected something with:\n%s",
output.value, header)
}
}
func (s *FoundationS) TestFatal(c *check.C) {
var line int
defer (func() {
if !c.Failed() {
c.Error("Fatal() didn't fail the test")
} else {
c.Succeed()
expected := fmt.Sprintf("foundation_test.go:%d:\n"+
" c.Fatal(\"Die \", \"now!\")\n"+
"... Error: Die now!\n\n",
line)
if c.GetTestLog() != expected {
c.Error("Incorrect log:", c.GetTestLog())
}
}
})()
line = getMyLine() + 1
c.Fatal("Die ", "now!")
c.Log("Fatal() didn't stop the test")
}
func (s *FoundationS) TestFatalf(c *check.C) {
var line int
defer (func() {
if !c.Failed() {
c.Error("Fatalf() didn't fail the test")
} else {
c.Succeed()
expected := fmt.Sprintf("foundation_test.go:%d:\n"+
" c.Fatalf(\"Die %%s!\", \"now\")\n"+
"... Error: Die now!\n\n",
line)
if c.GetTestLog() != expected {
c.Error("Incorrect log:", c.GetTestLog())
}
}
})()
line = getMyLine() + 1
c.Fatalf("Die %s!", "now")
c.Log("Fatalf() didn't stop the test")
}
func (s *FoundationS) TestCallerLoggingInsideTest(c *check.C) {
log := fmt.Sprintf(""+
"foundation_test.go:%d:\n"+
" result := c.Check\\(10, check.Equals, 20\\)\n"+
"\\.\\.\\. obtained int = 10\n"+
"\\.\\.\\. expected int = 20\n\n",
getMyLine()+1)
result := c.Check(10, check.Equals, 20)
checkState(c, result,
&expectedState{
name: "Check(10, Equals, 20)",
result: false,
failed: true,
log: log,
})
}
func (s *FoundationS) TestCallerLoggingInDifferentFile(c *check.C) {
result, line := checkEqualWrapper(c, 10, 20)
testLine := getMyLine() - 1
log := fmt.Sprintf(""+
"foundation_test.go:%d:\n"+
" result, line := checkEqualWrapper\\(c, 10, 20\\)\n"+
"check_test.go:%d:\n"+
" return c.Check\\(obtained, check.Equals, expected\\), getMyLine\\(\\)\n"+
"\\.\\.\\. obtained int = 10\n"+
"\\.\\.\\. expected int = 20\n\n",
testLine, line)
checkState(c, result,
&expectedState{
name: "Check(10, Equals, 20)",
result: false,
failed: true,
log: log,
})
}
// -----------------------------------------------------------------------
// ExpectFailure() inverts the logic of failure.
type ExpectFailureSucceedHelper struct{}
func (s *ExpectFailureSucceedHelper) TestSucceed(c *check.C) {
c.ExpectFailure("It booms!")
c.Error("Boom!")
}
type ExpectFailureFailHelper struct{}
func (s *ExpectFailureFailHelper) TestFail(c *check.C) {
c.ExpectFailure("Bug #XYZ")
}
func (s *FoundationS) TestExpectFailureFail(c *check.C) {
helper := ExpectFailureFailHelper{}
output := String{}
result := check.Run(&helper, &check.RunConf{Output: &output})
expected := "" +
"^\n-+\n" +
"FAIL: foundation_test\\.go:[0-9]+:" +
" ExpectFailureFailHelper\\.TestFail\n\n" +
"\\.\\.\\. Error: Test succeeded, but was expected to fail\n" +
"\\.\\.\\. Reason: Bug #XYZ\n$"
matched, err := regexp.MatchString(expected, output.value)
if err != nil {
c.Error("Bad expression: ", expected)
} else if !matched {
c.Error("ExpectFailure() didn't log properly:\n", output.value)
}
c.Assert(result.ExpectedFailures, check.Equals, 0)
}
func (s *FoundationS) TestExpectFailureSucceed(c *check.C) {
helper := ExpectFailureSucceedHelper{}
output := String{}
result := check.Run(&helper, &check.RunConf{Output: &output})
c.Assert(output.value, check.Equals, "")
c.Assert(result.ExpectedFailures, check.Equals, 1)
}
func (s *FoundationS) TestExpectFailureSucceedVerbose(c *check.C) {
helper := ExpectFailureSucceedHelper{}
output := String{}
result := check.Run(&helper, &check.RunConf{Output: &output, Verbose: true})
expected := "" +
"FAIL EXPECTED: foundation_test\\.go:[0-9]+:" +
" ExpectFailureSucceedHelper\\.TestSucceed \\(It booms!\\)\t *[.0-9]+s\n"
matched, err := regexp.MatchString(expected, output.value)
if err != nil {
c.Error("Bad expression: ", expected)
} else if !matched {
c.Error("ExpectFailure() didn't log properly:\n", output.value)
}
c.Assert(result.ExpectedFailures, check.Equals, 1)
}
// -----------------------------------------------------------------------
// Skip() allows stopping a test without positive/negative results.
type SkipTestHelper struct{}
func (s *SkipTestHelper) TestFail(c *check.C) {
c.Skip("Wrong platform or whatever")
c.Error("Boom!")
}
func (s *FoundationS) TestSkip(c *check.C) {
helper := SkipTestHelper{}
output := String{}
check.Run(&helper, &check.RunConf{Output: &output})
if output.value != "" {
c.Error("Skip() logged something:\n", output.value)
}
}
func (s *FoundationS) TestSkipVerbose(c *check.C) {
helper := SkipTestHelper{}
output := String{}
check.Run(&helper, &check.RunConf{Output: &output, Verbose: true})
expected := "SKIP: foundation_test\\.go:[0-9]+: SkipTestHelper\\.TestFail" +
" \\(Wrong platform or whatever\\)"
matched, err := regexp.MatchString(expected, output.value)
if err != nil {
c.Error("Bad expression: ", expected)
} else if !matched {
c.Error("Skip() didn't log properly:\n", output.value)
}
}
// -----------------------------------------------------------------------
// Check minimum *log.Logger interface provided by *check.C.
type minLogger interface {
Output(calldepth int, s string) error
}
func (s *BootstrapS) TestMinLogger(c *check.C) {
var logger minLogger
logger = log.New(os.Stderr, "", 0)
logger = c
logger.Output(0, "Hello there")
expected := `\[LOG\] [0-9]+:[0-9][0-9]\.[0-9][0-9][0-9] +Hello there\n`
output := c.GetTestLog()
c.Assert(output, check.Matches, expected)
}
// -----------------------------------------------------------------------
// Ensure that suites with embedded types are working fine, including the
// the workaround for issue 906.
type EmbeddedInternalS struct {
called bool
}
type EmbeddedS struct {
EmbeddedInternalS
}
var embeddedS = check.Suite(&EmbeddedS{})
func (s *EmbeddedS) TestCountSuite(c *check.C) {
suitesRun += 1
}
func (s *EmbeddedInternalS) TestMethod(c *check.C) {
c.Error("TestMethod() of the embedded type was called!?")
}
func (s *EmbeddedS) TestMethod(c *check.C) {
// http://code.google.com/p/go/issues/detail?id=906
c.Check(s.called, check.Equals, false) // Go issue 906 is affecting the runner?
s.called = true
}

View file

@ -0,0 +1,231 @@
package check
import (
"fmt"
"strings"
"time"
)
// TestName returns the current test name in the form "SuiteName.TestName"
func (c *C) TestName() string {
return c.testName
}
// -----------------------------------------------------------------------
// Basic succeeding/failing logic.
// Failed returns whether the currently running test has already failed.
func (c *C) Failed() bool {
return c.status == failedSt
}
// Fail marks the currently running test as failed.
//
// Something ought to have been previously logged so the developer can tell
// what went wrong. The higher level helper functions will fail the test
// and do the logging properly.
func (c *C) Fail() {
c.status = failedSt
}
// FailNow marks the currently running test as failed and stops running it.
// Something ought to have been previously logged so the developer can tell
// what went wrong. The higher level helper functions will fail the test
// and do the logging properly.
func (c *C) FailNow() {
c.Fail()
c.stopNow()
}
// Succeed marks the currently running test as succeeded, undoing any
// previous failures.
func (c *C) Succeed() {
c.status = succeededSt
}
// SucceedNow marks the currently running test as succeeded, undoing any
// previous failures, and stops running the test.
func (c *C) SucceedNow() {
c.Succeed()
c.stopNow()
}
// ExpectFailure informs that the running test is knowingly broken for
// the provided reason. If the test does not fail, an error will be reported
// to raise attention to this fact. This method is useful to temporarily
// disable tests which cover well known problems until a better time to
// fix the problem is found, without forgetting about the fact that a
// failure still exists.
func (c *C) ExpectFailure(reason string) {
if reason == "" {
panic("Missing reason why the test is expected to fail")
}
c.mustFail = true
c.reason = reason
}
// Skip skips the running test for the provided reason. If run from within
// SetUpTest, the individual test being set up will be skipped, and if run
// from within SetUpSuite, the whole suite is skipped.
func (c *C) Skip(reason string) {
if reason == "" {
panic("Missing reason why the test is being skipped")
}
c.reason = reason
c.status = skippedSt
c.stopNow()
}
// -----------------------------------------------------------------------
// Basic logging.
// GetTestLog returns the current test error output.
func (c *C) GetTestLog() string {
return c.logb.String()
}
// Log logs some information into the test error output.
// The provided arguments are assembled together into a string with fmt.Sprint.
func (c *C) Log(args ...interface{}) {
c.log(args...)
}
// Log logs some information into the test error output.
// The provided arguments are assembled together into a string with fmt.Sprintf.
func (c *C) Logf(format string, args ...interface{}) {
c.logf(format, args...)
}
// Output enables *C to be used as a logger in functions that require only
// the minimum interface of *log.Logger.
func (c *C) Output(calldepth int, s string) error {
d := time.Now().Sub(c.startTime)
msec := d / time.Millisecond
sec := d / time.Second
min := d / time.Minute
c.Logf("[LOG] %d:%02d.%03d %s", min, sec%60, msec%1000, s)
return nil
}
// Error logs an error into the test error output and marks the test as failed.
// The provided arguments are assembled together into a string with fmt.Sprint.
func (c *C) Error(args ...interface{}) {
c.logCaller(1)
c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...)))
c.logNewLine()
c.Fail()
}
// Errorf logs an error into the test error output and marks the test as failed.
// The provided arguments are assembled together into a string with fmt.Sprintf.
func (c *C) Errorf(format string, args ...interface{}) {
c.logCaller(1)
c.logString(fmt.Sprintf("Error: "+format, args...))
c.logNewLine()
c.Fail()
}
// Fatal logs an error into the test error output, marks the test as failed, and
// stops the test execution. The provided arguments are assembled together into
// a string with fmt.Sprint.
func (c *C) Fatal(args ...interface{}) {
c.logCaller(1)
c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...)))
c.logNewLine()
c.FailNow()
}
// Fatlaf logs an error into the test error output, marks the test as failed, and
// stops the test execution. The provided arguments are assembled together into
// a string with fmt.Sprintf.
func (c *C) Fatalf(format string, args ...interface{}) {
c.logCaller(1)
c.logString(fmt.Sprint("Error: ", fmt.Sprintf(format, args...)))
c.logNewLine()
c.FailNow()
}
// -----------------------------------------------------------------------
// Generic checks and assertions based on checkers.
// Check verifies if the first value matches the expected value according
// to the provided checker. If they do not match, an error is logged, the
// test is marked as failed, and the test execution continues.
//
// Some checkers may not need the expected argument (e.g. IsNil).
//
// Extra arguments provided to the function are logged next to the reported
// problem when the matching fails.
func (c *C) Check(obtained interface{}, checker Checker, args ...interface{}) bool {
return c.internalCheck("Check", obtained, checker, args...)
}
// Assert ensures that the first value matches the expected value according
// to the provided checker. If they do not match, an error is logged, the
// test is marked as failed, and the test execution stops.
//
// Some checkers may not need the expected argument (e.g. IsNil).
//
// Extra arguments provided to the function are logged next to the reported
// problem when the matching fails.
func (c *C) Assert(obtained interface{}, checker Checker, args ...interface{}) {
if !c.internalCheck("Assert", obtained, checker, args...) {
c.stopNow()
}
}
func (c *C) internalCheck(funcName string, obtained interface{}, checker Checker, args ...interface{}) bool {
if checker == nil {
c.logCaller(2)
c.logString(fmt.Sprintf("%s(obtained, nil!?, ...):", funcName))
c.logString("Oops.. you've provided a nil checker!")
c.logNewLine()
c.Fail()
return false
}
// If the last argument is a bug info, extract it out.
var comment CommentInterface
if len(args) > 0 {
if c, ok := args[len(args)-1].(CommentInterface); ok {
comment = c
args = args[:len(args)-1]
}
}
params := append([]interface{}{obtained}, args...)
info := checker.Info()
if len(params) != len(info.Params) {
names := append([]string{info.Params[0], info.Name}, info.Params[1:]...)
c.logCaller(2)
c.logString(fmt.Sprintf("%s(%s):", funcName, strings.Join(names, ", ")))
c.logString(fmt.Sprintf("Wrong number of parameters for %s: want %d, got %d", info.Name, len(names), len(params)+1))
c.logNewLine()
c.Fail()
return false
}
// Copy since it may be mutated by Check.
names := append([]string{}, info.Params...)
// Do the actual check.
result, error := checker.Check(params, names)
if !result || error != "" {
c.logCaller(2)
for i := 0; i != len(params); i++ {
c.logValue(names[i], params[i])
}
if comment != nil {
c.logString(comment.CheckCommentString())
}
if error != "" {
c.logString(error)
}
c.logNewLine()
c.Fail()
return false
}
return true
}

View file

@ -0,0 +1,519 @@
// These tests verify the inner workings of the helper methods associated
// with check.T.
package check_test
import (
"gopkg.in/check.v1"
"os"
"reflect"
"runtime"
"sync"
)
var helpersS = check.Suite(&HelpersS{})
type HelpersS struct{}
func (s *HelpersS) TestCountSuite(c *check.C) {
suitesRun += 1
}
// -----------------------------------------------------------------------
// Fake checker and bug info to verify the behavior of Assert() and Check().
type MyChecker struct {
info *check.CheckerInfo
params []interface{}
names []string
result bool
error string
}
func (checker *MyChecker) Info() *check.CheckerInfo {
if checker.info == nil {
return &check.CheckerInfo{Name: "MyChecker", Params: []string{"myobtained", "myexpected"}}
}
return checker.info
}
func (checker *MyChecker) Check(params []interface{}, names []string) (bool, string) {
rparams := checker.params
rnames := checker.names
checker.params = append([]interface{}{}, params...)
checker.names = append([]string{}, names...)
if rparams != nil {
copy(params, rparams)
}
if rnames != nil {
copy(names, rnames)
}
return checker.result, checker.error
}
type myCommentType string
func (c myCommentType) CheckCommentString() string {
return string(c)
}
func myComment(s string) myCommentType {
return myCommentType(s)
}
// -----------------------------------------------------------------------
// Ensure a real checker actually works fine.
func (s *HelpersS) TestCheckerInterface(c *check.C) {
testHelperSuccess(c, "Check(1, Equals, 1)", true, func() interface{} {
return c.Check(1, check.Equals, 1)
})
}
// -----------------------------------------------------------------------
// Tests for Check(), mostly the same as for Assert() following these.
func (s *HelpersS) TestCheckSucceedWithExpected(c *check.C) {
checker := &MyChecker{result: true}
testHelperSuccess(c, "Check(1, checker, 2)", true, func() interface{} {
return c.Check(1, checker, 2)
})
if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) {
c.Fatalf("Bad params for check: %#v", checker.params)
}
}
func (s *HelpersS) TestCheckSucceedWithoutExpected(c *check.C) {
checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
testHelperSuccess(c, "Check(1, checker)", true, func() interface{} {
return c.Check(1, checker)
})
if !reflect.DeepEqual(checker.params, []interface{}{1}) {
c.Fatalf("Bad params for check: %#v", checker.params)
}
}
func (s *HelpersS) TestCheckFailWithExpected(c *check.C) {
checker := &MyChecker{result: false}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" return c\\.Check\\(1, checker, 2\\)\n" +
"\\.+ myobtained int = 1\n" +
"\\.+ myexpected int = 2\n\n"
testHelperFailure(c, "Check(1, checker, 2)", false, false, log,
func() interface{} {
return c.Check(1, checker, 2)
})
}
func (s *HelpersS) TestCheckFailWithExpectedAndComment(c *check.C) {
checker := &MyChecker{result: false}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" return c\\.Check\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" +
"\\.+ myobtained int = 1\n" +
"\\.+ myexpected int = 2\n" +
"\\.+ Hello world!\n\n"
testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log,
func() interface{} {
return c.Check(1, checker, 2, myComment("Hello world!"))
})
}
func (s *HelpersS) TestCheckFailWithExpectedAndStaticComment(c *check.C) {
checker := &MyChecker{result: false}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" // Nice leading comment\\.\n" +
" return c\\.Check\\(1, checker, 2\\) // Hello there\n" +
"\\.+ myobtained int = 1\n" +
"\\.+ myexpected int = 2\n\n"
testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log,
func() interface{} {
// Nice leading comment.
return c.Check(1, checker, 2) // Hello there
})
}
func (s *HelpersS) TestCheckFailWithoutExpected(c *check.C) {
checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" return c\\.Check\\(1, checker\\)\n" +
"\\.+ myvalue int = 1\n\n"
testHelperFailure(c, "Check(1, checker)", false, false, log,
func() interface{} {
return c.Check(1, checker)
})
}
func (s *HelpersS) TestCheckFailWithoutExpectedAndMessage(c *check.C) {
checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" return c\\.Check\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" +
"\\.+ myvalue int = 1\n" +
"\\.+ Hello world!\n\n"
testHelperFailure(c, "Check(1, checker, msg)", false, false, log,
func() interface{} {
return c.Check(1, checker, myComment("Hello world!"))
})
}
func (s *HelpersS) TestCheckWithMissingExpected(c *check.C) {
checker := &MyChecker{result: true}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" return c\\.Check\\(1, checker\\)\n" +
"\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" +
"\\.+ Wrong number of parameters for MyChecker: " +
"want 3, got 2\n\n"
testHelperFailure(c, "Check(1, checker, !?)", false, false, log,
func() interface{} {
return c.Check(1, checker)
})
}
func (s *HelpersS) TestCheckWithTooManyExpected(c *check.C) {
checker := &MyChecker{result: true}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" return c\\.Check\\(1, checker, 2, 3\\)\n" +
"\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" +
"\\.+ Wrong number of parameters for MyChecker: " +
"want 3, got 4\n\n"
testHelperFailure(c, "Check(1, checker, 2, 3)", false, false, log,
func() interface{} {
return c.Check(1, checker, 2, 3)
})
}
func (s *HelpersS) TestCheckWithError(c *check.C) {
checker := &MyChecker{result: false, error: "Some not so cool data provided!"}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" return c\\.Check\\(1, checker, 2\\)\n" +
"\\.+ myobtained int = 1\n" +
"\\.+ myexpected int = 2\n" +
"\\.+ Some not so cool data provided!\n\n"
testHelperFailure(c, "Check(1, checker, 2)", false, false, log,
func() interface{} {
return c.Check(1, checker, 2)
})
}
func (s *HelpersS) TestCheckWithNilChecker(c *check.C) {
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" return c\\.Check\\(1, nil\\)\n" +
"\\.+ Check\\(obtained, nil!\\?, \\.\\.\\.\\):\n" +
"\\.+ Oops\\.\\. you've provided a nil checker!\n\n"
testHelperFailure(c, "Check(obtained, nil)", false, false, log,
func() interface{} {
return c.Check(1, nil)
})
}
func (s *HelpersS) TestCheckWithParamsAndNamesMutation(c *check.C) {
checker := &MyChecker{result: false, params: []interface{}{3, 4}, names: []string{"newobtained", "newexpected"}}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" return c\\.Check\\(1, checker, 2\\)\n" +
"\\.+ newobtained int = 3\n" +
"\\.+ newexpected int = 4\n\n"
testHelperFailure(c, "Check(1, checker, 2) with mutation", false, false, log,
func() interface{} {
return c.Check(1, checker, 2)
})
}
// -----------------------------------------------------------------------
// Tests for Assert(), mostly the same as for Check() above.
func (s *HelpersS) TestAssertSucceedWithExpected(c *check.C) {
checker := &MyChecker{result: true}
testHelperSuccess(c, "Assert(1, checker, 2)", nil, func() interface{} {
c.Assert(1, checker, 2)
return nil
})
if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) {
c.Fatalf("Bad params for check: %#v", checker.params)
}
}
func (s *HelpersS) TestAssertSucceedWithoutExpected(c *check.C) {
checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
testHelperSuccess(c, "Assert(1, checker)", nil, func() interface{} {
c.Assert(1, checker)
return nil
})
if !reflect.DeepEqual(checker.params, []interface{}{1}) {
c.Fatalf("Bad params for check: %#v", checker.params)
}
}
func (s *HelpersS) TestAssertFailWithExpected(c *check.C) {
checker := &MyChecker{result: false}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" c\\.Assert\\(1, checker, 2\\)\n" +
"\\.+ myobtained int = 1\n" +
"\\.+ myexpected int = 2\n\n"
testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log,
func() interface{} {
c.Assert(1, checker, 2)
return nil
})
}
func (s *HelpersS) TestAssertFailWithExpectedAndMessage(c *check.C) {
checker := &MyChecker{result: false}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" c\\.Assert\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" +
"\\.+ myobtained int = 1\n" +
"\\.+ myexpected int = 2\n" +
"\\.+ Hello world!\n\n"
testHelperFailure(c, "Assert(1, checker, 2, msg)", nil, true, log,
func() interface{} {
c.Assert(1, checker, 2, myComment("Hello world!"))
return nil
})
}
func (s *HelpersS) TestAssertFailWithoutExpected(c *check.C) {
checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" c\\.Assert\\(1, checker\\)\n" +
"\\.+ myvalue int = 1\n\n"
testHelperFailure(c, "Assert(1, checker)", nil, true, log,
func() interface{} {
c.Assert(1, checker)
return nil
})
}
func (s *HelpersS) TestAssertFailWithoutExpectedAndMessage(c *check.C) {
checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" c\\.Assert\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" +
"\\.+ myvalue int = 1\n" +
"\\.+ Hello world!\n\n"
testHelperFailure(c, "Assert(1, checker, msg)", nil, true, log,
func() interface{} {
c.Assert(1, checker, myComment("Hello world!"))
return nil
})
}
func (s *HelpersS) TestAssertWithMissingExpected(c *check.C) {
checker := &MyChecker{result: true}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" c\\.Assert\\(1, checker\\)\n" +
"\\.+ Assert\\(myobtained, MyChecker, myexpected\\):\n" +
"\\.+ Wrong number of parameters for MyChecker: " +
"want 3, got 2\n\n"
testHelperFailure(c, "Assert(1, checker, !?)", nil, true, log,
func() interface{} {
c.Assert(1, checker)
return nil
})
}
func (s *HelpersS) TestAssertWithError(c *check.C) {
checker := &MyChecker{result: false, error: "Some not so cool data provided!"}
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" c\\.Assert\\(1, checker, 2\\)\n" +
"\\.+ myobtained int = 1\n" +
"\\.+ myexpected int = 2\n" +
"\\.+ Some not so cool data provided!\n\n"
testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log,
func() interface{} {
c.Assert(1, checker, 2)
return nil
})
}
func (s *HelpersS) TestAssertWithNilChecker(c *check.C) {
log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" +
" c\\.Assert\\(1, nil\\)\n" +
"\\.+ Assert\\(obtained, nil!\\?, \\.\\.\\.\\):\n" +
"\\.+ Oops\\.\\. you've provided a nil checker!\n\n"
testHelperFailure(c, "Assert(obtained, nil)", nil, true, log,
func() interface{} {
c.Assert(1, nil)
return nil
})
}
// -----------------------------------------------------------------------
// Ensure that values logged work properly in some interesting cases.
func (s *HelpersS) TestValueLoggingWithArrays(c *check.C) {
checker := &MyChecker{result: false}
log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
" return c\\.Check\\(\\[\\]byte{1, 2}, checker, \\[\\]byte{1, 3}\\)\n" +
"\\.+ myobtained \\[\\]uint8 = \\[\\]byte{0x1, 0x2}\n" +
"\\.+ myexpected \\[\\]uint8 = \\[\\]byte{0x1, 0x3}\n\n"
testHelperFailure(c, "Check([]byte{1}, chk, []byte{3})", false, false, log,
func() interface{} {
return c.Check([]byte{1, 2}, checker, []byte{1, 3})
})
}
func (s *HelpersS) TestValueLoggingWithMultiLine(c *check.C) {
checker := &MyChecker{result: false}
log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
" return c\\.Check\\(\"a\\\\nb\\\\n\", checker, \"a\\\\nb\\\\nc\"\\)\n" +
"\\.+ myobtained string = \"\" \\+\n" +
"\\.+ \"a\\\\n\" \\+\n" +
"\\.+ \"b\\\\n\"\n" +
"\\.+ myexpected string = \"\" \\+\n" +
"\\.+ \"a\\\\n\" \\+\n" +
"\\.+ \"b\\\\n\" \\+\n" +
"\\.+ \"c\"\n\n"
testHelperFailure(c, `Check("a\nb\n", chk, "a\nb\nc")`, false, false, log,
func() interface{} {
return c.Check("a\nb\n", checker, "a\nb\nc")
})
}
func (s *HelpersS) TestValueLoggingWithMultiLineException(c *check.C) {
// If the newline is at the end of the string, don't log as multi-line.
checker := &MyChecker{result: false}
log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" +
" return c\\.Check\\(\"a b\\\\n\", checker, \"a\\\\nb\"\\)\n" +
"\\.+ myobtained string = \"a b\\\\n\"\n" +
"\\.+ myexpected string = \"\" \\+\n" +
"\\.+ \"a\\\\n\" \\+\n" +
"\\.+ \"b\"\n\n"
testHelperFailure(c, `Check("a b\n", chk, "a\nb")`, false, false, log,
func() interface{} {
return c.Check("a b\n", checker, "a\nb")
})
}
// -----------------------------------------------------------------------
// MakeDir() tests.
type MkDirHelper struct {
path1 string
path2 string
isDir1 bool
isDir2 bool
isDir3 bool
isDir4 bool
}
func (s *MkDirHelper) SetUpSuite(c *check.C) {
s.path1 = c.MkDir()
s.isDir1 = isDir(s.path1)
}
func (s *MkDirHelper) Test(c *check.C) {
s.path2 = c.MkDir()
s.isDir2 = isDir(s.path2)
}
func (s *MkDirHelper) TearDownSuite(c *check.C) {
s.isDir3 = isDir(s.path1)
s.isDir4 = isDir(s.path2)
}
func (s *HelpersS) TestMkDir(c *check.C) {
helper := MkDirHelper{}
output := String{}
check.Run(&helper, &check.RunConf{Output: &output})
c.Assert(output.value, check.Equals, "")
c.Check(helper.isDir1, check.Equals, true)
c.Check(helper.isDir2, check.Equals, true)
c.Check(helper.isDir3, check.Equals, true)
c.Check(helper.isDir4, check.Equals, true)
c.Check(helper.path1, check.Not(check.Equals),
helper.path2)
c.Check(isDir(helper.path1), check.Equals, false)
c.Check(isDir(helper.path2), check.Equals, false)
}
func isDir(path string) bool {
if stat, err := os.Stat(path); err == nil {
return stat.IsDir()
}
return false
}
// Concurrent logging should not corrupt the underling buffer.
// Use go test -race to detect the race in this test.
func (s *HelpersS) TestConcurrentLogging(c *check.C) {
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(runtime.NumCPU()))
var start, stop sync.WaitGroup
start.Add(1)
for i, n := 0, runtime.NumCPU()*2; i < n; i++ {
stop.Add(1)
go func(i int) {
start.Wait()
for j := 0; j < 30; j++ {
c.Logf("Worker %d: line %d", i, j)
}
stop.Done()
}(i)
}
start.Done()
stop.Wait()
}
// -----------------------------------------------------------------------
// Test the TestName function
type TestNameHelper struct {
name1 string
name2 string
name3 string
name4 string
name5 string
}
func (s *TestNameHelper) SetUpSuite(c *check.C) { s.name1 = c.TestName() }
func (s *TestNameHelper) SetUpTest(c *check.C) { s.name2 = c.TestName() }
func (s *TestNameHelper) Test(c *check.C) { s.name3 = c.TestName() }
func (s *TestNameHelper) TearDownTest(c *check.C) { s.name4 = c.TestName() }
func (s *TestNameHelper) TearDownSuite(c *check.C) { s.name5 = c.TestName() }
func (s *HelpersS) TestTestName(c *check.C) {
helper := TestNameHelper{}
output := String{}
check.Run(&helper, &check.RunConf{Output: &output})
c.Check(helper.name1, check.Equals, "")
c.Check(helper.name2, check.Equals, "TestNameHelper.Test")
c.Check(helper.name3, check.Equals, "TestNameHelper.Test")
c.Check(helper.name4, check.Equals, "TestNameHelper.Test")
c.Check(helper.name5, check.Equals, "")
}
// -----------------------------------------------------------------------
// A couple of helper functions to test helper functions. :-)
func testHelperSuccess(c *check.C, name string, expectedResult interface{}, closure func() interface{}) {
var result interface{}
defer (func() {
if err := recover(); err != nil {
panic(err)
}
checkState(c, result,
&expectedState{
name: name,
result: expectedResult,
failed: false,
log: "",
})
})()
result = closure()
}
func testHelperFailure(c *check.C, name string, expectedResult interface{}, shouldStop bool, log string, closure func() interface{}) {
var result interface{}
defer (func() {
if err := recover(); err != nil {
panic(err)
}
checkState(c, result,
&expectedState{
name: name,
result: expectedResult,
failed: true,
log: log,
})
})()
result = closure()
if shouldStop {
c.Logf("%s didn't stop when it should", name)
}
}

View file

@ -0,0 +1,168 @@
package check
import (
"bytes"
"go/ast"
"go/parser"
"go/printer"
"go/token"
"os"
)
func indent(s, with string) (r string) {
eol := true
for i := 0; i != len(s); i++ {
c := s[i]
switch {
case eol && c == '\n' || c == '\r':
case c == '\n' || c == '\r':
eol = true
case eol:
eol = false
s = s[:i] + with + s[i:]
i += len(with)
}
}
return s
}
func printLine(filename string, line int) (string, error) {
fset := token.NewFileSet()
file, err := os.Open(filename)
if err != nil {
return "", err
}
fnode, err := parser.ParseFile(fset, filename, file, parser.ParseComments)
if err != nil {
return "", err
}
config := &printer.Config{Mode: printer.UseSpaces, Tabwidth: 4}
lp := &linePrinter{fset: fset, fnode: fnode, line: line, config: config}
ast.Walk(lp, fnode)
result := lp.output.Bytes()
// Comments leave \n at the end.
n := len(result)
for n > 0 && result[n-1] == '\n' {
n--
}
return string(result[:n]), nil
}
type linePrinter struct {
config *printer.Config
fset *token.FileSet
fnode *ast.File
line int
output bytes.Buffer
stmt ast.Stmt
}
func (lp *linePrinter) emit() bool {
if lp.stmt != nil {
lp.trim(lp.stmt)
lp.printWithComments(lp.stmt)
lp.stmt = nil
return true
}
return false
}
func (lp *linePrinter) printWithComments(n ast.Node) {
nfirst := lp.fset.Position(n.Pos()).Line
nlast := lp.fset.Position(n.End()).Line
for _, g := range lp.fnode.Comments {
cfirst := lp.fset.Position(g.Pos()).Line
clast := lp.fset.Position(g.End()).Line
if clast == nfirst-1 && lp.fset.Position(n.Pos()).Column == lp.fset.Position(g.Pos()).Column {
for _, c := range g.List {
lp.output.WriteString(c.Text)
lp.output.WriteByte('\n')
}
}
if cfirst >= nfirst && cfirst <= nlast && n.End() <= g.List[0].Slash {
// The printer will not include the comment if it starts past
// the node itself. Trick it into printing by overlapping the
// slash with the end of the statement.
g.List[0].Slash = n.End() - 1
}
}
node := &printer.CommentedNode{n, lp.fnode.Comments}
lp.config.Fprint(&lp.output, lp.fset, node)
}
func (lp *linePrinter) Visit(n ast.Node) (w ast.Visitor) {
if n == nil {
if lp.output.Len() == 0 {
lp.emit()
}
return nil
}
first := lp.fset.Position(n.Pos()).Line
last := lp.fset.Position(n.End()).Line
if first <= lp.line && last >= lp.line {
// Print the innermost statement containing the line.
if stmt, ok := n.(ast.Stmt); ok {
if _, ok := n.(*ast.BlockStmt); !ok {
lp.stmt = stmt
}
}
if first == lp.line && lp.emit() {
return nil
}
return lp
}
return nil
}
func (lp *linePrinter) trim(n ast.Node) bool {
stmt, ok := n.(ast.Stmt)
if !ok {
return true
}
line := lp.fset.Position(n.Pos()).Line
if line != lp.line {
return false
}
switch stmt := stmt.(type) {
case *ast.IfStmt:
stmt.Body = lp.trimBlock(stmt.Body)
case *ast.SwitchStmt:
stmt.Body = lp.trimBlock(stmt.Body)
case *ast.TypeSwitchStmt:
stmt.Body = lp.trimBlock(stmt.Body)
case *ast.CaseClause:
stmt.Body = lp.trimList(stmt.Body)
case *ast.CommClause:
stmt.Body = lp.trimList(stmt.Body)
case *ast.BlockStmt:
stmt.List = lp.trimList(stmt.List)
}
return true
}
func (lp *linePrinter) trimBlock(stmt *ast.BlockStmt) *ast.BlockStmt {
if !lp.trim(stmt) {
return lp.emptyBlock(stmt)
}
stmt.Rbrace = stmt.Lbrace
return stmt
}
func (lp *linePrinter) trimList(stmts []ast.Stmt) []ast.Stmt {
for i := 0; i != len(stmts); i++ {
if !lp.trim(stmts[i]) {
stmts[i] = lp.emptyStmt(stmts[i])
break
}
}
return stmts
}
func (lp *linePrinter) emptyStmt(n ast.Node) *ast.ExprStmt {
return &ast.ExprStmt{&ast.Ellipsis{n.Pos(), nil}}
}
func (lp *linePrinter) emptyBlock(n ast.Node) *ast.BlockStmt {
p := n.Pos()
return &ast.BlockStmt{p, []ast.Stmt{lp.emptyStmt(n)}, p}
}

View file

@ -0,0 +1,104 @@
package check_test
import (
. "gopkg.in/check.v1"
)
var _ = Suite(&PrinterS{})
type PrinterS struct{}
func (s *PrinterS) TestCountSuite(c *C) {
suitesRun += 1
}
var printTestFuncLine int
func init() {
printTestFuncLine = getMyLine() + 3
}
func printTestFunc() {
println(1) // Comment1
if 2 == 2 { // Comment2
println(3) // Comment3
}
switch 5 {
case 6: println(6) // Comment6
println(7)
}
switch interface{}(9).(type) {// Comment9
case int: println(10)
println(11)
}
select {
case <-(chan bool)(nil): println(14)
println(15)
default: println(16)
println(17)
}
println(19,
20)
_ = func() { println(21)
println(22)
}
println(24, func() {
println(25)
})
// Leading comment
// with multiple lines.
println(29) // Comment29
}
var printLineTests = []struct {
line int
output string
}{
{1, "println(1) // Comment1"},
{2, "if 2 == 2 { // Comment2\n ...\n}"},
{3, "println(3) // Comment3"},
{5, "switch 5 {\n...\n}"},
{6, "case 6:\n println(6) // Comment6\n ..."},
{7, "println(7)"},
{9, "switch interface{}(9).(type) { // Comment9\n...\n}"},
{10, "case int:\n println(10)\n ..."},
{14, "case <-(chan bool)(nil):\n println(14)\n ..."},
{15, "println(15)"},
{16, "default:\n println(16)\n ..."},
{17, "println(17)"},
{19, "println(19,\n 20)"},
{20, "println(19,\n 20)"},
{21, "_ = func() {\n println(21)\n println(22)\n}"},
{22, "println(22)"},
{24, "println(24, func() {\n println(25)\n})"},
{25, "println(25)"},
{26, "println(24, func() {\n println(25)\n})"},
{29, "// Leading comment\n// with multiple lines.\nprintln(29) // Comment29"},
}
func (s *PrinterS) TestPrintLine(c *C) {
for _, test := range printLineTests {
output, err := PrintLine("printer_test.go", printTestFuncLine+test.line)
c.Assert(err, IsNil)
c.Assert(output, Equals, test.output)
}
}
var indentTests = []struct {
in, out string
}{
{"", ""},
{"\n", "\n"},
{"a", ">>>a"},
{"a\n", ">>>a\n"},
{"a\nb", ">>>a\n>>>b"},
{" ", ">>> "},
}
func (s *PrinterS) TestIndent(c *C) {
for _, test := range indentTests {
out := Indent(test.in, ">>>")
c.Assert(out, Equals, test.out)
}
}

View file

@ -0,0 +1,175 @@
package check
import (
"bufio"
"flag"
"fmt"
"os"
"testing"
"time"
)
// -----------------------------------------------------------------------
// Test suite registry.
var allSuites []interface{}
// Suite registers the given value as a test suite to be run. Any methods
// starting with the Test prefix in the given value will be considered as
// a test method.
func Suite(suite interface{}) interface{} {
allSuites = append(allSuites, suite)
return suite
}
// -----------------------------------------------------------------------
// Public running interface.
var (
oldFilterFlag = flag.String("gocheck.f", "", "Regular expression selecting which tests and/or suites to run")
oldVerboseFlag = flag.Bool("gocheck.v", false, "Verbose mode")
oldStreamFlag = flag.Bool("gocheck.vv", false, "Super verbose mode (disables output caching)")
oldBenchFlag = flag.Bool("gocheck.b", false, "Run benchmarks")
oldBenchTime = flag.Duration("gocheck.btime", 1*time.Second, "approximate run time for each benchmark")
oldListFlag = flag.Bool("gocheck.list", false, "List the names of all tests that will be run")
oldWorkFlag = flag.Bool("gocheck.work", false, "Display and do not remove the test working directory")
newFilterFlag = flag.String("check.f", "", "Regular expression selecting which tests and/or suites to run")
newVerboseFlag = flag.Bool("check.v", false, "Verbose mode")
newStreamFlag = flag.Bool("check.vv", false, "Super verbose mode (disables output caching)")
newBenchFlag = flag.Bool("check.b", false, "Run benchmarks")
newBenchTime = flag.Duration("check.btime", 1*time.Second, "approximate run time for each benchmark")
newBenchMem = flag.Bool("check.bmem", false, "Report memory benchmarks")
newListFlag = flag.Bool("check.list", false, "List the names of all tests that will be run")
newWorkFlag = flag.Bool("check.work", false, "Display and do not remove the test working directory")
)
// TestingT runs all test suites registered with the Suite function,
// printing results to stdout, and reporting any failures back to
// the "testing" package.
func TestingT(testingT *testing.T) {
benchTime := *newBenchTime
if benchTime == 1*time.Second {
benchTime = *oldBenchTime
}
conf := &RunConf{
Filter: *oldFilterFlag + *newFilterFlag,
Verbose: *oldVerboseFlag || *newVerboseFlag,
Stream: *oldStreamFlag || *newStreamFlag,
Benchmark: *oldBenchFlag || *newBenchFlag,
BenchmarkTime: benchTime,
BenchmarkMem: *newBenchMem,
KeepWorkDir: *oldWorkFlag || *newWorkFlag,
}
if *oldListFlag || *newListFlag {
w := bufio.NewWriter(os.Stdout)
for _, name := range ListAll(conf) {
fmt.Fprintln(w, name)
}
w.Flush()
return
}
result := RunAll(conf)
println(result.String())
if !result.Passed() {
testingT.Fail()
}
}
// RunAll runs all test suites registered with the Suite function, using the
// provided run configuration.
func RunAll(runConf *RunConf) *Result {
result := Result{}
for _, suite := range allSuites {
result.Add(Run(suite, runConf))
}
return &result
}
// Run runs the provided test suite using the provided run configuration.
func Run(suite interface{}, runConf *RunConf) *Result {
runner := newSuiteRunner(suite, runConf)
return runner.run()
}
// ListAll returns the names of all the test functions registered with the
// Suite function that will be run with the provided run configuration.
func ListAll(runConf *RunConf) []string {
var names []string
for _, suite := range allSuites {
names = append(names, List(suite, runConf)...)
}
return names
}
// List returns the names of the test functions in the given
// suite that will be run with the provided run configuration.
func List(suite interface{}, runConf *RunConf) []string {
var names []string
runner := newSuiteRunner(suite, runConf)
for _, t := range runner.tests {
names = append(names, t.String())
}
return names
}
// -----------------------------------------------------------------------
// Result methods.
func (r *Result) Add(other *Result) {
r.Succeeded += other.Succeeded
r.Skipped += other.Skipped
r.Failed += other.Failed
r.Panicked += other.Panicked
r.FixturePanicked += other.FixturePanicked
r.ExpectedFailures += other.ExpectedFailures
r.Missed += other.Missed
if r.WorkDir != "" && other.WorkDir != "" {
r.WorkDir += ":" + other.WorkDir
} else if other.WorkDir != "" {
r.WorkDir = other.WorkDir
}
}
func (r *Result) Passed() bool {
return (r.Failed == 0 && r.Panicked == 0 &&
r.FixturePanicked == 0 && r.Missed == 0 &&
r.RunError == nil)
}
func (r *Result) String() string {
if r.RunError != nil {
return "ERROR: " + r.RunError.Error()
}
var value string
if r.Failed == 0 && r.Panicked == 0 && r.FixturePanicked == 0 &&
r.Missed == 0 {
value = "OK: "
} else {
value = "OOPS: "
}
value += fmt.Sprintf("%d passed", r.Succeeded)
if r.Skipped != 0 {
value += fmt.Sprintf(", %d skipped", r.Skipped)
}
if r.ExpectedFailures != 0 {
value += fmt.Sprintf(", %d expected failures", r.ExpectedFailures)
}
if r.Failed != 0 {
value += fmt.Sprintf(", %d FAILED", r.Failed)
}
if r.Panicked != 0 {
value += fmt.Sprintf(", %d PANICKED", r.Panicked)
}
if r.FixturePanicked != 0 {
value += fmt.Sprintf(", %d FIXTURE-PANICKED", r.FixturePanicked)
}
if r.Missed != 0 {
value += fmt.Sprintf(", %d MISSED", r.Missed)
}
if r.WorkDir != "" {
value += "\nWORK=" + r.WorkDir
}
return value
}

View file

@ -0,0 +1,419 @@
// These tests verify the test running logic.
package check_test
import (
"errors"
. "gopkg.in/check.v1"
"os"
"sync"
)
var runnerS = Suite(&RunS{})
type RunS struct{}
func (s *RunS) TestCountSuite(c *C) {
suitesRun += 1
}
// -----------------------------------------------------------------------
// Tests ensuring result counting works properly.
func (s *RunS) TestSuccess(c *C) {
output := String{}
result := Run(&SuccessHelper{}, &RunConf{Output: &output})
c.Check(result.Succeeded, Equals, 1)
c.Check(result.Failed, Equals, 0)
c.Check(result.Skipped, Equals, 0)
c.Check(result.Panicked, Equals, 0)
c.Check(result.FixturePanicked, Equals, 0)
c.Check(result.Missed, Equals, 0)
c.Check(result.RunError, IsNil)
}
func (s *RunS) TestFailure(c *C) {
output := String{}
result := Run(&FailHelper{}, &RunConf{Output: &output})
c.Check(result.Succeeded, Equals, 0)
c.Check(result.Failed, Equals, 1)
c.Check(result.Skipped, Equals, 0)
c.Check(result.Panicked, Equals, 0)
c.Check(result.FixturePanicked, Equals, 0)
c.Check(result.Missed, Equals, 0)
c.Check(result.RunError, IsNil)
}
func (s *RunS) TestFixture(c *C) {
output := String{}
result := Run(&FixtureHelper{}, &RunConf{Output: &output})
c.Check(result.Succeeded, Equals, 2)
c.Check(result.Failed, Equals, 0)
c.Check(result.Skipped, Equals, 0)
c.Check(result.Panicked, Equals, 0)
c.Check(result.FixturePanicked, Equals, 0)
c.Check(result.Missed, Equals, 0)
c.Check(result.RunError, IsNil)
}
func (s *RunS) TestPanicOnTest(c *C) {
output := String{}
helper := &FixtureHelper{panicOn: "Test1"}
result := Run(helper, &RunConf{Output: &output})
c.Check(result.Succeeded, Equals, 1)
c.Check(result.Failed, Equals, 0)
c.Check(result.Skipped, Equals, 0)
c.Check(result.Panicked, Equals, 1)
c.Check(result.FixturePanicked, Equals, 0)
c.Check(result.Missed, Equals, 0)
c.Check(result.RunError, IsNil)
}
func (s *RunS) TestPanicOnSetUpTest(c *C) {
output := String{}
helper := &FixtureHelper{panicOn: "SetUpTest"}
result := Run(helper, &RunConf{Output: &output})
c.Check(result.Succeeded, Equals, 0)
c.Check(result.Failed, Equals, 0)
c.Check(result.Skipped, Equals, 0)
c.Check(result.Panicked, Equals, 0)
c.Check(result.FixturePanicked, Equals, 1)
c.Check(result.Missed, Equals, 2)
c.Check(result.RunError, IsNil)
}
func (s *RunS) TestPanicOnSetUpSuite(c *C) {
output := String{}
helper := &FixtureHelper{panicOn: "SetUpSuite"}
result := Run(helper, &RunConf{Output: &output})
c.Check(result.Succeeded, Equals, 0)
c.Check(result.Failed, Equals, 0)
c.Check(result.Skipped, Equals, 0)
c.Check(result.Panicked, Equals, 0)
c.Check(result.FixturePanicked, Equals, 1)
c.Check(result.Missed, Equals, 2)
c.Check(result.RunError, IsNil)
}
// -----------------------------------------------------------------------
// Check result aggregation.
func (s *RunS) TestAdd(c *C) {
result := &Result{
Succeeded: 1,
Skipped: 2,
Failed: 3,
Panicked: 4,
FixturePanicked: 5,
Missed: 6,
ExpectedFailures: 7,
}
result.Add(&Result{
Succeeded: 10,
Skipped: 20,
Failed: 30,
Panicked: 40,
FixturePanicked: 50,
Missed: 60,
ExpectedFailures: 70,
})
c.Check(result.Succeeded, Equals, 11)
c.Check(result.Skipped, Equals, 22)
c.Check(result.Failed, Equals, 33)
c.Check(result.Panicked, Equals, 44)
c.Check(result.FixturePanicked, Equals, 55)
c.Check(result.Missed, Equals, 66)
c.Check(result.ExpectedFailures, Equals, 77)
c.Check(result.RunError, IsNil)
}
// -----------------------------------------------------------------------
// Check the Passed() method.
func (s *RunS) TestPassed(c *C) {
c.Assert((&Result{}).Passed(), Equals, true)
c.Assert((&Result{Succeeded: 1}).Passed(), Equals, true)
c.Assert((&Result{Skipped: 1}).Passed(), Equals, true)
c.Assert((&Result{Failed: 1}).Passed(), Equals, false)
c.Assert((&Result{Panicked: 1}).Passed(), Equals, false)
c.Assert((&Result{FixturePanicked: 1}).Passed(), Equals, false)
c.Assert((&Result{Missed: 1}).Passed(), Equals, false)
c.Assert((&Result{RunError: errors.New("!")}).Passed(), Equals, false)
}
// -----------------------------------------------------------------------
// Check that result printing is working correctly.
func (s *RunS) TestPrintSuccess(c *C) {
result := &Result{Succeeded: 5}
c.Check(result.String(), Equals, "OK: 5 passed")
}
func (s *RunS) TestPrintFailure(c *C) {
result := &Result{Failed: 5}
c.Check(result.String(), Equals, "OOPS: 0 passed, 5 FAILED")
}
func (s *RunS) TestPrintSkipped(c *C) {
result := &Result{Skipped: 5}
c.Check(result.String(), Equals, "OK: 0 passed, 5 skipped")
}
func (s *RunS) TestPrintExpectedFailures(c *C) {
result := &Result{ExpectedFailures: 5}
c.Check(result.String(), Equals, "OK: 0 passed, 5 expected failures")
}
func (s *RunS) TestPrintPanicked(c *C) {
result := &Result{Panicked: 5}
c.Check(result.String(), Equals, "OOPS: 0 passed, 5 PANICKED")
}
func (s *RunS) TestPrintFixturePanicked(c *C) {
result := &Result{FixturePanicked: 5}
c.Check(result.String(), Equals, "OOPS: 0 passed, 5 FIXTURE-PANICKED")
}
func (s *RunS) TestPrintMissed(c *C) {
result := &Result{Missed: 5}
c.Check(result.String(), Equals, "OOPS: 0 passed, 5 MISSED")
}
func (s *RunS) TestPrintAll(c *C) {
result := &Result{Succeeded: 1, Skipped: 2, ExpectedFailures: 3,
Panicked: 4, FixturePanicked: 5, Missed: 6}
c.Check(result.String(), Equals,
"OOPS: 1 passed, 2 skipped, 3 expected failures, 4 PANICKED, "+
"5 FIXTURE-PANICKED, 6 MISSED")
}
func (s *RunS) TestPrintRunError(c *C) {
result := &Result{Succeeded: 1, Failed: 1,
RunError: errors.New("Kaboom!")}
c.Check(result.String(), Equals, "ERROR: Kaboom!")
}
// -----------------------------------------------------------------------
// Verify that the method pattern flag works correctly.
func (s *RunS) TestFilterTestName(c *C) {
helper := FixtureHelper{}
output := String{}
runConf := RunConf{Output: &output, Filter: "Test[91]"}
Run(&helper, &runConf)
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "Test1")
c.Check(helper.calls[3], Equals, "TearDownTest")
c.Check(helper.calls[4], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 5)
}
func (s *RunS) TestFilterTestNameWithAll(c *C) {
helper := FixtureHelper{}
output := String{}
runConf := RunConf{Output: &output, Filter: ".*"}
Run(&helper, &runConf)
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "Test1")
c.Check(helper.calls[3], Equals, "TearDownTest")
c.Check(helper.calls[4], Equals, "SetUpTest")
c.Check(helper.calls[5], Equals, "Test2")
c.Check(helper.calls[6], Equals, "TearDownTest")
c.Check(helper.calls[7], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 8)
}
func (s *RunS) TestFilterSuiteName(c *C) {
helper := FixtureHelper{}
output := String{}
runConf := RunConf{Output: &output, Filter: "FixtureHelper"}
Run(&helper, &runConf)
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "Test1")
c.Check(helper.calls[3], Equals, "TearDownTest")
c.Check(helper.calls[4], Equals, "SetUpTest")
c.Check(helper.calls[5], Equals, "Test2")
c.Check(helper.calls[6], Equals, "TearDownTest")
c.Check(helper.calls[7], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 8)
}
func (s *RunS) TestFilterSuiteNameAndTestName(c *C) {
helper := FixtureHelper{}
output := String{}
runConf := RunConf{Output: &output, Filter: "FixtureHelper\\.Test2"}
Run(&helper, &runConf)
c.Check(helper.calls[0], Equals, "SetUpSuite")
c.Check(helper.calls[1], Equals, "SetUpTest")
c.Check(helper.calls[2], Equals, "Test2")
c.Check(helper.calls[3], Equals, "TearDownTest")
c.Check(helper.calls[4], Equals, "TearDownSuite")
c.Check(len(helper.calls), Equals, 5)
}
func (s *RunS) TestFilterAllOut(c *C) {
helper := FixtureHelper{}
output := String{}
runConf := RunConf{Output: &output, Filter: "NotFound"}
Run(&helper, &runConf)
c.Check(len(helper.calls), Equals, 0)
}
func (s *RunS) TestRequirePartialMatch(c *C) {
helper := FixtureHelper{}
output := String{}
runConf := RunConf{Output: &output, Filter: "est"}
Run(&helper, &runConf)
c.Check(len(helper.calls), Equals, 8)
}
func (s *RunS) TestFilterError(c *C) {
helper := FixtureHelper{}
output := String{}
runConf := RunConf{Output: &output, Filter: "]["}
result := Run(&helper, &runConf)
c.Check(result.String(), Equals,
"ERROR: Bad filter expression: error parsing regexp: missing closing ]: `[`")
c.Check(len(helper.calls), Equals, 0)
}
// -----------------------------------------------------------------------
// Verify that List works correctly.
func (s *RunS) TestListFiltered(c *C) {
names := List(&FixtureHelper{}, &RunConf{Filter: "1"})
c.Assert(names, DeepEquals, []string{
"FixtureHelper.Test1",
})
}
func (s *RunS) TestList(c *C) {
names := List(&FixtureHelper{}, &RunConf{})
c.Assert(names, DeepEquals, []string{
"FixtureHelper.Test1",
"FixtureHelper.Test2",
})
}
// -----------------------------------------------------------------------
// Verify that verbose mode prints tests which pass as well.
func (s *RunS) TestVerboseMode(c *C) {
helper := FixtureHelper{}
output := String{}
runConf := RunConf{Output: &output, Verbose: true}
Run(&helper, &runConf)
expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test1\t *[.0-9]+s\n" +
"PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n"
c.Assert(output.value, Matches, expected)
}
func (s *RunS) TestVerboseModeWithFailBeforePass(c *C) {
helper := FixtureHelper{panicOn: "Test1"}
output := String{}
runConf := RunConf{Output: &output, Verbose: true}
Run(&helper, &runConf)
expected := "(?s).*PANIC.*\n-+\n" + // Should have an extra line.
"PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n"
c.Assert(output.value, Matches, expected)
}
// -----------------------------------------------------------------------
// Verify the stream output mode. In this mode there's no output caching.
type StreamHelper struct {
l2 sync.Mutex
l3 sync.Mutex
}
func (s *StreamHelper) SetUpSuite(c *C) {
c.Log("0")
}
func (s *StreamHelper) Test1(c *C) {
c.Log("1")
s.l2.Lock()
s.l3.Lock()
go func() {
s.l2.Lock() // Wait for "2".
c.Log("3")
s.l3.Unlock()
}()
}
func (s *StreamHelper) Test2(c *C) {
c.Log("2")
s.l2.Unlock()
s.l3.Lock() // Wait for "3".
c.Fail()
c.Log("4")
}
func (s *RunS) TestStreamMode(c *C) {
helper := &StreamHelper{}
output := String{}
runConf := RunConf{Output: &output, Stream: true}
Run(helper, &runConf)
expected := "START: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\n0\n" +
"PASS: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\t *[.0-9]+s\n\n" +
"START: run_test\\.go:[0-9]+: StreamHelper\\.Test1\n1\n" +
"PASS: run_test\\.go:[0-9]+: StreamHelper\\.Test1\t *[.0-9]+s\n\n" +
"START: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n2\n3\n4\n" +
"FAIL: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n\n"
c.Assert(output.value, Matches, expected)
}
type StreamMissHelper struct{}
func (s *StreamMissHelper) SetUpSuite(c *C) {
c.Log("0")
c.Fail()
}
func (s *StreamMissHelper) Test1(c *C) {
c.Log("1")
}
func (s *RunS) TestStreamModeWithMiss(c *C) {
helper := &StreamMissHelper{}
output := String{}
runConf := RunConf{Output: &output, Stream: true}
Run(helper, &runConf)
expected := "START: run_test\\.go:[0-9]+: StreamMissHelper\\.SetUpSuite\n0\n" +
"FAIL: run_test\\.go:[0-9]+: StreamMissHelper\\.SetUpSuite\n\n" +
"START: run_test\\.go:[0-9]+: StreamMissHelper\\.Test1\n" +
"MISS: run_test\\.go:[0-9]+: StreamMissHelper\\.Test1\n\n"
c.Assert(output.value, Matches, expected)
}
// -----------------------------------------------------------------------
// Verify that that the keep work dir request indeed does so.
type WorkDirSuite struct {}
func (s *WorkDirSuite) Test(c *C) {
c.MkDir()
}
func (s *RunS) TestKeepWorkDir(c *C) {
output := String{}
runConf := RunConf{Output: &output, Verbose: true, KeepWorkDir: true}
result := Run(&WorkDirSuite{}, &runConf)
c.Assert(result.String(), Matches, ".*\nWORK=" + result.WorkDir)
stat, err := os.Stat(result.WorkDir)
c.Assert(err, IsNil)
c.Assert(stat.IsDir(), Equals, true)
}