c.Fatal won't fail and exit test inside a goroutine, errors should be handled outside with a channel

Signed-off-by: Antonio Murdaca <me@runcom.ninja>
This commit is contained in:
Antonio Murdaca 2015-04-27 19:29:48 +02:00
parent f2f8e4c5c9
commit 4203230cbb
11 changed files with 156 additions and 169 deletions

View File

@ -260,15 +260,14 @@ func (s *DockerSuite) TestGetContainerStats(c *check.C) {
c.Fatalf("Error on container creation: %v, output: %q", err, out) c.Fatalf("Error on container creation: %v, output: %q", err, out)
} }
type b struct { type b struct {
body []byte status int
err error body []byte
err error
} }
bc := make(chan b, 1) bc := make(chan b, 1)
go func() { go func() {
status, body, err := sockRequest("GET", "/containers/"+name+"/stats", nil) status, body, err := sockRequest("GET", "/containers/"+name+"/stats", nil)
c.Assert(status, check.Equals, http.StatusOK) bc <- b{status, body, err}
c.Assert(err, check.IsNil)
bc <- b{body, err}
}() }()
// allow some time to stream the stats from the container // allow some time to stream the stats from the container
@ -283,9 +282,8 @@ func (s *DockerSuite) TestGetContainerStats(c *check.C) {
case <-time.After(2 * time.Second): case <-time.After(2 * time.Second):
c.Fatal("stream was not closed after container was removed") c.Fatal("stream was not closed after container was removed")
case sr := <-bc: case sr := <-bc:
if sr.err != nil { c.Assert(sr.err, check.IsNil)
c.Fatal(sr.err) c.Assert(sr.status, check.Equals, http.StatusOK)
}
dec := json.NewDecoder(bytes.NewBuffer(sr.body)) dec := json.NewDecoder(bytes.NewBuffer(sr.body))
var s *types.Stats var s *types.Stats
@ -297,6 +295,7 @@ func (s *DockerSuite) TestGetContainerStats(c *check.C) {
} }
func (s *DockerSuite) TestGetStoppedContainerStats(c *check.C) { func (s *DockerSuite) TestGetStoppedContainerStats(c *check.C) {
// TODO: this test does nothing because we are c.Assert'ing in goroutine
var ( var (
name = "statscontainer" name = "statscontainer"
runCmd = exec.Command(dockerBinary, "create", "--name", name, "busybox", "top") runCmd = exec.Command(dockerBinary, "create", "--name", name, "busybox", "top")

View File

@ -2,6 +2,7 @@ package main
import ( import (
"bufio" "bufio"
"fmt"
"io" "io"
"os/exec" "os/exec"
"strings" "strings"
@ -89,7 +90,6 @@ func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
} }
func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) { func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "-ti", "busybox") cmd := exec.Command(dockerBinary, "run", "-d", "-ti", "busybox")
out, _, err := runCommandWithOutput(cmd) out, _, err := runCommandWithOutput(cmd)
if err != nil { if err != nil {
@ -108,29 +108,32 @@ func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
} }
}() }()
done := make(chan struct{}) done := make(chan error)
go func() { go func() {
defer close(done) defer close(done)
cmd := exec.Command(dockerBinary, "attach", id) cmd := exec.Command(dockerBinary, "attach", id)
if _, err := cmd.StdinPipe(); err != nil { if _, err := cmd.StdinPipe(); err != nil {
c.Fatal(err) done <- err
return
} }
expected := "cannot enable tty mode" expected := "cannot enable tty mode"
if out, _, err := runCommandWithOutput(cmd); err == nil { if out, _, err := runCommandWithOutput(cmd); err == nil {
c.Fatal("attach should have failed") done <- fmt.Errorf("attach should have failed")
return
} else if !strings.Contains(out, expected) { } else if !strings.Contains(out, expected) {
c.Fatalf("attach failed with error %q: expected %q", out, expected) done <- fmt.Errorf("attach failed with error %q: expected %q", out, expected)
return
} }
}() }()
select { select {
case <-done: case err := <-done:
c.Assert(err, check.IsNil)
case <-time.After(attachWait): case <-time.After(attachWait):
c.Fatal("attach is running but should have failed") c.Fatal("attach is running but should have failed")
} }
} }
func (s *DockerSuite) TestAttachDisconnect(c *check.C) { func (s *DockerSuite) TestAttachDisconnect(c *check.C) {

View File

@ -27,14 +27,14 @@ func (s *DockerSuite) TestAttachClosedOnContainerStop(c *check.C) {
c.Fatal(err) c.Fatal(err)
} }
done := make(chan struct{}) errChan := make(chan error)
go func() { go func() {
defer close(done) defer close(errChan)
_, tty, err := pty.Open() _, tty, err := pty.Open()
if err != nil { if err != nil {
c.Fatalf("could not open pty: %v", err) errChan <- err
return
} }
attachCmd := exec.Command(dockerBinary, "attach", id) attachCmd := exec.Command(dockerBinary, "attach", id)
attachCmd.Stdin = tty attachCmd.Stdin = tty
@ -42,7 +42,8 @@ func (s *DockerSuite) TestAttachClosedOnContainerStop(c *check.C) {
attachCmd.Stderr = tty attachCmd.Stderr = tty
if err := attachCmd.Run(); err != nil { if err := attachCmd.Run(); err != nil {
c.Fatalf("attach returned error %s", err) errChan <- err
return
} }
}() }()
@ -51,7 +52,8 @@ func (s *DockerSuite) TestAttachClosedOnContainerStop(c *check.C) {
c.Fatalf("error thrown while waiting for container: %s, %v", out, err) c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
} }
select { select {
case <-done: case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(attachWait): case <-time.After(attachWait):
c.Fatal("timed out without attach returning") c.Fatal("timed out without attach returning")
} }
@ -71,12 +73,10 @@ func (s *DockerSuite) TestAttachAfterDetach(c *check.C) {
cmd.Stdout = tty cmd.Stdout = tty
cmd.Stderr = tty cmd.Stderr = tty
detached := make(chan struct{}) errChan := make(chan error)
go func() { go func() {
if err := cmd.Run(); err != nil { errChan <- cmd.Run()
c.Fatalf("attach returned error %s", err) close(errChan)
}
close(detached)
}() }()
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
@ -87,7 +87,12 @@ func (s *DockerSuite) TestAttachAfterDetach(c *check.C) {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
cpty.Write([]byte{17}) cpty.Write([]byte{17})
<-detached select {
case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(5 * time.Second):
c.Fatal("timeout while detaching")
}
cpty, tty, err = pty.Open() cpty, tty, err = pty.Open()
if err != nil { if err != nil {
@ -119,9 +124,7 @@ func (s *DockerSuite) TestAttachAfterDetach(c *check.C) {
select { select {
case err := <-readErr: case err := <-readErr:
if err != nil { c.Assert(err, check.IsNil)
c.Fatal(err)
}
case <-time.After(2 * time.Second): case <-time.After(2 * time.Second):
c.Fatal("timeout waiting for attach read") c.Fatal("timeout waiting for attach read")
} }

View File

@ -15,7 +15,6 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"sync"
"text/template" "text/template"
"time" "time"
@ -764,17 +763,17 @@ ADD test_file .`,
} }
defer ctx.Close() defer ctx.Close()
done := make(chan struct{}) errChan := make(chan error)
go func() { go func() {
if _, err := buildImageFromContext(name, ctx, true); err != nil { _, err := buildImageFromContext(name, ctx, true)
c.Fatal(err) errChan <- err
} close(errChan)
close(done)
}() }()
select { select {
case <-time.After(5 * time.Second): case <-time.After(5 * time.Second):
c.Fatal("Build with adding to workdir timed out") c.Fatal("Build with adding to workdir timed out")
case <-done: case err := <-errChan:
c.Assert(err, check.IsNil)
} }
} }
@ -1365,17 +1364,17 @@ COPY test_file .`,
} }
defer ctx.Close() defer ctx.Close()
done := make(chan struct{}) errChan := make(chan error)
go func() { go func() {
if _, err := buildImageFromContext(name, ctx, true); err != nil { _, err := buildImageFromContext(name, ctx, true)
c.Fatal(err) errChan <- err
} close(errChan)
close(done)
}() }()
select { select {
case <-time.After(5 * time.Second): case <-time.After(5 * time.Second):
c.Fatal("Build with adding to workdir timed out") c.Fatal("Build with adding to workdir timed out")
case <-done: case err := <-errChan:
c.Assert(err, check.IsNil)
} }
} }
@ -1829,9 +1828,6 @@ func (s *DockerSuite) TestBuildForceRm(c *check.C) {
// * When docker events sees container start, close the "docker build" command // * When docker events sees container start, close the "docker build" command
// * Wait for docker events to emit a dying event. // * Wait for docker events to emit a dying event.
func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) { func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
var wg sync.WaitGroup
defer wg.Wait()
name := "testbuildcancelation" name := "testbuildcancelation"
// (Note: one year, will never finish) // (Note: one year, will never finish)
@ -1849,26 +1845,21 @@ func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
containerID := make(chan string) containerID := make(chan string)
startEpoch := daemonTime(c).Unix() startEpoch := daemonTime(c).Unix()
// Watch for events since epoch.
eventsCmd := exec.Command(
dockerBinary, "events",
"--since", strconv.FormatInt(startEpoch, 10))
stdout, err := eventsCmd.StdoutPipe()
if err != nil {
c.Fatal(err)
}
if err := eventsCmd.Start(); err != nil {
c.Fatal(err)
}
defer eventsCmd.Process.Kill()
wg.Add(1)
// Goroutine responsible for watching start/die events from `docker events` // Goroutine responsible for watching start/die events from `docker events`
go func() { go func() {
defer wg.Done()
// Watch for events since epoch.
eventsCmd := exec.Command(
dockerBinary, "events",
"--since", strconv.FormatInt(startEpoch, 10))
stdout, err := eventsCmd.StdoutPipe()
err = eventsCmd.Start()
if err != nil {
c.Fatalf("failed to start 'docker events': %s", err)
}
go func() {
<-finish
eventsCmd.Process.Kill()
}()
cid := <-containerID cid := <-containerID
matchStart := regexp.MustCompile(cid + `(.*) start$`) matchStart := regexp.MustCompile(cid + `(.*) start$`)
@ -1886,19 +1877,13 @@ func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
close(eventDie) close(eventDie)
} }
} }
err = eventsCmd.Wait()
if err != nil && !IsKilled(err) {
c.Fatalf("docker events had bad exit status: %s", err)
}
}() }()
buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".") buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".")
buildCmd.Dir = ctx.Dir buildCmd.Dir = ctx.Dir
stdoutBuild, err := buildCmd.StdoutPipe() stdoutBuild, err := buildCmd.StdoutPipe()
err = buildCmd.Start() if err := buildCmd.Start(); err != nil {
if err != nil {
c.Fatalf("failed to run build: %s", err) c.Fatalf("failed to run build: %s", err)
} }
@ -1923,14 +1908,12 @@ func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
// Send a kill to the `docker build` command. // Send a kill to the `docker build` command.
// Causes the underlying build to be cancelled due to socket close. // Causes the underlying build to be cancelled due to socket close.
err = buildCmd.Process.Kill() if err := buildCmd.Process.Kill(); err != nil {
if err != nil {
c.Fatalf("error killing build command: %s", err) c.Fatalf("error killing build command: %s", err)
} }
// Get the exit status of `docker build`, check it exited because killed. // Get the exit status of `docker build`, check it exited because killed.
err = buildCmd.Wait() if err := buildCmd.Wait(); err != nil && !IsKilled(err) {
if err != nil && !IsKilled(err) {
c.Fatalf("wait failed during build run: %T %s", err, err) c.Fatalf("wait failed during build run: %T %s", err, err)
} }

View File

@ -75,8 +75,7 @@ func (s *DockerSuite) TestEventsLimit(c *check.C) {
waitGroup.Add(1) waitGroup.Add(1)
go func() { go func() {
defer waitGroup.Done() defer waitGroup.Done()
err := exec.Command(dockerBinary, args...).Run() errChan <- exec.Command(dockerBinary, args...).Run()
errChan <- err
}() }()
} }
@ -229,8 +228,7 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) {
if err != nil { if err != nil {
c.Fatal(err) c.Fatal(err)
} }
err = eventsCmd.Start() if err := eventsCmd.Start(); err != nil {
if err != nil {
c.Fatal(err) c.Fatal(err)
} }
defer eventsCmd.Process.Kill() defer eventsCmd.Process.Kill()
@ -424,30 +422,23 @@ func (s *DockerSuite) TestEventsFilterContainer(c *check.C) {
func (s *DockerSuite) TestEventsStreaming(c *check.C) { func (s *DockerSuite) TestEventsStreaming(c *check.C) {
start := daemonTime(c).Unix() start := daemonTime(c).Unix()
finish := make(chan struct{})
defer close(finish)
id := make(chan string) id := make(chan string)
eventCreate := make(chan struct{}) eventCreate := make(chan struct{})
eventStart := make(chan struct{}) eventStart := make(chan struct{})
eventDie := make(chan struct{}) eventDie := make(chan struct{})
eventDestroy := make(chan struct{}) eventDestroy := make(chan struct{})
eventsCmd := exec.Command(dockerBinary, "events", "--since", strconv.FormatInt(start, 10))
stdout, err := eventsCmd.StdoutPipe()
if err != nil {
c.Fatal(err)
}
if err := eventsCmd.Start(); err != nil {
c.Fatalf("failed to start 'docker events': %s", err)
}
defer eventsCmd.Process.Kill()
go func() { go func() {
eventsCmd := exec.Command(dockerBinary, "events", "--since", strconv.FormatInt(start, 10))
stdout, err := eventsCmd.StdoutPipe()
if err != nil {
c.Fatal(err)
}
err = eventsCmd.Start()
if err != nil {
c.Fatalf("failed to start 'docker events': %s", err)
}
go func() {
<-finish
eventsCmd.Process.Kill()
}()
containerID := <-id containerID := <-id
matchCreate := regexp.MustCompile(containerID + `: \(from busybox:latest\) create$`) matchCreate := regexp.MustCompile(containerID + `: \(from busybox:latest\) create$`)
@ -468,11 +459,6 @@ func (s *DockerSuite) TestEventsStreaming(c *check.C) {
close(eventDestroy) close(eventDestroy)
} }
} }
err = eventsCmd.Wait()
if err != nil && !IsKilled(err) {
c.Fatalf("docker events had bad exit status: %s", err)
}
}() }()
runCmd := exec.Command(dockerBinary, "run", "-d", "busybox:latest", "true") runCmd := exec.Command(dockerBinary, "run", "-d", "busybox:latest", "true")
@ -516,5 +502,4 @@ func (s *DockerSuite) TestEventsStreaming(c *check.C) {
case <-eventDestroy: case <-eventDestroy:
// ignore, done // ignore, done
} }
} }

View File

@ -74,15 +74,14 @@ func (s *DockerSuite) TestExecInteractive(c *check.C) {
if err := stdin.Close(); err != nil { if err := stdin.Close(); err != nil {
c.Fatal(err) c.Fatal(err)
} }
finish := make(chan struct{}) errChan := make(chan error)
go func() { go func() {
if err := execCmd.Wait(); err != nil { errChan <- execCmd.Wait()
c.Fatal(err) close(errChan)
}
close(finish)
}() }()
select { select {
case <-finish: case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
c.Fatal("docker exec failed to exit on stdin close") c.Fatal("docker exec failed to exit on stdin close")
} }
@ -278,25 +277,29 @@ func (s *DockerSuite) TestExecTtyWithoutStdin(c *check.C) {
} }
}() }()
done := make(chan struct{}) errChan := make(chan error)
go func() { go func() {
defer close(done) defer close(errChan)
cmd := exec.Command(dockerBinary, "exec", "-ti", id, "true") cmd := exec.Command(dockerBinary, "exec", "-ti", id, "true")
if _, err := cmd.StdinPipe(); err != nil { if _, err := cmd.StdinPipe(); err != nil {
c.Fatal(err) errChan <- err
return
} }
expected := "cannot enable tty mode" expected := "cannot enable tty mode"
if out, _, err := runCommandWithOutput(cmd); err == nil { if out, _, err := runCommandWithOutput(cmd); err == nil {
c.Fatal("exec should have failed") errChan <- fmt.Errorf("exec should have failed")
return
} else if !strings.Contains(out, expected) { } else if !strings.Contains(out, expected) {
c.Fatalf("exec failed with error %q: expected %q", out, expected) errChan <- fmt.Errorf("exec failed with error %q: expected %q", out, expected)
return
} }
}() }()
select { select {
case <-done: case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(3 * time.Second): case <-time.After(3 * time.Second):
c.Fatal("exec is running but should have failed") c.Fatal("exec is running but should have failed")
} }
@ -326,17 +329,22 @@ func (s *DockerSuite) TestExecStopNotHanging(c *check.C) {
c.Fatal(err) c.Fatal(err)
} }
wait := make(chan struct{}) type dstop struct {
out []byte
err error
}
ch := make(chan dstop)
go func() { go func() {
if out, err := exec.Command(dockerBinary, "stop", "testing").CombinedOutput(); err != nil { out, err := exec.Command(dockerBinary, "stop", "testing").CombinedOutput()
c.Fatal(out, err) ch <- dstop{out, err}
} close(ch)
close(wait)
}() }()
select { select {
case <-time.After(3 * time.Second): case <-time.After(3 * time.Second):
c.Fatal("Container stop timed out") c.Fatal("Container stop timed out")
case <-wait: case s := <-ch:
c.Assert(s.err, check.IsNil)
} }
} }
@ -359,6 +367,7 @@ func (s *DockerSuite) TestExecCgroup(c *check.C) {
var wg sync.WaitGroup var wg sync.WaitGroup
var mu sync.Mutex var mu sync.Mutex
execCgroups := []sort.StringSlice{} execCgroups := []sort.StringSlice{}
errChan := make(chan error)
// exec a few times concurrently to get consistent failure // exec a few times concurrently to get consistent failure
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
wg.Add(1) wg.Add(1)
@ -366,7 +375,8 @@ func (s *DockerSuite) TestExecCgroup(c *check.C) {
cmd := exec.Command(dockerBinary, "exec", "testing", "cat", "/proc/self/cgroup") cmd := exec.Command(dockerBinary, "exec", "testing", "cat", "/proc/self/cgroup")
out, _, err := runCommandWithOutput(cmd) out, _, err := runCommandWithOutput(cmd)
if err != nil { if err != nil {
c.Fatal(out, err) errChan <- err
return
} }
cg := sort.StringSlice(strings.Split(string(out), "\n")) cg := sort.StringSlice(strings.Split(string(out), "\n"))
@ -377,6 +387,11 @@ func (s *DockerSuite) TestExecCgroup(c *check.C) {
}() }()
} }
wg.Wait() wg.Wait()
close(errChan)
for err := range errChan {
c.Assert(err, check.IsNil)
}
for _, cg := range execCgroups { for _, cg := range execCgroups {
if !reflect.DeepEqual(cg, containerCgroups) { if !reflect.DeepEqual(cg, containerCgroups) {

View File

@ -260,16 +260,15 @@ func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
c.Fatal(err) c.Fatal(err)
} }
ch := make(chan struct{}) errChan := make(chan error)
go func() { go func() {
if err := logsCmd.Wait(); err != nil { errChan <- logsCmd.Wait()
c.Fatal(err) close(errChan)
}
close(ch)
}() }()
select { select {
case <-ch: case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
c.Fatal("Following logs is hanged") c.Fatal("Following logs is hanged")
} }
@ -298,9 +297,7 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
logCmd := exec.Command(dockerBinary, "logs", "-f", cleanedContainerID) logCmd := exec.Command(dockerBinary, "logs", "-f", cleanedContainerID)
stdout, err := logCmd.StdoutPipe() stdout, err := logCmd.StdoutPipe()
if err != nil { c.Assert(err, check.IsNil)
c.Fatal(err)
}
if err := logCmd.Start(); err != nil { if err := logCmd.Start(); err != nil {
c.Fatal(err) c.Fatal(err)
@ -308,15 +305,11 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
// First read slowly // First read slowly
bytes1, err := consumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead) bytes1, err := consumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead)
if err != nil { c.Assert(err, check.IsNil)
c.Fatal(err)
}
// After the container has finished we can continue reading fast // After the container has finished we can continue reading fast
bytes2, err := consumeWithSpeed(stdout, 32*1024, 0, nil) bytes2, err := consumeWithSpeed(stdout, 32*1024, 0, nil)
if err != nil { c.Assert(err, check.IsNil)
c.Fatal(err)
}
actual := bytes1 + bytes2 actual := bytes1 + bytes2
expected := 200000 expected := 200000

View File

@ -255,7 +255,6 @@ func assertContainerList(out string, expected []string) bool {
} }
func (s *DockerSuite) TestPsListContainersSize(c *check.C) { func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "hello") cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "hello")
runCommandWithOutput(cmd) runCommandWithOutput(cmd)
cmd = exec.Command(dockerBinary, "ps", "-s", "-n=1") cmd = exec.Command(dockerBinary, "ps", "-s", "-n=1")

View File

@ -756,17 +756,22 @@ func (s *DockerSuite) TestRunTwoConcurrentContainers(c *check.C) {
group := sync.WaitGroup{} group := sync.WaitGroup{}
group.Add(2) group.Add(2)
errChan := make(chan error, 2)
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
go func() { go func() {
defer group.Done() defer group.Done()
cmd := exec.Command(dockerBinary, "run", "busybox", "sleep", "2") cmd := exec.Command(dockerBinary, "run", "busybox", "sleep", "2")
if _, err := runCommand(cmd); err != nil { _, err := runCommand(cmd)
c.Fatal(err) errChan <- err
}
}() }()
} }
group.Wait() group.Wait()
close(errChan)
for err := range errChan {
c.Assert(err, check.IsNil)
}
} }
func (s *DockerSuite) TestRunEnvironment(c *check.C) { func (s *DockerSuite) TestRunEnvironment(c *check.C) {
@ -1851,22 +1856,20 @@ func (s *DockerSuite) TestRunExitOnStdinClose(c *check.C) {
if err := stdin.Close(); err != nil { if err := stdin.Close(); err != nil {
c.Fatal(err) c.Fatal(err)
} }
finish := make(chan struct{}) finish := make(chan error)
go func() { go func() {
if err := runCmd.Wait(); err != nil { finish <- runCmd.Wait()
c.Fatal(err)
}
close(finish) close(finish)
}() }()
select { select {
case <-finish: case err := <-finish:
c.Assert(err, check.IsNil)
case <-time.After(1 * time.Second): case <-time.After(1 * time.Second):
c.Fatal("docker run failed to exit on stdin close") c.Fatal("docker run failed to exit on stdin close")
} }
state, err := inspectField(name, "State.Running") state, err := inspectField(name, "State.Running")
if err != nil { c.Assert(err, check.IsNil)
c.Fatal(err)
}
if state != "false" { if state != "false" {
c.Fatal("Container must be stopped after stdin closing") c.Fatal("Container must be stopped after stdin closing")
} }
@ -2762,25 +2765,29 @@ func (s *DockerSuite) TestRunPortFromDockerRangeInUse(c *check.C) {
} }
func (s *DockerSuite) TestRunTtyWithPipe(c *check.C) { func (s *DockerSuite) TestRunTtyWithPipe(c *check.C) {
done := make(chan struct{}) errChan := make(chan error)
go func() { go func() {
defer close(done) defer close(errChan)
cmd := exec.Command(dockerBinary, "run", "-ti", "busybox", "true") cmd := exec.Command(dockerBinary, "run", "-ti", "busybox", "true")
if _, err := cmd.StdinPipe(); err != nil { if _, err := cmd.StdinPipe(); err != nil {
c.Fatal(err) errChan <- err
return
} }
expected := "cannot enable tty mode" expected := "cannot enable tty mode"
if out, _, err := runCommandWithOutput(cmd); err == nil { if out, _, err := runCommandWithOutput(cmd); err == nil {
c.Fatal("run should have failed") errChan <- fmt.Errorf("run should have failed")
return
} else if !strings.Contains(out, expected) { } else if !strings.Contains(out, expected) {
c.Fatalf("run failed with error %q: expected %q", out, expected) errChan <- fmt.Errorf("run failed with error %q: expected %q", out, expected)
return
} }
}() }()
select { select {
case <-done: case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(3 * time.Second): case <-time.After(3 * time.Second):
c.Fatal("container is running but should have failed") c.Fatal("container is running but should have failed")
} }
@ -2875,19 +2882,19 @@ func (s *DockerSuite) TestRunAllowPortRangeThroughPublish(c *check.C) {
} }
func (s *DockerSuite) TestRunOOMExitCode(c *check.C) { func (s *DockerSuite) TestRunOOMExitCode(c *check.C) {
done := make(chan struct{}) errChan := make(chan error)
go func() { go func() {
defer close(done) defer close(errChan)
runCmd := exec.Command(dockerBinary, "run", "-m", "4MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done") runCmd := exec.Command(dockerBinary, "run", "-m", "4MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done")
out, exitCode, _ := runCommandWithOutput(runCmd) out, exitCode, _ := runCommandWithOutput(runCmd)
if expected := 137; exitCode != expected { if expected := 137; exitCode != expected {
c.Fatalf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out) errChan <- fmt.Errorf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out)
} }
}() }()
select { select {
case <-done: case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(30 * time.Second): case <-time.After(30 * time.Second):
c.Fatal("Timeout waiting for container to die on OOM") c.Fatal("Timeout waiting for container to die on OOM")
} }
@ -3030,9 +3037,7 @@ func (s *DockerSuite) TestRunPidHostWithChildIsKillable(c *check.C) {
}() }()
select { select {
case err := <-errchan: case err := <-errchan:
if err != nil { c.Assert(err, check.IsNil)
c.Fatal(err)
}
case <-time.After(5 * time.Second): case <-time.After(5 * time.Second):
c.Fatal("Kill container timed out") c.Fatal("Kill container timed out")
} }

View File

@ -29,21 +29,22 @@ func (s *DockerSuite) TestRunRedirectStdout(c *check.C) {
cmd.Stdin = tty cmd.Stdin = tty
cmd.Stdout = tty cmd.Stdout = tty
cmd.Stderr = tty cmd.Stderr = tty
ch := make(chan struct{})
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
c.Fatalf("start err: %v", err) c.Fatalf("start err: %v", err)
} }
ch := make(chan error)
go func() { go func() {
if err := cmd.Wait(); err != nil { ch <- cmd.Wait()
c.Fatalf("wait err=%v", err)
}
close(ch) close(ch)
}() }()
select { select {
case <-time.After(10 * time.Second): case <-time.After(10 * time.Second):
c.Fatal("command timeout") c.Fatal("command timeout")
case <-ch: case err := <-ch:
if err != nil {
c.Fatalf("wait err=%v", err)
}
} }
} }

View File

@ -20,18 +20,19 @@ func (s *DockerSuite) TestStartAttachReturnsOnError(c *check.C) {
c.Fatal("Expected error but got none") c.Fatal("Expected error but got none")
} }
ch := make(chan struct{}) ch := make(chan error)
go func() { go func() {
// Attempt to start attached to the container that won't start // Attempt to start attached to the container that won't start
// This should return an error immediately since the container can't be started // This should return an error immediately since the container can't be started
if _, err := runCommand(exec.Command(dockerBinary, "start", "-a", "test2")); err == nil { if _, err := runCommand(exec.Command(dockerBinary, "start", "-a", "test2")); err == nil {
c.Fatal("Expected error but got none") ch <- fmt.Errorf("Expected error but got none")
} }
close(ch) close(ch)
}() }()
select { select {
case <-ch: case err := <-ch:
c.Assert(err, check.IsNil)
case <-time.After(time.Second): case <-time.After(time.Second):
c.Fatalf("Attach did not exit properly") c.Fatalf("Attach did not exit properly")
} }