github.com/devdivbcp/moby@v17.12.0-ce-rc1.0.20200726071732-2d4bfdc789ad+incompatible/integration-cli/docker_api_exec_resize_test.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "net/http" 9 "strings" 10 "sync" 11 "testing" 12 13 "github.com/docker/docker/api/types/versions" 14 "github.com/docker/docker/internal/test/request" 15 "gotest.tools/assert" 16 ) 17 18 func (s *DockerSuite) TestExecResizeAPIHeightWidthNoInt(c *testing.T) { 19 testRequires(c, DaemonIsLinux) 20 out, _ := dockerCmd(c, "run", "-d", "busybox", "top") 21 cleanedContainerID := strings.TrimSpace(out) 22 23 endpoint := "/exec/" + cleanedContainerID + "/resize?h=foo&w=bar" 24 res, _, err := request.Post(endpoint) 25 assert.NilError(c, err) 26 if versions.LessThan(testEnv.DaemonAPIVersion(), "1.32") { 27 assert.Equal(c, res.StatusCode, http.StatusInternalServerError) 28 } else { 29 assert.Equal(c, res.StatusCode, http.StatusBadRequest) 30 } 31 } 32 33 // Part of #14845 34 func (s *DockerSuite) TestExecResizeImmediatelyAfterExecStart(c *testing.T) { 35 name := "exec_resize_test" 36 dockerCmd(c, "run", "-d", "-i", "-t", "--name", name, "--restart", "always", "busybox", "/bin/sh") 37 38 testExecResize := func() error { 39 data := map[string]interface{}{ 40 "AttachStdin": true, 41 "Cmd": []string{"/bin/sh"}, 42 } 43 uri := fmt.Sprintf("/containers/%s/exec", name) 44 res, body, err := request.Post(uri, request.JSONBody(data)) 45 if err != nil { 46 return err 47 } 48 if res.StatusCode != http.StatusCreated { 49 return fmt.Errorf("POST %s is expected to return %d, got %d", uri, http.StatusCreated, res.StatusCode) 50 } 51 52 buf, err := request.ReadBody(body) 53 assert.NilError(c, err) 54 55 out := map[string]string{} 56 err = json.Unmarshal(buf, &out) 57 if err != nil { 58 return fmt.Errorf("ExecCreate returned invalid json. Error: %q", err.Error()) 59 } 60 61 execID := out["Id"] 62 if len(execID) < 1 { 63 return fmt.Errorf("ExecCreate got invalid execID") 64 } 65 66 payload := bytes.NewBufferString(`{"Tty":true}`) 67 conn, _, err := sockRequestHijack("POST", fmt.Sprintf("/exec/%s/start", execID), payload, "application/json", request.DaemonHost()) 68 if err != nil { 69 return fmt.Errorf("Failed to start the exec: %q", err.Error()) 70 } 71 defer conn.Close() 72 73 _, rc, err := request.Post(fmt.Sprintf("/exec/%s/resize?h=24&w=80", execID), request.ContentType("text/plain")) 74 if err != nil { 75 // It's probably a panic of the daemon if io.ErrUnexpectedEOF is returned. 76 if err == io.ErrUnexpectedEOF { 77 return fmt.Errorf("The daemon might have crashed.") 78 } 79 // Other error happened, should be reported. 80 return fmt.Errorf("Fail to exec resize immediately after start. Error: %q", err.Error()) 81 } 82 83 rc.Close() 84 85 return nil 86 } 87 88 // The panic happens when daemon.ContainerExecStart is called but the 89 // container.Exec is not called. 90 // Because the panic is not 100% reproducible, we send the requests concurrently 91 // to increase the probability that the problem is triggered. 92 var ( 93 n = 10 94 ch = make(chan error, n) 95 wg sync.WaitGroup 96 ) 97 for i := 0; i < n; i++ { 98 wg.Add(1) 99 go func() { 100 defer wg.Done() 101 if err := testExecResize(); err != nil { 102 ch <- err 103 } 104 }() 105 } 106 107 wg.Wait() 108 select { 109 case err := <-ch: 110 c.Fatal(err.Error()) 111 default: 112 } 113 }