github.com/lazyboychen7/engine@v17.12.1-ce-rc2+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 12 "github.com/docker/docker/integration-cli/checker" 13 "github.com/docker/docker/integration-cli/request" 14 "github.com/go-check/check" 15 ) 16 17 func (s *DockerSuite) TestExecResizeAPIHeightWidthNoInt(c *check.C) { 18 testRequires(c, DaemonIsLinux) 19 out, _ := dockerCmd(c, "run", "-d", "busybox", "top") 20 cleanedContainerID := strings.TrimSpace(out) 21 22 endpoint := "/exec/" + cleanedContainerID + "/resize?h=foo&w=bar" 23 res, _, err := request.Post(endpoint) 24 c.Assert(err, checker.IsNil) 25 c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest) 26 } 27 28 // Part of #14845 29 func (s *DockerSuite) TestExecResizeImmediatelyAfterExecStart(c *check.C) { 30 name := "exec_resize_test" 31 dockerCmd(c, "run", "-d", "-i", "-t", "--name", name, "--restart", "always", "busybox", "/bin/sh") 32 33 testExecResize := func() error { 34 data := map[string]interface{}{ 35 "AttachStdin": true, 36 "Cmd": []string{"/bin/sh"}, 37 } 38 uri := fmt.Sprintf("/containers/%s/exec", name) 39 res, body, err := request.Post(uri, request.JSONBody(data)) 40 if err != nil { 41 return err 42 } 43 if res.StatusCode != http.StatusCreated { 44 return fmt.Errorf("POST %s is expected to return %d, got %d", uri, http.StatusCreated, res.StatusCode) 45 } 46 47 buf, err := request.ReadBody(body) 48 c.Assert(err, checker.IsNil) 49 50 out := map[string]string{} 51 err = json.Unmarshal(buf, &out) 52 if err != nil { 53 return fmt.Errorf("ExecCreate returned invalid json. Error: %q", err.Error()) 54 } 55 56 execID := out["Id"] 57 if len(execID) < 1 { 58 return fmt.Errorf("ExecCreate got invalid execID") 59 } 60 61 payload := bytes.NewBufferString(`{"Tty":true}`) 62 conn, _, err := request.SockRequestHijack("POST", fmt.Sprintf("/exec/%s/start", execID), payload, "application/json", daemonHost()) 63 if err != nil { 64 return fmt.Errorf("Failed to start the exec: %q", err.Error()) 65 } 66 defer conn.Close() 67 68 _, rc, err := request.Post(fmt.Sprintf("/exec/%s/resize?h=24&w=80", execID), request.ContentType("text/plain")) 69 // It's probably a panic of the daemon if io.ErrUnexpectedEOF is returned. 70 if err == io.ErrUnexpectedEOF { 71 return fmt.Errorf("The daemon might have crashed.") 72 } 73 74 if err == nil { 75 rc.Close() 76 } 77 78 // We only interested in the io.ErrUnexpectedEOF error, so we return nil otherwise. 79 return nil 80 } 81 82 // The panic happens when daemon.ContainerExecStart is called but the 83 // container.Exec is not called. 84 // Because the panic is not 100% reproducible, we send the requests concurrently 85 // to increase the probability that the problem is triggered. 86 var ( 87 n = 10 88 ch = make(chan error, n) 89 wg sync.WaitGroup 90 ) 91 for i := 0; i < n; i++ { 92 wg.Add(1) 93 go func() { 94 defer wg.Done() 95 if err := testExecResize(); err != nil { 96 ch <- err 97 } 98 }() 99 } 100 101 wg.Wait() 102 select { 103 case err := <-ch: 104 c.Fatal(err.Error()) 105 default: 106 } 107 }