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