integration-cli/docker_api_exec_resize_test.go
3341f3a3
 package main
 
 import (
ba5e0980
 	"bytes"
 	"encoding/json"
 	"fmt"
 	"io"
27fccdba
 	"net/http"
3341f3a3
 	"strings"
bb161b77
 	"sync"
dc944ea7
 
33968e6c
 	"github.com/docker/docker/integration-cli/checker"
d69d4799
 	"github.com/docker/docker/integration-cli/request"
dc944ea7
 	"github.com/go-check/check"
3341f3a3
 )
 
7fb7a477
 func (s *DockerSuite) TestExecResizeAPIHeightWidthNoInt(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
5c295460
 	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
3341f3a3
 	cleanedContainerID := strings.TrimSpace(out)
 
 	endpoint := "/exec/" + cleanedContainerID + "/resize?h=foo&w=bar"
0fd5a654
 	res, _, err := request.Post(endpoint)
7b6bca5a
 	c.Assert(err, checker.IsNil)
0fd5a654
 	c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
3341f3a3
 }
ba5e0980
 
 // Part of #14845
 func (s *DockerSuite) TestExecResizeImmediatelyAfterExecStart(c *check.C) {
 	name := "exec_resize_test"
 	dockerCmd(c, "run", "-d", "-i", "-t", "--name", name, "--restart", "always", "busybox", "/bin/sh")
 
bb161b77
 	testExecResize := func() error {
 		data := map[string]interface{}{
 			"AttachStdin": true,
 			"Cmd":         []string{"/bin/sh"},
 		}
 		uri := fmt.Sprintf("/containers/%s/exec", name)
0fd5a654
 		res, body, err := request.Post(uri, request.JSONBody(data))
bb161b77
 		if err != nil {
 			return err
 		}
0fd5a654
 		if res.StatusCode != http.StatusCreated {
 			return fmt.Errorf("POST %s is expected to return %d, got %d", uri, http.StatusCreated, res.StatusCode)
bb161b77
 		}
ba5e0980
 
0fd5a654
 		buf, err := request.ReadBody(body)
 		c.Assert(err, checker.IsNil)
 
bb161b77
 		out := map[string]string{}
0fd5a654
 		err = json.Unmarshal(buf, &out)
bb161b77
 		if err != nil {
 			return fmt.Errorf("ExecCreate returned invalid json. Error: %q", err.Error())
 		}
ba5e0980
 
bb161b77
 		execID := out["Id"]
 		if len(execID) < 1 {
 			return fmt.Errorf("ExecCreate got invalid execID")
 		}
ba5e0980
 
bb161b77
 		payload := bytes.NewBufferString(`{"Tty":true}`)
d69d4799
 		conn, _, err := request.SockRequestHijack("POST", fmt.Sprintf("/exec/%s/start", execID), payload, "application/json", daemonHost())
bb161b77
 		if err != nil {
 			return fmt.Errorf("Failed to start the exec: %q", err.Error())
 		}
 		defer conn.Close()
ba5e0980
 
b11ba123
 		_, rc, err := request.Post(fmt.Sprintf("/exec/%s/resize?h=24&w=80", execID), request.ContentType("text/plain"))
bb161b77
 		// It's probably a panic of the daemon if io.ErrUnexpectedEOF is returned.
 		if err == io.ErrUnexpectedEOF {
 			return fmt.Errorf("The daemon might have crashed.")
 		}
ba5e0980
 
bb161b77
 		if err == nil {
 			rc.Close()
 		}
ba5e0980
 
bb161b77
 		// We only interested in the io.ErrUnexpectedEOF error, so we return nil otherwise.
 		return nil
 	}
 
 	// The panic happens when daemon.ContainerExecStart is called but the
 	// container.Exec is not called.
 	// Because the panic is not 100% reproducible, we send the requests concurrently
 	// to increase the probability that the problem is triggered.
 	var (
 		n  = 10
 		ch = make(chan error, n)
 		wg sync.WaitGroup
 	)
 	for i := 0; i < n; i++ {
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
 			if err := testExecResize(); err != nil {
 				ch <- err
ba5e0980
 			}
 		}()
 	}
 
bb161b77
 	wg.Wait()
 	select {
 	case err := <-ch:
 		c.Fatal(err.Error())
 	default:
ba5e0980
 	}
 }