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