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
 
7b6bca5a
 	"github.com/docker/docker/pkg/integration/checker"
dc944ea7
 	"github.com/go-check/check"
3341f3a3
 )
 
dc944ea7
 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"
27fccdba
 	status, _, err := sockRequest("POST", endpoint, nil)
7b6bca5a
 	c.Assert(err, checker.IsNil)
 	c.Assert(status, checker.Equals, http.StatusInternalServerError)
3341f3a3
 }
ba5e0980
 
 // Part of #14845
 func (s *DockerSuite) TestExecResizeImmediatelyAfterExecStart(c *check.C) {
f9a3558a
 	testRequires(c, DaemonIsLinux)
83cb2885
 
ba5e0980
 	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)
 		status, body, err := sockRequest("POST", uri, data)
 		if err != nil {
 			return err
 		}
 		if status != http.StatusCreated {
 			return fmt.Errorf("POST %s is expected to return %d, got %d", uri, http.StatusCreated, status)
 		}
ba5e0980
 
bb161b77
 		out := map[string]string{}
 		err = json.Unmarshal(body, &out)
 		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}`)
 		conn, _, err := sockRequestHijack("POST", fmt.Sprintf("/exec/%s/start", execID), payload, "application/json")
 		if err != nil {
 			return fmt.Errorf("Failed to start the exec: %q", err.Error())
 		}
 		defer conn.Close()
ba5e0980
 
bb161b77
 		_, rc, err := sockRequestRaw("POST", fmt.Sprintf("/exec/%s/resize?h=24&w=80", execID), nil, "text/plain")
 		// 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
 	}
 }