1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

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)
}
type b struct {
body []byte
err error
status int
body []byte
err error
}
bc := make(chan b, 1)
go func() {
status, body, err := sockRequest("GET", "/containers/"+name+"/stats", nil)
c.Assert(status, check.Equals, http.StatusOK)
c.Assert(err, check.IsNil)
bc <- b{body, err}
bc <- b{status, body, err}
}()
// 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):
c.Fatal("stream was not closed after container was removed")
case sr := <-bc:
if sr.err != nil {
c.Fatal(sr.err)
}
c.Assert(sr.err, check.IsNil)
c.Assert(sr.status, check.Equals, http.StatusOK)
dec := json.NewDecoder(bytes.NewBuffer(sr.body))
var s *types.Stats
@ -297,6 +295,7 @@ func (s *DockerSuite) TestGetContainerStats(c *check.C) {
}
func (s *DockerSuite) TestGetStoppedContainerStats(c *check.C) {
// TODO: this test does nothing because we are c.Assert'ing in goroutine
var (
name = "statscontainer"
runCmd = exec.Command(dockerBinary, "create", "--name", name, "busybox", "top")

View file

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

View file

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

View file

@ -15,7 +15,6 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"text/template"
"time"
@ -764,17 +763,17 @@ ADD test_file .`,
}
defer ctx.Close()
done := make(chan struct{})
errChan := make(chan error)
go func() {
if _, err := buildImageFromContext(name, ctx, true); err != nil {
c.Fatal(err)
}
close(done)
_, err := buildImageFromContext(name, ctx, true)
errChan <- err
close(errChan)
}()
select {
case <-time.After(5 * time.Second):
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()
done := make(chan struct{})
errChan := make(chan error)
go func() {
if _, err := buildImageFromContext(name, ctx, true); err != nil {
c.Fatal(err)
}
close(done)
_, err := buildImageFromContext(name, ctx, true)
errChan <- err
close(errChan)
}()
select {
case <-time.After(5 * time.Second):
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
// * Wait for docker events to emit a dying event.
func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
var wg sync.WaitGroup
defer wg.Wait()
name := "testbuildcancelation"
// (Note: one year, will never finish)
@ -1849,26 +1845,21 @@ func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
containerID := make(chan string)
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`
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
matchStart := regexp.MustCompile(cid + `(.*) start$`)
@ -1886,19 +1877,13 @@ func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
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.Dir = ctx.Dir
stdoutBuild, err := buildCmd.StdoutPipe()
err = buildCmd.Start()
if err != nil {
if err := buildCmd.Start(); err != nil {
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.
// Causes the underlying build to be cancelled due to socket close.
err = buildCmd.Process.Kill()
if err != nil {
if err := buildCmd.Process.Kill(); err != nil {
c.Fatalf("error killing build command: %s", err)
}
// Get the exit status of `docker build`, check it exited because killed.
err = buildCmd.Wait()
if err != nil && !IsKilled(err) {
if err := buildCmd.Wait(); err != nil && !IsKilled(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)
go func() {
defer waitGroup.Done()
err := exec.Command(dockerBinary, args...).Run()
errChan <- err
errChan <- exec.Command(dockerBinary, args...).Run()
}()
}
@ -229,8 +228,7 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) {
if err != nil {
c.Fatal(err)
}
err = eventsCmd.Start()
if err != nil {
if err := eventsCmd.Start(); err != nil {
c.Fatal(err)
}
defer eventsCmd.Process.Kill()
@ -424,30 +422,23 @@ func (s *DockerSuite) TestEventsFilterContainer(c *check.C) {
func (s *DockerSuite) TestEventsStreaming(c *check.C) {
start := daemonTime(c).Unix()
finish := make(chan struct{})
defer close(finish)
id := make(chan string)
eventCreate := make(chan struct{})
eventStart := make(chan struct{})
eventDie := 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() {
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
matchCreate := regexp.MustCompile(containerID + `: \(from busybox:latest\) create$`)
@ -468,11 +459,6 @@ func (s *DockerSuite) TestEventsStreaming(c *check.C) {
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")
@ -516,5 +502,4 @@ func (s *DockerSuite) TestEventsStreaming(c *check.C) {
case <-eventDestroy:
// ignore, done
}
}

View file

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

View file

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

View file

@ -255,7 +255,6 @@ func assertContainerList(out string, expected []string) bool {
}
func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "hello")
runCommandWithOutput(cmd)
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.Add(2)
errChan := make(chan error, 2)
for i := 0; i < 2; i++ {
go func() {
defer group.Done()
cmd := exec.Command(dockerBinary, "run", "busybox", "sleep", "2")
if _, err := runCommand(cmd); err != nil {
c.Fatal(err)
}
_, err := runCommand(cmd)
errChan <- err
}()
}
group.Wait()
close(errChan)
for err := range errChan {
c.Assert(err, check.IsNil)
}
}
func (s *DockerSuite) TestRunEnvironment(c *check.C) {
@ -1851,22 +1856,20 @@ func (s *DockerSuite) TestRunExitOnStdinClose(c *check.C) {
if err := stdin.Close(); err != nil {
c.Fatal(err)
}
finish := make(chan struct{})
finish := make(chan error)
go func() {
if err := runCmd.Wait(); err != nil {
c.Fatal(err)
}
finish <- runCmd.Wait()
close(finish)
}()
select {
case <-finish:
case err := <-finish:
c.Assert(err, check.IsNil)
case <-time.After(1 * time.Second):
c.Fatal("docker run failed to exit on stdin close")
}
state, err := inspectField(name, "State.Running")
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
if state != "false" {
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) {
done := make(chan struct{})
errChan := make(chan error)
go func() {
defer close(done)
defer close(errChan)
cmd := exec.Command(dockerBinary, "run", "-ti", "busybox", "true")
if _, err := cmd.StdinPipe(); err != nil {
c.Fatal(err)
errChan <- err
return
}
expected := "cannot enable tty mode"
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) {
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 {
case <-done:
case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(3 * time.Second):
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) {
done := make(chan struct{})
errChan := make(chan error)
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")
out, exitCode, _ := runCommandWithOutput(runCmd)
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 {
case <-done:
case err := <-errChan:
c.Assert(err, check.IsNil)
case <-time.After(30 * time.Second):
c.Fatal("Timeout waiting for container to die on OOM")
}
@ -3030,9 +3037,7 @@ func (s *DockerSuite) TestRunPidHostWithChildIsKillable(c *check.C) {
}()
select {
case err := <-errchan:
if err != nil {
c.Fatal(err)
}
c.Assert(err, check.IsNil)
case <-time.After(5 * time.Second):
c.Fatal("Kill container timed out")
}

View file

@ -29,21 +29,22 @@ func (s *DockerSuite) TestRunRedirectStdout(c *check.C) {
cmd.Stdin = tty
cmd.Stdout = tty
cmd.Stderr = tty
ch := make(chan struct{})
if err := cmd.Start(); err != nil {
c.Fatalf("start err: %v", err)
}
ch := make(chan error)
go func() {
if err := cmd.Wait(); err != nil {
c.Fatalf("wait err=%v", err)
}
ch <- cmd.Wait()
close(ch)
}()
select {
case <-time.After(10 * time.Second):
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")
}
ch := make(chan struct{})
ch := make(chan error)
go func() {
// 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 {
c.Fatal("Expected error but got none")
ch <- fmt.Errorf("Expected error but got none")
}
close(ch)
}()
select {
case <-ch:
case err := <-ch:
c.Assert(err, check.IsNil)
case <-time.After(time.Second):
c.Fatalf("Attach did not exit properly")
}