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