Browse code

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>

Antonio Murdaca authored on 2015/04/28 02:29:48
Showing 11 changed files
... ...
@@ -260,15 +260,14 @@ func (s *DockerSuite) TestGetContainerStats(c *check.C) {
260 260
 		c.Fatalf("Error on container creation: %v, output: %q", err, out)
261 261
 	}
262 262
 	type b struct {
263
-		body []byte
264
-		err  error
263
+		status int
264
+		body   []byte
265
+		err    error
265 266
 	}
266 267
 	bc := make(chan b, 1)
267 268
 	go func() {
268 269
 		status, body, err := sockRequest("GET", "/containers/"+name+"/stats", nil)
269
-		c.Assert(status, check.Equals, http.StatusOK)
270
-		c.Assert(err, check.IsNil)
271
-		bc <- b{body, err}
270
+		bc <- b{status, body, err}
272 271
 	}()
273 272
 
274 273
 	// allow some time to stream the stats from the container
... ...
@@ -283,9 +282,8 @@ func (s *DockerSuite) TestGetContainerStats(c *check.C) {
283 283
 	case <-time.After(2 * time.Second):
284 284
 		c.Fatal("stream was not closed after container was removed")
285 285
 	case sr := <-bc:
286
-		if sr.err != nil {
287
-			c.Fatal(sr.err)
288
-		}
286
+		c.Assert(sr.err, check.IsNil)
287
+		c.Assert(sr.status, check.Equals, http.StatusOK)
289 288
 
290 289
 		dec := json.NewDecoder(bytes.NewBuffer(sr.body))
291 290
 		var s *types.Stats
... ...
@@ -297,6 +295,7 @@ func (s *DockerSuite) TestGetContainerStats(c *check.C) {
297 297
 }
298 298
 
299 299
 func (s *DockerSuite) TestGetStoppedContainerStats(c *check.C) {
300
+	// TODO: this test does nothing because we are c.Assert'ing in goroutine
300 301
 	var (
301 302
 		name   = "statscontainer"
302 303
 		runCmd = exec.Command(dockerBinary, "create", "--name", name, "busybox", "top")
... ...
@@ -2,6 +2,7 @@ package main
2 2
 
3 3
 import (
4 4
 	"bufio"
5
+	"fmt"
5 6
 	"io"
6 7
 	"os/exec"
7 8
 	"strings"
... ...
@@ -89,7 +90,6 @@ func (s *DockerSuite) TestAttachMultipleAndRestart(c *check.C) {
89 89
 }
90 90
 
91 91
 func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
92
-
93 92
 	cmd := exec.Command(dockerBinary, "run", "-d", "-ti", "busybox")
94 93
 	out, _, err := runCommandWithOutput(cmd)
95 94
 	if err != nil {
... ...
@@ -108,29 +108,32 @@ func (s *DockerSuite) TestAttachTtyWithoutStdin(c *check.C) {
108 108
 		}
109 109
 	}()
110 110
 
111
-	done := make(chan struct{})
111
+	done := make(chan error)
112 112
 	go func() {
113 113
 		defer close(done)
114 114
 
115 115
 		cmd := exec.Command(dockerBinary, "attach", id)
116 116
 		if _, err := cmd.StdinPipe(); err != nil {
117
-			c.Fatal(err)
117
+			done <- err
118
+			return
118 119
 		}
119 120
 
120 121
 		expected := "cannot enable tty mode"
121 122
 		if out, _, err := runCommandWithOutput(cmd); err == nil {
122
-			c.Fatal("attach should have failed")
123
+			done <- fmt.Errorf("attach should have failed")
124
+			return
123 125
 		} else if !strings.Contains(out, expected) {
124
-			c.Fatalf("attach failed with error %q: expected %q", out, expected)
126
+			done <- fmt.Errorf("attach failed with error %q: expected %q", out, expected)
127
+			return
125 128
 		}
126 129
 	}()
127 130
 
128 131
 	select {
129
-	case <-done:
132
+	case err := <-done:
133
+		c.Assert(err, check.IsNil)
130 134
 	case <-time.After(attachWait):
131 135
 		c.Fatal("attach is running but should have failed")
132 136
 	}
133
-
134 137
 }
135 138
 
136 139
 func (s *DockerSuite) TestAttachDisconnect(c *check.C) {
... ...
@@ -27,14 +27,14 @@ func (s *DockerSuite) TestAttachClosedOnContainerStop(c *check.C) {
27 27
 		c.Fatal(err)
28 28
 	}
29 29
 
30
-	done := make(chan struct{})
31
-
30
+	errChan := make(chan error)
32 31
 	go func() {
33
-		defer close(done)
32
+		defer close(errChan)
34 33
 
35 34
 		_, tty, err := pty.Open()
36 35
 		if err != nil {
37
-			c.Fatalf("could not open pty: %v", err)
36
+			errChan <- err
37
+			return
38 38
 		}
39 39
 		attachCmd := exec.Command(dockerBinary, "attach", id)
40 40
 		attachCmd.Stdin = tty
... ...
@@ -42,7 +42,8 @@ func (s *DockerSuite) TestAttachClosedOnContainerStop(c *check.C) {
42 42
 		attachCmd.Stderr = tty
43 43
 
44 44
 		if err := attachCmd.Run(); err != nil {
45
-			c.Fatalf("attach returned error %s", err)
45
+			errChan <- err
46
+			return
46 47
 		}
47 48
 	}()
48 49
 
... ...
@@ -51,7 +52,8 @@ func (s *DockerSuite) TestAttachClosedOnContainerStop(c *check.C) {
51 51
 		c.Fatalf("error thrown while waiting for container: %s, %v", out, err)
52 52
 	}
53 53
 	select {
54
-	case <-done:
54
+	case err := <-errChan:
55
+		c.Assert(err, check.IsNil)
55 56
 	case <-time.After(attachWait):
56 57
 		c.Fatal("timed out without attach returning")
57 58
 	}
... ...
@@ -71,12 +73,10 @@ func (s *DockerSuite) TestAttachAfterDetach(c *check.C) {
71 71
 	cmd.Stdout = tty
72 72
 	cmd.Stderr = tty
73 73
 
74
-	detached := make(chan struct{})
74
+	errChan := make(chan error)
75 75
 	go func() {
76
-		if err := cmd.Run(); err != nil {
77
-			c.Fatalf("attach returned error %s", err)
78
-		}
79
-		close(detached)
76
+		errChan <- cmd.Run()
77
+		close(errChan)
80 78
 	}()
81 79
 
82 80
 	time.Sleep(500 * time.Millisecond)
... ...
@@ -87,7 +87,12 @@ func (s *DockerSuite) TestAttachAfterDetach(c *check.C) {
87 87
 	time.Sleep(100 * time.Millisecond)
88 88
 	cpty.Write([]byte{17})
89 89
 
90
-	<-detached
90
+	select {
91
+	case err := <-errChan:
92
+		c.Assert(err, check.IsNil)
93
+	case <-time.After(5 * time.Second):
94
+		c.Fatal("timeout while detaching")
95
+	}
91 96
 
92 97
 	cpty, tty, err = pty.Open()
93 98
 	if err != nil {
... ...
@@ -119,9 +124,7 @@ func (s *DockerSuite) TestAttachAfterDetach(c *check.C) {
119 119
 
120 120
 	select {
121 121
 	case err := <-readErr:
122
-		if err != nil {
123
-			c.Fatal(err)
124
-		}
122
+		c.Assert(err, check.IsNil)
125 123
 	case <-time.After(2 * time.Second):
126 124
 		c.Fatal("timeout waiting for attach read")
127 125
 	}
... ...
@@ -15,7 +15,6 @@ import (
15 15
 	"runtime"
16 16
 	"strconv"
17 17
 	"strings"
18
-	"sync"
19 18
 	"text/template"
20 19
 	"time"
21 20
 
... ...
@@ -764,17 +763,17 @@ ADD test_file .`,
764 764
 	}
765 765
 	defer ctx.Close()
766 766
 
767
-	done := make(chan struct{})
767
+	errChan := make(chan error)
768 768
 	go func() {
769
-		if _, err := buildImageFromContext(name, ctx, true); err != nil {
770
-			c.Fatal(err)
771
-		}
772
-		close(done)
769
+		_, err := buildImageFromContext(name, ctx, true)
770
+		errChan <- err
771
+		close(errChan)
773 772
 	}()
774 773
 	select {
775 774
 	case <-time.After(5 * time.Second):
776 775
 		c.Fatal("Build with adding to workdir timed out")
777
-	case <-done:
776
+	case err := <-errChan:
777
+		c.Assert(err, check.IsNil)
778 778
 	}
779 779
 }
780 780
 
... ...
@@ -1365,17 +1364,17 @@ COPY test_file .`,
1365 1365
 	}
1366 1366
 	defer ctx.Close()
1367 1367
 
1368
-	done := make(chan struct{})
1368
+	errChan := make(chan error)
1369 1369
 	go func() {
1370
-		if _, err := buildImageFromContext(name, ctx, true); err != nil {
1371
-			c.Fatal(err)
1372
-		}
1373
-		close(done)
1370
+		_, err := buildImageFromContext(name, ctx, true)
1371
+		errChan <- err
1372
+		close(errChan)
1374 1373
 	}()
1375 1374
 	select {
1376 1375
 	case <-time.After(5 * time.Second):
1377 1376
 		c.Fatal("Build with adding to workdir timed out")
1378
-	case <-done:
1377
+	case err := <-errChan:
1378
+		c.Assert(err, check.IsNil)
1379 1379
 	}
1380 1380
 }
1381 1381
 
... ...
@@ -1829,9 +1828,6 @@ func (s *DockerSuite) TestBuildForceRm(c *check.C) {
1829 1829
 // * When docker events sees container start, close the "docker build" command
1830 1830
 // * Wait for docker events to emit a dying event.
1831 1831
 func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
1832
-	var wg sync.WaitGroup
1833
-	defer wg.Wait()
1834
-
1835 1832
 	name := "testbuildcancelation"
1836 1833
 
1837 1834
 	// (Note: one year, will never finish)
... ...
@@ -1849,26 +1845,21 @@ func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
1849 1849
 	containerID := make(chan string)
1850 1850
 
1851 1851
 	startEpoch := daemonTime(c).Unix()
1852
+	// Watch for events since epoch.
1853
+	eventsCmd := exec.Command(
1854
+		dockerBinary, "events",
1855
+		"--since", strconv.FormatInt(startEpoch, 10))
1856
+	stdout, err := eventsCmd.StdoutPipe()
1857
+	if err != nil {
1858
+		c.Fatal(err)
1859
+	}
1860
+	if err := eventsCmd.Start(); err != nil {
1861
+		c.Fatal(err)
1862
+	}
1863
+	defer eventsCmd.Process.Kill()
1852 1864
 
1853
-	wg.Add(1)
1854 1865
 	// Goroutine responsible for watching start/die events from `docker events`
1855 1866
 	go func() {
1856
-		defer wg.Done()
1857
-		// Watch for events since epoch.
1858
-		eventsCmd := exec.Command(
1859
-			dockerBinary, "events",
1860
-			"--since", strconv.FormatInt(startEpoch, 10))
1861
-		stdout, err := eventsCmd.StdoutPipe()
1862
-		err = eventsCmd.Start()
1863
-		if err != nil {
1864
-			c.Fatalf("failed to start 'docker events': %s", err)
1865
-		}
1866
-
1867
-		go func() {
1868
-			<-finish
1869
-			eventsCmd.Process.Kill()
1870
-		}()
1871
-
1872 1867
 		cid := <-containerID
1873 1868
 
1874 1869
 		matchStart := regexp.MustCompile(cid + `(.*) start$`)
... ...
@@ -1886,19 +1877,13 @@ func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
1886 1886
 				close(eventDie)
1887 1887
 			}
1888 1888
 		}
1889
-
1890
-		err = eventsCmd.Wait()
1891
-		if err != nil && !IsKilled(err) {
1892
-			c.Fatalf("docker events had bad exit status: %s", err)
1893
-		}
1894 1889
 	}()
1895 1890
 
1896 1891
 	buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".")
1897 1892
 	buildCmd.Dir = ctx.Dir
1898 1893
 
1899 1894
 	stdoutBuild, err := buildCmd.StdoutPipe()
1900
-	err = buildCmd.Start()
1901
-	if err != nil {
1895
+	if err := buildCmd.Start(); err != nil {
1902 1896
 		c.Fatalf("failed to run build: %s", err)
1903 1897
 	}
1904 1898
 
... ...
@@ -1923,14 +1908,12 @@ func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
1923 1923
 
1924 1924
 	// Send a kill to the `docker build` command.
1925 1925
 	// Causes the underlying build to be cancelled due to socket close.
1926
-	err = buildCmd.Process.Kill()
1927
-	if err != nil {
1926
+	if err := buildCmd.Process.Kill(); err != nil {
1928 1927
 		c.Fatalf("error killing build command: %s", err)
1929 1928
 	}
1930 1929
 
1931 1930
 	// Get the exit status of `docker build`, check it exited because killed.
1932
-	err = buildCmd.Wait()
1933
-	if err != nil && !IsKilled(err) {
1931
+	if err := buildCmd.Wait(); err != nil && !IsKilled(err) {
1934 1932
 		c.Fatalf("wait failed during build run: %T %s", err, err)
1935 1933
 	}
1936 1934
 
... ...
@@ -75,8 +75,7 @@ func (s *DockerSuite) TestEventsLimit(c *check.C) {
75 75
 		waitGroup.Add(1)
76 76
 		go func() {
77 77
 			defer waitGroup.Done()
78
-			err := exec.Command(dockerBinary, args...).Run()
79
-			errChan <- err
78
+			errChan <- exec.Command(dockerBinary, args...).Run()
80 79
 		}()
81 80
 	}
82 81
 
... ...
@@ -229,8 +228,7 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) {
229 229
 	if err != nil {
230 230
 		c.Fatal(err)
231 231
 	}
232
-	err = eventsCmd.Start()
233
-	if err != nil {
232
+	if err := eventsCmd.Start(); err != nil {
234 233
 		c.Fatal(err)
235 234
 	}
236 235
 	defer eventsCmd.Process.Kill()
... ...
@@ -424,30 +422,23 @@ func (s *DockerSuite) TestEventsFilterContainer(c *check.C) {
424 424
 func (s *DockerSuite) TestEventsStreaming(c *check.C) {
425 425
 	start := daemonTime(c).Unix()
426 426
 
427
-	finish := make(chan struct{})
428
-	defer close(finish)
429 427
 	id := make(chan string)
430 428
 	eventCreate := make(chan struct{})
431 429
 	eventStart := make(chan struct{})
432 430
 	eventDie := make(chan struct{})
433 431
 	eventDestroy := make(chan struct{})
434 432
 
435
-	go func() {
436
-		eventsCmd := exec.Command(dockerBinary, "events", "--since", strconv.FormatInt(start, 10))
437
-		stdout, err := eventsCmd.StdoutPipe()
438
-		if err != nil {
439
-			c.Fatal(err)
440
-		}
441
-		err = eventsCmd.Start()
442
-		if err != nil {
443
-			c.Fatalf("failed to start 'docker events': %s", err)
444
-		}
445
-
446
-		go func() {
447
-			<-finish
448
-			eventsCmd.Process.Kill()
449
-		}()
433
+	eventsCmd := exec.Command(dockerBinary, "events", "--since", strconv.FormatInt(start, 10))
434
+	stdout, err := eventsCmd.StdoutPipe()
435
+	if err != nil {
436
+		c.Fatal(err)
437
+	}
438
+	if err := eventsCmd.Start(); err != nil {
439
+		c.Fatalf("failed to start 'docker events': %s", err)
440
+	}
441
+	defer eventsCmd.Process.Kill()
450 442
 
443
+	go func() {
451 444
 		containerID := <-id
452 445
 
453 446
 		matchCreate := regexp.MustCompile(containerID + `: \(from busybox:latest\) create$`)
... ...
@@ -468,11 +459,6 @@ func (s *DockerSuite) TestEventsStreaming(c *check.C) {
468 468
 				close(eventDestroy)
469 469
 			}
470 470
 		}
471
-
472
-		err = eventsCmd.Wait()
473
-		if err != nil && !IsKilled(err) {
474
-			c.Fatalf("docker events had bad exit status: %s", err)
475
-		}
476 471
 	}()
477 472
 
478 473
 	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox:latest", "true")
... ...
@@ -516,5 +502,4 @@ func (s *DockerSuite) TestEventsStreaming(c *check.C) {
516 516
 	case <-eventDestroy:
517 517
 		// ignore, done
518 518
 	}
519
-
520 519
 }
... ...
@@ -74,15 +74,14 @@ func (s *DockerSuite) TestExecInteractive(c *check.C) {
74 74
 	if err := stdin.Close(); err != nil {
75 75
 		c.Fatal(err)
76 76
 	}
77
-	finish := make(chan struct{})
77
+	errChan := make(chan error)
78 78
 	go func() {
79
-		if err := execCmd.Wait(); err != nil {
80
-			c.Fatal(err)
81
-		}
82
-		close(finish)
79
+		errChan <- execCmd.Wait()
80
+		close(errChan)
83 81
 	}()
84 82
 	select {
85
-	case <-finish:
83
+	case err := <-errChan:
84
+		c.Assert(err, check.IsNil)
86 85
 	case <-time.After(1 * time.Second):
87 86
 		c.Fatal("docker exec failed to exit on stdin close")
88 87
 	}
... ...
@@ -278,25 +277,29 @@ func (s *DockerSuite) TestExecTtyWithoutStdin(c *check.C) {
278 278
 		}
279 279
 	}()
280 280
 
281
-	done := make(chan struct{})
281
+	errChan := make(chan error)
282 282
 	go func() {
283
-		defer close(done)
283
+		defer close(errChan)
284 284
 
285 285
 		cmd := exec.Command(dockerBinary, "exec", "-ti", id, "true")
286 286
 		if _, err := cmd.StdinPipe(); err != nil {
287
-			c.Fatal(err)
287
+			errChan <- err
288
+			return
288 289
 		}
289 290
 
290 291
 		expected := "cannot enable tty mode"
291 292
 		if out, _, err := runCommandWithOutput(cmd); err == nil {
292
-			c.Fatal("exec should have failed")
293
+			errChan <- fmt.Errorf("exec should have failed")
294
+			return
293 295
 		} else if !strings.Contains(out, expected) {
294
-			c.Fatalf("exec failed with error %q: expected %q", out, expected)
296
+			errChan <- fmt.Errorf("exec failed with error %q: expected %q", out, expected)
297
+			return
295 298
 		}
296 299
 	}()
297 300
 
298 301
 	select {
299
-	case <-done:
302
+	case err := <-errChan:
303
+		c.Assert(err, check.IsNil)
300 304
 	case <-time.After(3 * time.Second):
301 305
 		c.Fatal("exec is running but should have failed")
302 306
 	}
... ...
@@ -326,17 +329,22 @@ func (s *DockerSuite) TestExecStopNotHanging(c *check.C) {
326 326
 		c.Fatal(err)
327 327
 	}
328 328
 
329
-	wait := make(chan struct{})
329
+	type dstop struct {
330
+		out []byte
331
+		err error
332
+	}
333
+
334
+	ch := make(chan dstop)
330 335
 	go func() {
331
-		if out, err := exec.Command(dockerBinary, "stop", "testing").CombinedOutput(); err != nil {
332
-			c.Fatal(out, err)
333
-		}
334
-		close(wait)
336
+		out, err := exec.Command(dockerBinary, "stop", "testing").CombinedOutput()
337
+		ch <- dstop{out, err}
338
+		close(ch)
335 339
 	}()
336 340
 	select {
337 341
 	case <-time.After(3 * time.Second):
338 342
 		c.Fatal("Container stop timed out")
339
-	case <-wait:
343
+	case s := <-ch:
344
+		c.Assert(s.err, check.IsNil)
340 345
 	}
341 346
 }
342 347
 
... ...
@@ -359,6 +367,7 @@ func (s *DockerSuite) TestExecCgroup(c *check.C) {
359 359
 	var wg sync.WaitGroup
360 360
 	var mu sync.Mutex
361 361
 	execCgroups := []sort.StringSlice{}
362
+	errChan := make(chan error)
362 363
 	// exec a few times concurrently to get consistent failure
363 364
 	for i := 0; i < 5; i++ {
364 365
 		wg.Add(1)
... ...
@@ -366,7 +375,8 @@ func (s *DockerSuite) TestExecCgroup(c *check.C) {
366 366
 			cmd := exec.Command(dockerBinary, "exec", "testing", "cat", "/proc/self/cgroup")
367 367
 			out, _, err := runCommandWithOutput(cmd)
368 368
 			if err != nil {
369
-				c.Fatal(out, err)
369
+				errChan <- err
370
+				return
370 371
 			}
371 372
 			cg := sort.StringSlice(strings.Split(string(out), "\n"))
372 373
 
... ...
@@ -377,6 +387,11 @@ func (s *DockerSuite) TestExecCgroup(c *check.C) {
377 377
 		}()
378 378
 	}
379 379
 	wg.Wait()
380
+	close(errChan)
381
+
382
+	for err := range errChan {
383
+		c.Assert(err, check.IsNil)
384
+	}
380 385
 
381 386
 	for _, cg := range execCgroups {
382 387
 		if !reflect.DeepEqual(cg, containerCgroups) {
... ...
@@ -260,16 +260,15 @@ func (s *DockerSuite) TestLogsFollowStopped(c *check.C) {
260 260
 		c.Fatal(err)
261 261
 	}
262 262
 
263
-	ch := make(chan struct{})
263
+	errChan := make(chan error)
264 264
 	go func() {
265
-		if err := logsCmd.Wait(); err != nil {
266
-			c.Fatal(err)
267
-		}
268
-		close(ch)
265
+		errChan <- logsCmd.Wait()
266
+		close(errChan)
269 267
 	}()
270 268
 
271 269
 	select {
272
-	case <-ch:
270
+	case err := <-errChan:
271
+		c.Assert(err, check.IsNil)
273 272
 	case <-time.After(1 * time.Second):
274 273
 		c.Fatal("Following logs is hanged")
275 274
 	}
... ...
@@ -298,9 +297,7 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
298 298
 	logCmd := exec.Command(dockerBinary, "logs", "-f", cleanedContainerID)
299 299
 
300 300
 	stdout, err := logCmd.StdoutPipe()
301
-	if err != nil {
302
-		c.Fatal(err)
303
-	}
301
+	c.Assert(err, check.IsNil)
304 302
 
305 303
 	if err := logCmd.Start(); err != nil {
306 304
 		c.Fatal(err)
... ...
@@ -308,15 +305,11 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
308 308
 
309 309
 	// First read slowly
310 310
 	bytes1, err := consumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead)
311
-	if err != nil {
312
-		c.Fatal(err)
313
-	}
311
+	c.Assert(err, check.IsNil)
314 312
 
315 313
 	// After the container has finished we can continue reading fast
316 314
 	bytes2, err := consumeWithSpeed(stdout, 32*1024, 0, nil)
317
-	if err != nil {
318
-		c.Fatal(err)
319
-	}
315
+	c.Assert(err, check.IsNil)
320 316
 
321 317
 	actual := bytes1 + bytes2
322 318
 	expected := 200000
... ...
@@ -255,7 +255,6 @@ func assertContainerList(out string, expected []string) bool {
255 255
 }
256 256
 
257 257
 func (s *DockerSuite) TestPsListContainersSize(c *check.C) {
258
-
259 258
 	cmd := exec.Command(dockerBinary, "run", "-d", "busybox", "echo", "hello")
260 259
 	runCommandWithOutput(cmd)
261 260
 	cmd = exec.Command(dockerBinary, "ps", "-s", "-n=1")
... ...
@@ -756,17 +756,22 @@ func (s *DockerSuite) TestRunTwoConcurrentContainers(c *check.C) {
756 756
 	group := sync.WaitGroup{}
757 757
 	group.Add(2)
758 758
 
759
+	errChan := make(chan error, 2)
759 760
 	for i := 0; i < 2; i++ {
760 761
 		go func() {
761 762
 			defer group.Done()
762 763
 			cmd := exec.Command(dockerBinary, "run", "busybox", "sleep", "2")
763
-			if _, err := runCommand(cmd); err != nil {
764
-				c.Fatal(err)
765
-			}
764
+			_, err := runCommand(cmd)
765
+			errChan <- err
766 766
 		}()
767 767
 	}
768 768
 
769 769
 	group.Wait()
770
+	close(errChan)
771
+
772
+	for err := range errChan {
773
+		c.Assert(err, check.IsNil)
774
+	}
770 775
 }
771 776
 
772 777
 func (s *DockerSuite) TestRunEnvironment(c *check.C) {
... ...
@@ -1851,22 +1856,20 @@ func (s *DockerSuite) TestRunExitOnStdinClose(c *check.C) {
1851 1851
 	if err := stdin.Close(); err != nil {
1852 1852
 		c.Fatal(err)
1853 1853
 	}
1854
-	finish := make(chan struct{})
1854
+	finish := make(chan error)
1855 1855
 	go func() {
1856
-		if err := runCmd.Wait(); err != nil {
1857
-			c.Fatal(err)
1858
-		}
1856
+		finish <- runCmd.Wait()
1859 1857
 		close(finish)
1860 1858
 	}()
1861 1859
 	select {
1862
-	case <-finish:
1860
+	case err := <-finish:
1861
+		c.Assert(err, check.IsNil)
1863 1862
 	case <-time.After(1 * time.Second):
1864 1863
 		c.Fatal("docker run failed to exit on stdin close")
1865 1864
 	}
1866 1865
 	state, err := inspectField(name, "State.Running")
1867
-	if err != nil {
1868
-		c.Fatal(err)
1869
-	}
1866
+	c.Assert(err, check.IsNil)
1867
+
1870 1868
 	if state != "false" {
1871 1869
 		c.Fatal("Container must be stopped after stdin closing")
1872 1870
 	}
... ...
@@ -2762,25 +2765,29 @@ func (s *DockerSuite) TestRunPortFromDockerRangeInUse(c *check.C) {
2762 2762
 }
2763 2763
 
2764 2764
 func (s *DockerSuite) TestRunTtyWithPipe(c *check.C) {
2765
-	done := make(chan struct{})
2765
+	errChan := make(chan error)
2766 2766
 	go func() {
2767
-		defer close(done)
2767
+		defer close(errChan)
2768 2768
 
2769 2769
 		cmd := exec.Command(dockerBinary, "run", "-ti", "busybox", "true")
2770 2770
 		if _, err := cmd.StdinPipe(); err != nil {
2771
-			c.Fatal(err)
2771
+			errChan <- err
2772
+			return
2772 2773
 		}
2773 2774
 
2774 2775
 		expected := "cannot enable tty mode"
2775 2776
 		if out, _, err := runCommandWithOutput(cmd); err == nil {
2776
-			c.Fatal("run should have failed")
2777
+			errChan <- fmt.Errorf("run should have failed")
2778
+			return
2777 2779
 		} else if !strings.Contains(out, expected) {
2778
-			c.Fatalf("run failed with error %q: expected %q", out, expected)
2780
+			errChan <- fmt.Errorf("run failed with error %q: expected %q", out, expected)
2781
+			return
2779 2782
 		}
2780 2783
 	}()
2781 2784
 
2782 2785
 	select {
2783
-	case <-done:
2786
+	case err := <-errChan:
2787
+		c.Assert(err, check.IsNil)
2784 2788
 	case <-time.After(3 * time.Second):
2785 2789
 		c.Fatal("container is running but should have failed")
2786 2790
 	}
... ...
@@ -2875,19 +2882,19 @@ func (s *DockerSuite) TestRunAllowPortRangeThroughPublish(c *check.C) {
2875 2875
 }
2876 2876
 
2877 2877
 func (s *DockerSuite) TestRunOOMExitCode(c *check.C) {
2878
-	done := make(chan struct{})
2878
+	errChan := make(chan error)
2879 2879
 	go func() {
2880
-		defer close(done)
2881
-
2880
+		defer close(errChan)
2882 2881
 		runCmd := exec.Command(dockerBinary, "run", "-m", "4MB", "busybox", "sh", "-c", "x=a; while true; do x=$x$x$x$x; done")
2883 2882
 		out, exitCode, _ := runCommandWithOutput(runCmd)
2884 2883
 		if expected := 137; exitCode != expected {
2885
-			c.Fatalf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out)
2884
+			errChan <- fmt.Errorf("wrong exit code for OOM container: expected %d, got %d (output: %q)", expected, exitCode, out)
2886 2885
 		}
2887 2886
 	}()
2888 2887
 
2889 2888
 	select {
2890
-	case <-done:
2889
+	case err := <-errChan:
2890
+		c.Assert(err, check.IsNil)
2891 2891
 	case <-time.After(30 * time.Second):
2892 2892
 		c.Fatal("Timeout waiting for container to die on OOM")
2893 2893
 	}
... ...
@@ -3030,9 +3037,7 @@ func (s *DockerSuite) TestRunPidHostWithChildIsKillable(c *check.C) {
3030 3030
 	}()
3031 3031
 	select {
3032 3032
 	case err := <-errchan:
3033
-		if err != nil {
3034
-			c.Fatal(err)
3035
-		}
3033
+		c.Assert(err, check.IsNil)
3036 3034
 	case <-time.After(5 * time.Second):
3037 3035
 		c.Fatal("Kill container timed out")
3038 3036
 	}
... ...
@@ -29,21 +29,22 @@ func (s *DockerSuite) TestRunRedirectStdout(c *check.C) {
29 29
 		cmd.Stdin = tty
30 30
 		cmd.Stdout = tty
31 31
 		cmd.Stderr = tty
32
-		ch := make(chan struct{})
33 32
 		if err := cmd.Start(); err != nil {
34 33
 			c.Fatalf("start err: %v", err)
35 34
 		}
35
+		ch := make(chan error)
36 36
 		go func() {
37
-			if err := cmd.Wait(); err != nil {
38
-				c.Fatalf("wait err=%v", err)
39
-			}
37
+			ch <- cmd.Wait()
40 38
 			close(ch)
41 39
 		}()
42 40
 
43 41
 		select {
44 42
 		case <-time.After(10 * time.Second):
45 43
 			c.Fatal("command timeout")
46
-		case <-ch:
44
+		case err := <-ch:
45
+			if err != nil {
46
+				c.Fatalf("wait err=%v", err)
47
+			}
47 48
 		}
48 49
 	}
49 50
 
... ...
@@ -20,18 +20,19 @@ func (s *DockerSuite) TestStartAttachReturnsOnError(c *check.C) {
20 20
 		c.Fatal("Expected error but got none")
21 21
 	}
22 22
 
23
-	ch := make(chan struct{})
23
+	ch := make(chan error)
24 24
 	go func() {
25 25
 		// Attempt to start attached to the container that won't start
26 26
 		// This should return an error immediately since the container can't be started
27 27
 		if _, err := runCommand(exec.Command(dockerBinary, "start", "-a", "test2")); err == nil {
28
-			c.Fatal("Expected error but got none")
28
+			ch <- fmt.Errorf("Expected error but got none")
29 29
 		}
30 30
 		close(ch)
31 31
 	}()
32 32
 
33 33
 	select {
34
-	case <-ch:
34
+	case err := <-ch:
35
+		c.Assert(err, check.IsNil)
35 36
 	case <-time.After(time.Second):
36 37
 		c.Fatalf("Attach did not exit properly")
37 38
 	}