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