Browse code

move the assertions outside of the goroutine

Signed-off-by: Shijiang Wei <mountkin@gmail.com>

Shijiang Wei authored on 2015/08/04 20:44:54
Showing 1 changed files
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"io"
8 8
 	"net/http"
9 9
 	"strings"
10
+	"sync"
10 11
 
11 12
 	"github.com/go-check/check"
12 13
 )
... ...
@@ -28,53 +29,75 @@ func (s *DockerSuite) TestExecResizeImmediatelyAfterExecStart(c *check.C) {
28 28
 	name := "exec_resize_test"
29 29
 	dockerCmd(c, "run", "-d", "-i", "-t", "--name", name, "--restart", "always", "busybox", "/bin/sh")
30 30
 
31
-	// The panic happens when daemon.ContainerExecStart is called but the
32
-	// container.Exec is not called.
33
-	// Because the panic is not 100% reproducible, we send the requests concurrently
34
-	// to increase the probability that the problem is triggered.
35
-	n := 10
36
-	ch := make(chan struct{})
37
-	for i := 0; i < n; i++ {
38
-		go func() {
39
-			defer func() {
40
-				ch <- struct{}{}
41
-			}()
31
+	testExecResize := func() error {
32
+		data := map[string]interface{}{
33
+			"AttachStdin": true,
34
+			"Cmd":         []string{"/bin/sh"},
35
+		}
36
+		uri := fmt.Sprintf("/containers/%s/exec", name)
37
+		status, body, err := sockRequest("POST", uri, data)
38
+		if err != nil {
39
+			return err
40
+		}
41
+		if status != http.StatusCreated {
42
+			return fmt.Errorf("POST %s is expected to return %d, got %d", uri, http.StatusCreated, status)
43
+		}
42 44
 
43
-			data := map[string]interface{}{
44
-				"AttachStdin": true,
45
-				"Cmd":         []string{"/bin/sh"},
46
-			}
47
-			status, body, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), data)
48
-			c.Assert(err, check.IsNil)
49
-			c.Assert(status, check.Equals, http.StatusCreated)
45
+		out := map[string]string{}
46
+		err = json.Unmarshal(body, &out)
47
+		if err != nil {
48
+			return fmt.Errorf("ExecCreate returned invalid json. Error: %q", err.Error())
49
+		}
50 50
 
51
-			out := map[string]string{}
52
-			err = json.Unmarshal(body, &out)
53
-			c.Assert(err, check.IsNil)
51
+		execID := out["Id"]
52
+		if len(execID) < 1 {
53
+			return fmt.Errorf("ExecCreate got invalid execID")
54
+		}
54 55
 
55
-			execID := out["Id"]
56
-			if len(execID) < 1 {
57
-				c.Fatal("ExecCreate got invalid execID")
58
-			}
56
+		payload := bytes.NewBufferString(`{"Tty":true}`)
57
+		conn, _, err := sockRequestHijack("POST", fmt.Sprintf("/exec/%s/start", execID), payload, "application/json")
58
+		if err != nil {
59
+			return fmt.Errorf("Failed to start the exec: %q", err.Error())
60
+		}
61
+		defer conn.Close()
59 62
 
60
-			payload := bytes.NewBufferString(`{"Tty":true}`)
61
-			conn, _, err := sockRequestHijack("POST", fmt.Sprintf("/exec/%s/start", execID), payload, "application/json")
62
-			c.Assert(err, check.IsNil)
63
-			defer conn.Close()
63
+		_, rc, err := sockRequestRaw("POST", fmt.Sprintf("/exec/%s/resize?h=24&w=80", execID), nil, "text/plain")
64
+		// It's probably a panic of the daemon if io.ErrUnexpectedEOF is returned.
65
+		if err == io.ErrUnexpectedEOF {
66
+			return fmt.Errorf("The daemon might have crashed.")
67
+		}
64 68
 
65
-			_, rc, err := sockRequestRaw("POST", fmt.Sprintf("/exec/%s/resize?h=24&w=80", execID), nil, "text/plain")
66
-			// It's probably a panic of the daemon if io.ErrUnexpectedEOF is returned.
67
-			if err == io.ErrUnexpectedEOF {
68
-				c.Fatal("The daemon might have crashed.")
69
-			}
69
+		if err == nil {
70
+			rc.Close()
71
+		}
70 72
 
71
-			if err == nil {
72
-				rc.Close()
73
+		// We only interested in the io.ErrUnexpectedEOF error, so we return nil otherwise.
74
+		return nil
75
+	}
76
+
77
+	// The panic happens when daemon.ContainerExecStart is called but the
78
+	// container.Exec is not called.
79
+	// Because the panic is not 100% reproducible, we send the requests concurrently
80
+	// to increase the probability that the problem is triggered.
81
+	var (
82
+		n  = 10
83
+		ch = make(chan error, n)
84
+		wg sync.WaitGroup
85
+	)
86
+	for i := 0; i < n; i++ {
87
+		wg.Add(1)
88
+		go func() {
89
+			defer wg.Done()
90
+			if err := testExecResize(); err != nil {
91
+				ch <- err
73 92
 			}
74 93
 		}()
75 94
 	}
76 95
 
77
-	for i := 0; i < n; i++ {
78
-		<-ch
96
+	wg.Wait()
97
+	select {
98
+	case err := <-ch:
99
+		c.Fatal(err.Error())
100
+	default:
79 101
 	}
80 102
 }