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