Merge pull request #34600 from dnephin/remove-pkg-testutil
Remove pkg/testutil/utils.go
This commit is contained in:
commit
59e1565565
28 changed files with 355 additions and 732 deletions
|
@ -253,7 +253,7 @@ func TestGetWithStatusError(t *testing.T) {
|
|||
if testcase.expectedErr == "" {
|
||||
require.NoError(t, err)
|
||||
|
||||
body, err := testutil.ReadBody(response.Body)
|
||||
body, err := readBody(response.Body)
|
||||
require.NoError(t, err)
|
||||
assert.Contains(t, string(body), testcase.expectedBody)
|
||||
} else {
|
||||
|
@ -261,3 +261,8 @@ func TestGetWithStatusError(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readBody(b io.ReadCloser) ([]byte, error) {
|
||||
defer b.Close()
|
||||
return ioutil.ReadAll(b)
|
||||
}
|
||||
|
|
|
@ -229,3 +229,11 @@ func WithStdout(writer io.Writer) func(*icmd.Cmd) func() {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithStdin sets the standard input reader for the command
|
||||
func WithStdin(stdin io.Reader) func(*icmd.Cmd) func() {
|
||||
return func(cmd *icmd.Cmd) func() {
|
||||
cmd.Stdin = stdin
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,18 +14,20 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/docker/go-connections/sockets"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/go-check/check"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
type testingT interface {
|
||||
|
@ -545,7 +547,7 @@ func (d *Daemon) queryRootDir() (string, error) {
|
|||
}
|
||||
var b []byte
|
||||
var i Info
|
||||
b, err = testutil.ReadBody(body)
|
||||
b, err = request.ReadBody(body)
|
||||
if err == nil && resp.StatusCode == http.StatusOK {
|
||||
// read the docker root dir
|
||||
if err = json.Unmarshal(b, &i); err == nil {
|
||||
|
@ -570,20 +572,13 @@ func (d *Daemon) WaitRun(contID string) error {
|
|||
return WaitInspectWithArgs(d.dockerBinary, contID, "{{.State.Running}}", "true", 10*time.Second, args...)
|
||||
}
|
||||
|
||||
// GetBaseDeviceSize returns the base device size of the daemon
|
||||
func (d *Daemon) GetBaseDeviceSize(c *check.C) int64 {
|
||||
infoCmdOutput, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
exec.Command(d.dockerBinary, "-H", d.Sock(), "info"),
|
||||
exec.Command("grep", "Base Device Size"),
|
||||
)
|
||||
c.Assert(err, checker.IsNil)
|
||||
basesizeSlice := strings.Split(infoCmdOutput, ":")
|
||||
basesize := strings.Trim(basesizeSlice[1], " ")
|
||||
basesize = strings.Trim(basesize, "\n")[:len(basesize)-3]
|
||||
basesizeFloat, err := strconv.ParseFloat(strings.Trim(basesize, " "), 64)
|
||||
c.Assert(err, checker.IsNil)
|
||||
basesizeBytes := int64(basesizeFloat) * (1024 * 1024 * 1024)
|
||||
return basesizeBytes
|
||||
// Info returns the info struct for this daemon
|
||||
func (d *Daemon) Info(t require.TestingT) types.Info {
|
||||
apiclient, err := request.NewClientForHost(d.Sock())
|
||||
require.NoError(t, err)
|
||||
info, err := apiclient.Info(context.Background())
|
||||
require.NoError(t, err)
|
||||
return info
|
||||
}
|
||||
|
||||
// Cmd executes a docker CLI command against this daemon.
|
||||
|
@ -620,7 +615,7 @@ func (d *Daemon) SockRequest(method, endpoint string, data interface{}) (int, []
|
|||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
return res.StatusCode, b, err
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/go-check/check"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
@ -80,7 +79,7 @@ func (s *DockerSuite) TestPostContainersAttachContainerNotFound(c *check.C) {
|
|||
resp, err := client.Do(req)
|
||||
// connection will shutdown, err should be "persistent connection closed"
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound)
|
||||
content, err := testutil.ReadBody(resp.Body)
|
||||
content, err := request.ReadBody(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
expected := "No such container: doesnotexist\r\n"
|
||||
c.Assert(string(content), checker.Equals, expected)
|
||||
|
|
|
@ -17,7 +17,6 @@ import (
|
|||
"github.com/docker/docker/integration-cli/cli/build/fakegit"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakestorage"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/go-check/check"
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/moby/buildkit/session/filesync"
|
||||
|
@ -47,7 +46,7 @@ RUN find /tmp/`
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
buf, err := testutil.ReadBody(body)
|
||||
buf, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Make sure Dockerfile exists.
|
||||
|
@ -135,7 +134,7 @@ RUN echo 'right'
|
|||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
defer body.Close()
|
||||
content, err := testutil.ReadBody(body)
|
||||
content, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Build used the wrong dockerfile.
|
||||
|
@ -153,7 +152,7 @@ RUN echo from dockerfile`,
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
buf, err := testutil.ReadBody(body)
|
||||
buf, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out := string(buf)
|
||||
|
@ -174,7 +173,7 @@ RUN echo from Dockerfile`,
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
buf, err := testutil.ReadBody(body)
|
||||
buf, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out := string(buf)
|
||||
|
@ -196,7 +195,7 @@ RUN echo from dockerfile`,
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
buf, err := testutil.ReadBody(body)
|
||||
buf, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out := string(buf)
|
||||
|
@ -243,7 +242,7 @@ func (s *DockerSuite) TestBuildAPIUnnormalizedTarPaths(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
out, err := testutil.ReadBody(body)
|
||||
out, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
lines := strings.Split(string(out), "\n")
|
||||
c.Assert(len(lines), checker.GreaterThan, 1)
|
||||
|
@ -280,7 +279,7 @@ func (s *DockerSuite) TestBuildOnBuildWithCopy(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
out, err := testutil.ReadBody(body)
|
||||
out, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(out), checker.Contains, "Successfully built")
|
||||
}
|
||||
|
@ -299,7 +298,7 @@ func (s *DockerSuite) TestBuildOnBuildCache(c *check.C) {
|
|||
require.NoError(c, err)
|
||||
assert.Equal(c, http.StatusOK, res.StatusCode)
|
||||
|
||||
out, err := testutil.ReadBody(body)
|
||||
out, err := request.ReadBody(body)
|
||||
require.NoError(c, err)
|
||||
assert.Contains(c, string(out), "Successfully built")
|
||||
return out
|
||||
|
@ -361,7 +360,7 @@ func (s *DockerRegistrySuite) TestBuildCopyFromForcePull(c *check.C) {
|
|||
require.NoError(c, err)
|
||||
assert.Equal(c, http.StatusOK, res.StatusCode)
|
||||
|
||||
out, err := testutil.ReadBody(body)
|
||||
out, err := request.ReadBody(body)
|
||||
require.NoError(c, err)
|
||||
assert.Contains(c, string(out), "Successfully built")
|
||||
}
|
||||
|
@ -405,7 +404,7 @@ func (s *DockerSuite) TestBuildAddRemoteNoDecompress(c *check.C) {
|
|||
require.NoError(c, err)
|
||||
assert.Equal(c, http.StatusOK, res.StatusCode)
|
||||
|
||||
out, err := testutil.ReadBody(body)
|
||||
out, err := request.ReadBody(body)
|
||||
require.NoError(c, err)
|
||||
assert.Contains(c, string(out), "Successfully built")
|
||||
}
|
||||
|
@ -461,7 +460,7 @@ func (s *DockerSuite) TestBuildWithSession(c *check.C) {
|
|||
require.NoError(c, err)
|
||||
assert.Equal(c, http.StatusOK, res.StatusCode)
|
||||
|
||||
outBytes, err := testutil.ReadBody(body)
|
||||
outBytes, err := request.ReadBody(body)
|
||||
require.NoError(c, err)
|
||||
assert.Contains(c, string(outBytes), "Successfully built")
|
||||
assert.Equal(c, strings.Count(string(outBytes), "Using cache"), 4)
|
||||
|
@ -499,7 +498,7 @@ func testBuildWithSession(c *check.C, dir, dockerfile string) (outStr string) {
|
|||
return err
|
||||
}
|
||||
assert.Equal(c, res.StatusCode, http.StatusOK)
|
||||
out, err := testutil.ReadBody(body)
|
||||
out, err := request.ReadBody(body)
|
||||
require.NoError(c, err)
|
||||
assert.Contains(c, string(out), "Successfully built")
|
||||
sess.Close()
|
||||
|
|
|
@ -27,7 +27,6 @@ import (
|
|||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/docker/docker/volume"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
@ -215,7 +214,7 @@ func (s *DockerSuite) TestGetContainerStatsRmRunning(c *check.C) {
|
|||
out := runSleepingContainer(c)
|
||||
id := strings.TrimSpace(out)
|
||||
|
||||
buf := &testutil.ChannelBuffer{C: make(chan []byte, 1)}
|
||||
buf := &ChannelBuffer{C: make(chan []byte, 1)}
|
||||
defer buf.Close()
|
||||
|
||||
_, body, err := request.Get("/containers/"+id+"/stats?stream=1", request.JSON)
|
||||
|
@ -243,6 +242,34 @@ func (s *DockerSuite) TestGetContainerStatsRmRunning(c *check.C) {
|
|||
c.Assert(<-chErr, checker.IsNil)
|
||||
}
|
||||
|
||||
// ChannelBuffer holds a chan of byte array that can be populate in a goroutine.
|
||||
type ChannelBuffer struct {
|
||||
C chan []byte
|
||||
}
|
||||
|
||||
// Write implements Writer.
|
||||
func (c *ChannelBuffer) Write(b []byte) (int, error) {
|
||||
c.C <- b
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// Close closes the go channel.
|
||||
func (c *ChannelBuffer) Close() error {
|
||||
close(c.C)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadTimeout reads the content of the channel in the specified byte array with
|
||||
// the specified duration as timeout.
|
||||
func (c *ChannelBuffer) ReadTimeout(p []byte, n time.Duration) (int, error) {
|
||||
select {
|
||||
case b := <-c.C:
|
||||
return copy(p[0:], b), nil
|
||||
case <-time.After(n):
|
||||
return -1, fmt.Errorf("timeout reading from channel")
|
||||
}
|
||||
}
|
||||
|
||||
// regression test for gh13421
|
||||
// previous test was just checking one stat entry so it didn't fail (stats with
|
||||
// stream false always return one stat)
|
||||
|
@ -707,7 +734,7 @@ func (s *DockerSuite) TestContainerAPIInvalidPortSyntax(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(b[:]), checker.Contains, "invalid port")
|
||||
}
|
||||
|
@ -727,7 +754,7 @@ func (s *DockerSuite) TestContainerAPIRestartPolicyInvalidPolicyName(c *check.C)
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(b[:]), checker.Contains, "invalid restart policy")
|
||||
}
|
||||
|
@ -747,7 +774,7 @@ func (s *DockerSuite) TestContainerAPIRestartPolicyRetryMismatch(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(b[:]), checker.Contains, "maximum retry count cannot be used with restart policy")
|
||||
}
|
||||
|
@ -767,7 +794,7 @@ func (s *DockerSuite) TestContainerAPIRestartPolicyNegativeRetryCount(c *check.C
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(b[:]), checker.Contains, "maximum retry count cannot be negative")
|
||||
}
|
||||
|
@ -818,7 +845,7 @@ func (s *DockerSuite) TestContainerAPIPostCreateNull(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusCreated)
|
||||
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
type createResp struct {
|
||||
ID string
|
||||
|
@ -847,7 +874,7 @@ func (s *DockerSuite) TestCreateWithTooLowMemoryLimit(c *check.C) {
|
|||
|
||||
res, body, err := request.Post("/containers/create", request.RawString(config), request.JSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
b, err2 := testutil.ReadBody(body)
|
||||
b, err2 := request.ReadBody(body)
|
||||
c.Assert(err2, checker.IsNil)
|
||||
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
|
@ -42,7 +41,7 @@ func (s *DockerSuite) TestExecAPICreateNoValidContentType(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
comment := check.Commentf("Expected message when creating exec command with invalid Content-Type specified")
|
||||
|
@ -109,7 +108,7 @@ func (s *DockerSuite) TestExecAPIStartBackwardsCompatible(c *check.C) {
|
|||
resp, body, err := request.Post(fmt.Sprintf("/v1.20/exec/%s/start", id), request.RawString(`{"Detach": true}`), request.ContentType("text/plain"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
comment := check.Commentf("response body: %s", b)
|
||||
c.Assert(err, checker.IsNil, comment)
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusOK, comment)
|
||||
|
@ -144,7 +143,7 @@ func (s *DockerSuite) TestExecAPIStartWithDetach(c *check.C) {
|
|||
_, body, err := request.Post(fmt.Sprintf("/exec/%s/start", createResp.ID), request.RawString(`{"Detach": true}`), request.JSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
b, err = testutil.ReadBody(body)
|
||||
b, err = request.ReadBody(body)
|
||||
comment := check.Commentf("response body: %s", b)
|
||||
c.Assert(err, checker.IsNil, comment)
|
||||
|
||||
|
@ -207,7 +206,7 @@ func startExec(c *check.C, id string, code int) {
|
|||
resp, body, err := request.Post(fmt.Sprintf("/exec/%s/start", id), request.RawString(`{"Detach": true}`), request.JSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
comment := check.Commentf("response body: %s", b)
|
||||
c.Assert(err, checker.IsNil, comment)
|
||||
c.Assert(resp.StatusCode, checker.Equals, code, comment)
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"encoding/json"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
|
@ -52,7 +51,7 @@ func (s *DockerSuite) TestInfoAPIRuncCommit(c *check.C) {
|
|||
c.Assert(res.StatusCode, checker.Equals, http.StatusOK)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
var i types.Info
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
|
@ -29,7 +28,7 @@ func (s *DockerSuite) TestSessionCreateWithBadUpgrade(c *check.C) {
|
|||
res, body, err := request.Post("/session")
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
buf, err := testutil.ReadBody(body)
|
||||
buf, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out := string(buf)
|
||||
|
@ -41,7 +40,7 @@ func (s *DockerSuite) TestSessionCreateWithBadUpgrade(c *check.C) {
|
|||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
buf, err = testutil.ReadBody(body)
|
||||
buf, err = request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
out = string(buf)
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
|
@ -62,7 +61,7 @@ func (s *DockerSuite) TestAPIErrorJSON(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(httpResp.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
c.Assert(httpResp.Header.Get("Content-Type"), checker.Equals, "application/json")
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(getErrorMessage(c, b), checker.Equals, "Config cannot be empty in order to create a container")
|
||||
}
|
||||
|
@ -75,7 +74,7 @@ func (s *DockerSuite) TestAPIErrorPlainText(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(httpResp.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
c.Assert(httpResp.Header.Get("Content-Type"), checker.Contains, "text/plain")
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(strings.TrimSpace(string(b)), checker.Equals, "Config cannot be empty in order to create a container")
|
||||
}
|
||||
|
@ -86,7 +85,7 @@ func (s *DockerSuite) TestAPIErrorNotFoundJSON(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(httpResp.StatusCode, checker.Equals, http.StatusNotFound)
|
||||
c.Assert(httpResp.Header.Get("Content-Type"), checker.Equals, "application/json")
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(getErrorMessage(c, b), checker.Equals, "page not found")
|
||||
}
|
||||
|
@ -96,7 +95,7 @@ func (s *DockerSuite) TestAPIErrorNotFoundPlainText(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(httpResp.StatusCode, checker.Equals, http.StatusNotFound)
|
||||
c.Assert(httpResp.Header.Get("Content-Type"), checker.Contains, "text/plain")
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(strings.TrimSpace(string(b)), checker.Equals, "page not found")
|
||||
}
|
||||
|
|
|
@ -25,10 +25,9 @@ import (
|
|||
"github.com/docker/docker/integration-cli/cli/build/fakestorage"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/stringutils"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/go-check/check"
|
||||
"github.com/opencontainers/go-digest"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestBuildJSONEmptyRun(c *check.C) {
|
||||
|
@ -1526,7 +1525,7 @@ func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
|
|||
if err != nil {
|
||||
c.Fatalf("failed to list contents of tmp dir: %s", err)
|
||||
}
|
||||
if err = testutil.CompareDirectoryEntries(entries, entriesFinal); err != nil {
|
||||
if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
|
||||
c.Fatalf("context should have been deleted, but wasn't")
|
||||
}
|
||||
|
||||
|
@ -1550,12 +1549,31 @@ func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
|
|||
if err != nil {
|
||||
c.Fatalf("failed to list contents of tmp dir: %s", err)
|
||||
}
|
||||
if err = testutil.CompareDirectoryEntries(entries, entriesFinal); err != nil {
|
||||
if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
|
||||
c.Fatalf("context should have been deleted, but wasn't")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// compareDirectoryEntries compares two sets of FileInfo (usually taken from a directory)
|
||||
// and returns an error if different.
|
||||
func compareDirectoryEntries(e1 []os.FileInfo, e2 []os.FileInfo) error {
|
||||
var (
|
||||
e1Entries = make(map[string]struct{})
|
||||
e2Entries = make(map[string]struct{})
|
||||
)
|
||||
for _, e := range e1 {
|
||||
e1Entries[e.Name()] = struct{}{}
|
||||
}
|
||||
for _, e := range e2 {
|
||||
e2Entries[e.Name()] = struct{}{}
|
||||
}
|
||||
if !reflect.DeepEqual(e1Entries, e2Entries) {
|
||||
return fmt.Errorf("entries differ")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildCmd(c *check.C) {
|
||||
name := "testbuildcmd"
|
||||
expected := "[/bin/echo Hello World]"
|
||||
|
@ -4052,7 +4070,7 @@ func (s *DockerSuite) TestBuildContainerWithCgroupParent(c *check.C) {
|
|||
if err != nil {
|
||||
c.Fatalf("failed to read '/proc/self/cgroup - %v", err)
|
||||
}
|
||||
selfCgroupPaths := testutil.ParseCgroupPaths(string(data))
|
||||
selfCgroupPaths := ParseCgroupPaths(string(data))
|
||||
_, found := selfCgroupPaths["memory"]
|
||||
if !found {
|
||||
c.Fatalf("unable to find self memory cgroup path. CgroupsPath: %v", selfCgroupPaths)
|
||||
|
|
|
@ -12,15 +12,15 @@ import (
|
|||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/integration-cli/cli/build"
|
||||
"github.com/docker/docker/integration-cli/cli/build/fakecontext"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/docker/go-units"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
|
@ -191,7 +191,7 @@ func (s *DockerSuite) TestBuildCancellationKillsSleep(c *check.C) {
|
|||
}
|
||||
|
||||
// Get the exit status of `docker build`, check it exited because killed.
|
||||
if err := buildCmd.Wait(); err != nil && !testutil.IsKilled(err) {
|
||||
if err := buildCmd.Wait(); err != nil && !isKilled(err) {
|
||||
c.Fatalf("wait failed during build run: %T %s", err, err)
|
||||
}
|
||||
|
||||
|
@ -202,3 +202,17 @@ func (s *DockerSuite) TestBuildCancellationKillsSleep(c *check.C) {
|
|||
// ignore, done
|
||||
}
|
||||
}
|
||||
|
||||
func isKilled(err error) bool {
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
status, ok := exitErr.Sys().(syscall.WaitStatus)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
// status.ExitStatus() is required on Windows because it does not
|
||||
// implement Signal() nor Signaled(). Just check it had a bad exit
|
||||
// status could mean it was killed (and in tests we do kill)
|
||||
return (status.Signaled() && status.Signal() == os.Kill) || status.ExitStatus() != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
@ -548,7 +547,7 @@ func (s *DockerSuite) TestCpToStdout(c *check.C) {
|
|||
// failed to set up container
|
||||
c.Assert(strings.TrimSpace(out), checker.Equals, "0")
|
||||
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "cp", containerID+":/test", "-"),
|
||||
exec.Command("tar", "-vtf", "-"))
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ import (
|
|||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
units "github.com/docker/go-units"
|
||||
"github.com/docker/libnetwork/iptables"
|
||||
|
@ -202,7 +201,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithInvalidBasesize(c *check.C) {
|
|||
testRequires(c, Devicemapper)
|
||||
s.d.Start(c)
|
||||
|
||||
oldBasesizeBytes := s.d.GetBaseDeviceSize(c)
|
||||
oldBasesizeBytes := getBaseDeviceSize(c, s.d)
|
||||
var newBasesizeBytes int64 = 1073741824 //1GB in bytes
|
||||
|
||||
if newBasesizeBytes < oldBasesizeBytes {
|
||||
|
@ -222,7 +221,7 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithIncreasedBasesize(c *check.C) {
|
|||
testRequires(c, Devicemapper)
|
||||
s.d.Start(c)
|
||||
|
||||
oldBasesizeBytes := s.d.GetBaseDeviceSize(c)
|
||||
oldBasesizeBytes := getBaseDeviceSize(c, s.d)
|
||||
|
||||
var newBasesizeBytes int64 = 53687091200 //50GB in bytes
|
||||
|
||||
|
@ -233,13 +232,31 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithIncreasedBasesize(c *check.C) {
|
|||
err := s.d.RestartWithError("--storage-opt", fmt.Sprintf("dm.basesize=%d", newBasesizeBytes))
|
||||
c.Assert(err, check.IsNil, check.Commentf("we should have been able to start the daemon with increased base device size: %v", err))
|
||||
|
||||
basesizeAfterRestart := s.d.GetBaseDeviceSize(c)
|
||||
basesizeAfterRestart := getBaseDeviceSize(c, s.d)
|
||||
newBasesize, err := convertBasesize(newBasesizeBytes)
|
||||
c.Assert(err, check.IsNil, check.Commentf("Error in converting base device size: %v", err))
|
||||
c.Assert(newBasesize, check.Equals, basesizeAfterRestart, check.Commentf("Basesize passed is not equal to Basesize set"))
|
||||
s.d.Stop(c)
|
||||
}
|
||||
|
||||
func getBaseDeviceSize(c *check.C, d *daemon.Daemon) int64 {
|
||||
info := d.Info(c)
|
||||
for _, statusLine := range info.DriverStatus {
|
||||
key, value := statusLine[0], statusLine[1]
|
||||
if key == "Base Device Size" {
|
||||
return parseDeviceSize(c, value)
|
||||
}
|
||||
}
|
||||
c.Fatal("failed to parse Base Device Size from info")
|
||||
return int64(0)
|
||||
}
|
||||
|
||||
func parseDeviceSize(c *check.C, raw string) int64 {
|
||||
size, err := units.RAMInBytes(strings.TrimSpace(raw))
|
||||
c.Assert(err, check.IsNil)
|
||||
return size
|
||||
}
|
||||
|
||||
func convertBasesize(basesizeBytes int64) (int64, error) {
|
||||
basesize := units.HumanSize(float64(basesizeBytes))
|
||||
basesize = strings.Trim(basesize, " ")[:len(basesize)-3]
|
||||
|
@ -1883,7 +1900,7 @@ func (s *DockerDaemonSuite) TestDaemonCgroupParent(c *check.C) {
|
|||
|
||||
out, err := s.d.Cmd("run", "--name", name, "busybox", "cat", "/proc/self/cgroup")
|
||||
c.Assert(err, checker.IsNil)
|
||||
cgroupPaths := testutil.ParseCgroupPaths(string(out))
|
||||
cgroupPaths := ParseCgroupPaths(string(out))
|
||||
c.Assert(len(cgroupPaths), checker.Not(checker.Equals), 0, check.Commentf("unexpected output - %q", string(out)))
|
||||
out, err = s.d.Cmd("inspect", "-f", "{{.Id}}", name)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/integration-cli/cli/build"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
@ -230,7 +229,7 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) {
|
|||
cleanedContainerID := strings.TrimSpace(out)
|
||||
|
||||
since := daemonUnixTime(c)
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "export", cleanedContainerID),
|
||||
exec.Command(dockerBinary, "import", "-"),
|
||||
)
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
@ -21,7 +20,7 @@ func (s *DockerSuite) TestImportDisplay(c *check.C) {
|
|||
out, _ := dockerCmd(c, "run", "-d", "busybox", "true")
|
||||
cleanedContainerID := strings.TrimSpace(out)
|
||||
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "export", cleanedContainerID),
|
||||
exec.Command(dockerBinary, "import", "-"),
|
||||
)
|
||||
|
|
|
@ -4,10 +4,10 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
@ -90,40 +90,41 @@ func (s *DockerSuite) TestLinksPingLinkedContainersAfterRename(c *check.C) {
|
|||
|
||||
func (s *DockerSuite) TestLinksInspectLinksStarted(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
var (
|
||||
expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
|
||||
result []string
|
||||
)
|
||||
dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
|
||||
dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
|
||||
dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "top")
|
||||
links := inspectFieldJSON(c, "testinspectlink", "HostConfig.Links")
|
||||
|
||||
var result []string
|
||||
err := json.Unmarshal([]byte(links), &result)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
output := testutil.ConvertSliceOfStringsToMap(result)
|
||||
|
||||
c.Assert(output, checker.DeepEquals, expected)
|
||||
var expected = []string{
|
||||
"/container1:/testinspectlink/alias1",
|
||||
"/container2:/testinspectlink/alias2",
|
||||
}
|
||||
sort.Strings(result)
|
||||
c.Assert(result, checker.DeepEquals, expected)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLinksInspectLinksStopped(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
var (
|
||||
expected = map[string]struct{}{"/container1:/testinspectlink/alias1": {}, "/container2:/testinspectlink/alias2": {}}
|
||||
result []string
|
||||
)
|
||||
|
||||
dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
|
||||
dockerCmd(c, "run", "-d", "--name", "container2", "busybox", "top")
|
||||
dockerCmd(c, "run", "-d", "--name", "testinspectlink", "--link", "container1:alias1", "--link", "container2:alias2", "busybox", "true")
|
||||
links := inspectFieldJSON(c, "testinspectlink", "HostConfig.Links")
|
||||
|
||||
var result []string
|
||||
err := json.Unmarshal([]byte(links), &result)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
output := testutil.ConvertSliceOfStringsToMap(result)
|
||||
|
||||
c.Assert(output, checker.DeepEquals, expected)
|
||||
var expected = []string{
|
||||
"/container1:/testinspectlink/alias1",
|
||||
"/container2:/testinspectlink/alias2",
|
||||
}
|
||||
sort.Strings(result)
|
||||
c.Assert(result, checker.DeepEquals, expected)
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLinksNotStartedParentNotFail(c *check.C) {
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/pkg/jsonlog"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
@ -232,11 +231,11 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
|
|||
c.Assert(logCmd.Start(), checker.IsNil)
|
||||
|
||||
// First read slowly
|
||||
bytes1, err := testutil.ConsumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead)
|
||||
bytes1, err := ConsumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// After the container has finished we can continue reading fast
|
||||
bytes2, err := testutil.ConsumeWithSpeed(stdout, 32*1024, 0, nil)
|
||||
bytes2, err := ConsumeWithSpeed(stdout, 32*1024, 0, nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
actual := bytes1 + bytes2
|
||||
|
@ -244,6 +243,29 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
|
|||
c.Assert(actual, checker.Equals, expected)
|
||||
}
|
||||
|
||||
// ConsumeWithSpeed reads chunkSize bytes from reader before sleeping
|
||||
// for interval duration. Returns total read bytes. Send true to the
|
||||
// stop channel to return before reading to EOF on the reader.
|
||||
func ConsumeWithSpeed(reader io.Reader, chunkSize int, interval time.Duration, stop chan bool) (n int, err error) {
|
||||
buffer := make([]byte, chunkSize)
|
||||
for {
|
||||
var readBytes int
|
||||
readBytes, err = reader.Read(buffer)
|
||||
n += readBytes
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-stop:
|
||||
return
|
||||
case <-time.After(interval):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestLogsFollowGoroutinesWithStdout(c *check.C) {
|
||||
out, _ := dockerCmd(c, "run", "-d", "busybox", "/bin/sh", "-c", "while true; do echo hello; sleep 2; done")
|
||||
id := strings.TrimSpace(out)
|
||||
|
|
|
@ -28,7 +28,6 @@ import (
|
|||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/stringutils"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/docker/docker/runconfig"
|
||||
"github.com/docker/go-connections/nat"
|
||||
|
@ -495,7 +494,7 @@ func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) {
|
|||
func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
|
||||
testRequires(c, SameHostDaemon)
|
||||
prefix, slash := getPrefixAndSlashFromDaemonPlatform()
|
||||
hostpath := testutil.RandomTmpDirPath("test", testEnv.DaemonPlatform())
|
||||
hostpath := RandomTmpDirPath("test", testEnv.DaemonPlatform())
|
||||
if err := os.MkdirAll(hostpath, 0755); err != nil {
|
||||
c.Fatalf("Failed to create %s: %q", hostpath, err)
|
||||
}
|
||||
|
@ -518,8 +517,8 @@ func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
|
|||
|
||||
// Test for GH#10618
|
||||
func (s *DockerSuite) TestRunNoDupVolumes(c *check.C) {
|
||||
path1 := testutil.RandomTmpDirPath("test1", testEnv.DaemonPlatform())
|
||||
path2 := testutil.RandomTmpDirPath("test2", testEnv.DaemonPlatform())
|
||||
path1 := RandomTmpDirPath("test1", testEnv.DaemonPlatform())
|
||||
path2 := RandomTmpDirPath("test2", testEnv.DaemonPlatform())
|
||||
|
||||
someplace := ":/someplace"
|
||||
if testEnv.DaemonPlatform() == "windows" {
|
||||
|
@ -2183,7 +2182,7 @@ func (s *DockerSuite) TestVolumesNoCopyData(c *check.C) {
|
|||
c.Fatalf("Data was copied on volumes-from but shouldn't be:\n%q", out)
|
||||
}
|
||||
|
||||
tmpDir := testutil.RandomTmpDirPath("docker_test_bind_mount_copy_data", testEnv.DaemonPlatform())
|
||||
tmpDir := RandomTmpDirPath("docker_test_bind_mount_copy_data", testEnv.DaemonPlatform())
|
||||
if out, _, err := dockerCmdWithError("run", "-v", tmpDir+":/foo", "dataimage", "ls", "-lh", "/foo/bar"); err == nil || !strings.Contains(out, "No such file or directory") {
|
||||
c.Fatalf("Data was copied on bind mount but shouldn't be:\n%q", out)
|
||||
}
|
||||
|
@ -2247,7 +2246,7 @@ func (s *DockerSuite) TestRunSlowStdoutConsumer(c *check.C) {
|
|||
if err := cont.Start(); err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
n, err := testutil.ConsumeWithSpeed(stdout, 10000, 5*time.Millisecond, nil)
|
||||
n, err := ConsumeWithSpeed(stdout, 10000, 5*time.Millisecond, nil)
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
|
@ -3337,7 +3336,7 @@ func testRunContainerWithCgroupParent(c *check.C, cgroupParent, name string) {
|
|||
if err != nil {
|
||||
c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
|
||||
}
|
||||
cgroupPaths := testutil.ParseCgroupPaths(string(out))
|
||||
cgroupPaths := ParseCgroupPaths(string(out))
|
||||
if len(cgroupPaths) == 0 {
|
||||
c.Fatalf("unexpected output - %q", string(out))
|
||||
}
|
||||
|
@ -3377,7 +3376,7 @@ func testRunInvalidCgroupParent(c *check.C, cgroupParent, cleanCgroupParent, nam
|
|||
c.Fatalf("SECURITY: --cgroup-parent with ../../ relative paths cause files to be created in the host (this is bad) !!")
|
||||
}
|
||||
|
||||
cgroupPaths := testutil.ParseCgroupPaths(string(out))
|
||||
cgroupPaths := ParseCgroupPaths(string(out))
|
||||
if len(cgroupPaths) == 0 {
|
||||
c.Fatalf("unexpected output - %q", string(out))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -15,10 +17,9 @@ import (
|
|||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli/build"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/go-check/check"
|
||||
"github.com/opencontainers/go-digest"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
// save a repo using gz compression and try to load it using stdout
|
||||
|
@ -32,7 +33,7 @@ func (s *DockerSuite) TestSaveXzAndLoadRepoStdout(c *check.C) {
|
|||
|
||||
dockerCmd(c, "inspect", repoName)
|
||||
|
||||
repoTarball, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
repoTarball, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", repoName),
|
||||
exec.Command("xz", "-c"),
|
||||
exec.Command("gzip", "-c"))
|
||||
|
@ -61,7 +62,7 @@ func (s *DockerSuite) TestSaveXzGzAndLoadRepoStdout(c *check.C) {
|
|||
|
||||
dockerCmd(c, "inspect", repoName)
|
||||
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", repoName),
|
||||
exec.Command("xz", "-c"),
|
||||
exec.Command("gzip", "-c"))
|
||||
|
@ -88,7 +89,7 @@ func (s *DockerSuite) TestSaveSingleTag(c *check.C) {
|
|||
out, _ := dockerCmd(c, "images", "-q", "--no-trunc", repoName)
|
||||
cleanedImageID := strings.TrimSpace(out)
|
||||
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", fmt.Sprintf("%v:latest", repoName)),
|
||||
exec.Command("tar", "t"),
|
||||
exec.Command("grep", "-E", fmt.Sprintf("(^repositories$|%v)", cleanedImageID)))
|
||||
|
@ -107,7 +108,7 @@ func (s *DockerSuite) TestSaveCheckTimes(c *check.C) {
|
|||
c.Assert(err, checker.IsNil, check.Commentf("failed to marshal from %q: err %v", repoName, err))
|
||||
c.Assert(len(data), checker.Not(checker.Equals), 0, check.Commentf("failed to marshal the data from %q", repoName))
|
||||
tarTvTimeFormat := "2006-01-02 15:04"
|
||||
out, _, err = testutil.RunCommandPipelineWithOutput(
|
||||
out, err = RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", repoName),
|
||||
exec.Command("tar", "tv"),
|
||||
exec.Command("grep", "-E", fmt.Sprintf("%s %s", data[0].Created.Format(tarTvTimeFormat), digest.Digest(data[0].ID).Hex())))
|
||||
|
@ -165,7 +166,7 @@ func (s *DockerSuite) TestSaveAndLoadRepoFlags(c *check.C) {
|
|||
|
||||
before, _ := dockerCmd(c, "inspect", repoName)
|
||||
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", repoName),
|
||||
exec.Command(dockerBinary, "load"))
|
||||
c.Assert(err, checker.IsNil, check.Commentf("failed to save and load repo: %s, %v", out, err))
|
||||
|
@ -194,7 +195,7 @@ func (s *DockerSuite) TestSaveMultipleNames(c *check.C) {
|
|||
// Make two images
|
||||
dockerCmd(c, "tag", "emptyfs:latest", fmt.Sprintf("%v-two:latest", repoName))
|
||||
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", fmt.Sprintf("%v-one", repoName), fmt.Sprintf("%v-two:latest", repoName)),
|
||||
exec.Command("tar", "xO", "repositories"),
|
||||
exec.Command("grep", "-q", "-E", "(-one|-two)"),
|
||||
|
@ -226,7 +227,7 @@ func (s *DockerSuite) TestSaveRepoWithMultipleImages(c *check.C) {
|
|||
deleteImages(repoName)
|
||||
|
||||
// create the archive
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", repoName, "busybox:latest"),
|
||||
exec.Command("tar", "t"))
|
||||
c.Assert(err, checker.IsNil, check.Commentf("failed to save multiple images: %s, %v", out, err))
|
||||
|
@ -270,7 +271,7 @@ func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
|
|||
RUN adduser -D user && mkdir -p /opt/a/b && chown -R user:user /opt/a
|
||||
RUN touch /opt/a/b/c && chown user:user /opt/a/b/c`))
|
||||
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", name),
|
||||
exec.Command("tar", "-xf", "-", "-C", extractionDirectory),
|
||||
)
|
||||
|
@ -289,7 +290,7 @@ func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
|
|||
c.Assert(err, checker.IsNil, check.Commentf("failed to open %s: %s", layerPath, err))
|
||||
defer f.Close()
|
||||
|
||||
entries, err := testutil.ListTar(f)
|
||||
entries, err := listTar(f)
|
||||
for _, e := range entries {
|
||||
if !strings.Contains(e, "dev/") {
|
||||
entriesSansDev = append(entriesSansDev, e)
|
||||
|
@ -308,6 +309,23 @@ func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
|
|||
|
||||
}
|
||||
|
||||
func listTar(f io.Reader) ([]string, error) {
|
||||
tr := tar.NewReader(f)
|
||||
var entries []string
|
||||
|
||||
for {
|
||||
th, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
// end of tar archive
|
||||
return entries, nil
|
||||
}
|
||||
if err != nil {
|
||||
return entries, err
|
||||
}
|
||||
entries = append(entries, th.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Test loading a weird image where one of the layers is of zero size.
|
||||
// The layer.tar file is actually zero bytes, no padding or anything else.
|
||||
// See issue: 18170
|
||||
|
@ -365,7 +383,7 @@ func (s *DockerSuite) TestSaveLoadNoTag(c *check.C) {
|
|||
id := inspectField(c, name, "Id")
|
||||
|
||||
// Test to make sure that save w/o name just shows imageID during load
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err := RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", id),
|
||||
exec.Command(dockerBinary, "load"))
|
||||
c.Assert(err, checker.IsNil, check.Commentf("failed to save and load repo: %s, %v", out, err))
|
||||
|
@ -376,7 +394,7 @@ func (s *DockerSuite) TestSaveLoadNoTag(c *check.C) {
|
|||
c.Assert(out, checker.Contains, id)
|
||||
|
||||
// Test to make sure that save by name shows that name during load
|
||||
out, _, err = testutil.RunCommandPipelineWithOutput(
|
||||
out, err = RunCommandPipelineWithOutput(
|
||||
exec.Command(dockerBinary, "save", name),
|
||||
exec.Command(dockerBinary, "load"))
|
||||
c.Assert(err, checker.IsNil, check.Commentf("failed to save and load repo: %s, %v", out, err))
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -23,7 +22,6 @@ import (
|
|||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/cli"
|
||||
"github.com/docker/docker/integration-cli/daemon"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
icmd "github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/docker/docker/pkg/testutil/tempfile"
|
||||
"github.com/docker/libnetwork/driverapi"
|
||||
|
@ -467,14 +465,17 @@ func (s *DockerSwarmSuite) TestSwarmIngressNetwork(c *check.C) {
|
|||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
// Ingress network can be removed
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
exec.Command("echo", "Y"),
|
||||
exec.Command("docker", "-H", d.Sock(), "network", "rm", "ingress"),
|
||||
)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
removeNetwork := func(name string) *icmd.Result {
|
||||
return cli.Docker(
|
||||
cli.Args("-H", d.Sock(), "network", "rm", name),
|
||||
cli.WithStdin(strings.NewReader("Y")))
|
||||
}
|
||||
|
||||
result := removeNetwork("ingress")
|
||||
result.Assert(c, icmd.Success)
|
||||
|
||||
// And recreated
|
||||
out, err = d.Cmd("network", "create", "-d", "overlay", "--ingress", "new-ingress")
|
||||
out, err := d.Cmd("network", "create", "-d", "overlay", "--ingress", "new-ingress")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
// But only one is allowed
|
||||
|
@ -485,21 +486,19 @@ func (s *DockerSwarmSuite) TestSwarmIngressNetwork(c *check.C) {
|
|||
// It cannot be removed if it is being used
|
||||
out, err = d.Cmd("service", "create", "--no-resolve-image", "--name", "srv1", "-p", "9000:8000", "busybox", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
out, _, err = testutil.RunCommandPipelineWithOutput(
|
||||
exec.Command("echo", "Y"),
|
||||
exec.Command("docker", "-H", d.Sock(), "network", "rm", "new-ingress"),
|
||||
)
|
||||
c.Assert(err, checker.NotNil)
|
||||
c.Assert(strings.TrimSpace(out), checker.Contains, "ingress network cannot be removed because service")
|
||||
|
||||
result = removeNetwork("new-ingress")
|
||||
result.Assert(c, icmd.Expected{
|
||||
ExitCode: 1,
|
||||
Err: "ingress network cannot be removed because service",
|
||||
})
|
||||
|
||||
// But it can be removed once no more services depend on it
|
||||
out, err = d.Cmd("service", "update", "--publish-rm", "9000:8000", "srv1")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
out, _, err = testutil.RunCommandPipelineWithOutput(
|
||||
exec.Command("echo", "Y"),
|
||||
exec.Command("docker", "-H", d.Sock(), "network", "rm", "new-ingress"),
|
||||
)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
||||
result = removeNetwork("new-ingress")
|
||||
result.Assert(c, icmd.Success)
|
||||
|
||||
// A service which needs the ingress network cannot be created if no ingress is present
|
||||
out, err = d.Cmd("service", "create", "--no-resolve-image", "--name", "srv2", "-p", "500:500", "busybox", "top")
|
||||
|
@ -520,15 +519,14 @@ func (s *DockerSwarmSuite) TestSwarmCreateServiceWithNoIngressNetwork(c *check.C
|
|||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
// Remove ingress network
|
||||
out, _, err := testutil.RunCommandPipelineWithOutput(
|
||||
exec.Command("echo", "Y"),
|
||||
exec.Command("docker", "-H", d.Sock(), "network", "rm", "ingress"),
|
||||
)
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
result := cli.Docker(
|
||||
cli.Args("-H", d.Sock(), "network", "rm", "ingress"),
|
||||
cli.WithStdin(strings.NewReader("Y")))
|
||||
result.Assert(c, icmd.Success)
|
||||
|
||||
// Create a overlay network and launch a service on it
|
||||
// Make sure nothing panics because ingress network is missing
|
||||
out, err = d.Cmd("network", "create", "-d", "overlay", "another-network")
|
||||
out, err := d.Cmd("network", "create", "-d", "overlay", "another-network")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
out, err = d.Cmd("service", "create", "--no-resolve-image", "--name", "srv4", "--network", "another-network", "busybox", "top")
|
||||
c.Assert(err, checker.IsNil, check.Commentf(out))
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
|
@ -62,15 +61,15 @@ func (s *DockerDaemonSuite) TestDaemonUserNamespaceRootSetting(c *check.C) {
|
|||
c.Assert(err, checker.IsNil, check.Commentf("Could not inspect running container: out: %q", pid))
|
||||
// check the uid and gid maps for the PID to ensure root is remapped
|
||||
// (cmd = cat /proc/<pid>/uid_map | grep -E '0\s+9999\s+1')
|
||||
out, rc1, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err = RunCommandPipelineWithOutput(
|
||||
exec.Command("cat", "/proc/"+strings.TrimSpace(pid)+"/uid_map"),
|
||||
exec.Command("grep", "-E", fmt.Sprintf("0[[:space:]]+%d[[:space:]]+", uid)))
|
||||
c.Assert(rc1, checker.Equals, 0, check.Commentf("Didn't match uid_map: output: %s", out))
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
out, rc2, err := testutil.RunCommandPipelineWithOutput(
|
||||
out, err = RunCommandPipelineWithOutput(
|
||||
exec.Command("cat", "/proc/"+strings.TrimSpace(pid)+"/gid_map"),
|
||||
exec.Command("grep", "-E", fmt.Sprintf("0[[:space:]]+%d[[:space:]]+", gid)))
|
||||
c.Assert(rc2, checker.Equals, 0, check.Commentf("Didn't match gid_map: output: %s", out))
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
// check that the touched file is owned by remapped uid:gid
|
||||
stat, err := system.Stat(filepath.Join(tmpDir, "testfile"))
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/integration-cli/request"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
|
@ -45,7 +44,7 @@ func (s *DockerSuite) TestDeprecatedContainerAPIStartVolumeBinds(c *check.C) {
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusCreated)
|
||||
|
||||
bindPath := testutil.RandomTmpDirPath("test", testEnv.DaemonPlatform())
|
||||
bindPath := RandomTmpDirPath("test", testEnv.DaemonPlatform())
|
||||
config = map[string]interface{}{
|
||||
"Binds": []string{bindPath + ":" + path},
|
||||
}
|
||||
|
@ -72,8 +71,8 @@ func (s *DockerSuite) TestDeprecatedContainerAPIStartDupVolumeBinds(c *check.C)
|
|||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(status, checker.Equals, http.StatusCreated)
|
||||
|
||||
bindPath1 := testutil.RandomTmpDirPath("test1", testEnv.DaemonPlatform())
|
||||
bindPath2 := testutil.RandomTmpDirPath("test2", testEnv.DaemonPlatform())
|
||||
bindPath1 := RandomTmpDirPath("test1", testEnv.DaemonPlatform())
|
||||
bindPath2 := RandomTmpDirPath("test2", testEnv.DaemonPlatform())
|
||||
|
||||
config = map[string]interface{}{
|
||||
"Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"},
|
||||
|
@ -151,7 +150,7 @@ func (s *DockerSuite) TestDeprecatedStartWithTooLowMemoryLimit(c *check.C) {
|
|||
|
||||
res, body, err := request.Post(formatV123StartAPIURL("/containers/"+containerID+"/start"), request.RawString(config), request.JSON)
|
||||
c.Assert(err, checker.IsNil)
|
||||
b, err2 := testutil.ReadBody(body)
|
||||
b, err2 := request.ReadBody(body)
|
||||
c.Assert(err2, checker.IsNil)
|
||||
c.Assert(res.StatusCode, checker.Equals, http.StatusBadRequest)
|
||||
c.Assert(string(b), checker.Contains, "Minimum memory limit allowed is 4MB")
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
dclient "github.com/docker/docker/client"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/docker/go-connections/sockets"
|
||||
"github.com/docker/go-connections/tlsconfig"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -166,7 +165,11 @@ func NewHTTPClient(host string) (*http.Client, error) {
|
|||
|
||||
// NewClient returns a new Docker API client
|
||||
func NewClient() (dclient.APIClient, error) {
|
||||
host := DaemonHost()
|
||||
return NewClientForHost(DaemonHost())
|
||||
}
|
||||
|
||||
// NewClientForHost returns a Docker API client for the host
|
||||
func NewClientForHost(host string) (dclient.APIClient, error) {
|
||||
httpClient, err := NewHTTPClient(host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -214,10 +217,16 @@ func SockRequest(method, endpoint string, data interface{}, daemon string, modif
|
|||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
b, err := testutil.ReadBody(body)
|
||||
b, err := ReadBody(body)
|
||||
return res.StatusCode, b, err
|
||||
}
|
||||
|
||||
// ReadBody read the specified ReadCloser content and returns it
|
||||
func ReadBody(b io.ReadCloser) ([]byte, error) {
|
||||
defer b.Close()
|
||||
return ioutil.ReadAll(b)
|
||||
}
|
||||
|
||||
// SockRequestRaw create a request against the specified host (with method, endpoint and other request modifier) and
|
||||
// returns the http response, the output as a io.ReadCloser
|
||||
// Deprecated: use request.Do (or Get, Delete, Post) instead
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/stringutils"
|
||||
"github.com/docker/docker/pkg/testutil/cmd"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func getPrefixAndSlashFromDaemonPlatform() (prefix, slash string) {
|
||||
|
@ -30,3 +36,79 @@ func transformCmd(execCmd *exec.Cmd) cmd.Cmd {
|
|||
Stdout: execCmd.Stdout,
|
||||
}
|
||||
}
|
||||
|
||||
// ParseCgroupPaths parses 'procCgroupData', which is output of '/proc/<pid>/cgroup', and returns
|
||||
// a map which cgroup name as key and path as value.
|
||||
func ParseCgroupPaths(procCgroupData string) map[string]string {
|
||||
cgroupPaths := map[string]string{}
|
||||
for _, line := range strings.Split(procCgroupData, "\n") {
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) != 3 {
|
||||
continue
|
||||
}
|
||||
cgroupPaths[parts[1]] = parts[2]
|
||||
}
|
||||
return cgroupPaths
|
||||
}
|
||||
|
||||
// RandomTmpDirPath provides a temporary path with rand string appended.
|
||||
// does not create or checks if it exists.
|
||||
func RandomTmpDirPath(s string, platform string) string {
|
||||
// TODO: why doesn't this use os.TempDir() ?
|
||||
tmp := "/tmp"
|
||||
if platform == "windows" {
|
||||
tmp = os.Getenv("TEMP")
|
||||
}
|
||||
path := filepath.Join(tmp, fmt.Sprintf("%s.%s", s, stringutils.GenerateRandomAlphaOnlyString(10)))
|
||||
if platform == "windows" {
|
||||
return filepath.FromSlash(path) // Using \
|
||||
}
|
||||
return filepath.ToSlash(path) // Using /
|
||||
}
|
||||
|
||||
// RunCommandPipelineWithOutput runs the array of commands with the output
|
||||
// of each pipelined with the following (like cmd1 | cmd2 | cmd3 would do).
|
||||
// It returns the final output, the exitCode different from 0 and the error
|
||||
// if something bad happened.
|
||||
// Deprecated: use icmd instead
|
||||
func RunCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, err error) {
|
||||
if len(cmds) < 2 {
|
||||
return "", errors.New("pipeline does not have multiple cmds")
|
||||
}
|
||||
|
||||
// connect stdin of each cmd to stdout pipe of previous cmd
|
||||
for i, cmd := range cmds {
|
||||
if i > 0 {
|
||||
prevCmd := cmds[i-1]
|
||||
cmd.Stdin, err = prevCmd.StdoutPipe()
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot set stdout pipe for %s: %v", cmd.Path, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start all cmds except the last
|
||||
for _, cmd := range cmds[:len(cmds)-1] {
|
||||
if err = cmd.Start(); err != nil {
|
||||
return "", fmt.Errorf("starting %s failed with error: %v", cmd.Path, err)
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
var pipeErrMsgs []string
|
||||
// wait all cmds except the last to release their resources
|
||||
for _, cmd := range cmds[:len(cmds)-1] {
|
||||
if pipeErr := cmd.Wait(); pipeErr != nil {
|
||||
pipeErrMsgs = append(pipeErrMsgs, fmt.Sprintf("command %s failed with error: %v", cmd.Path, pipeErr))
|
||||
}
|
||||
}
|
||||
if len(pipeErrMsgs) > 0 && err == nil {
|
||||
err = fmt.Errorf("pipelineError from Wait: %v", strings.Join(pipeErrMsgs, ", "))
|
||||
}
|
||||
}()
|
||||
|
||||
// wait on last cmd
|
||||
out, err := cmds[len(cmds)-1].CombinedOutput()
|
||||
return string(out), err
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
package testutil
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
@ -14,20 +11,3 @@ func ErrorContains(t require.TestingT, err error, expectedError string) {
|
|||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), expectedError)
|
||||
}
|
||||
|
||||
// EqualNormalizedString compare the actual value to the expected value after applying the specified
|
||||
// transform function. It fails the test if these two transformed string are not equal.
|
||||
// For example `EqualNormalizedString(t, RemoveSpace, "foo\n", "foo")` wouldn't fail the test as
|
||||
// spaces (and thus '\n') are removed before comparing the string.
|
||||
func EqualNormalizedString(t require.TestingT, transformFun func(rune) rune, actual, expected string) {
|
||||
require.Equal(t, strings.Map(transformFun, expected), strings.Map(transformFun, actual))
|
||||
}
|
||||
|
||||
// RemoveSpace returns -1 if the specified runes is considered as a space (unicode)
|
||||
// and the rune itself otherwise.
|
||||
func RemoveSpace(r rune) rune {
|
||||
if unicode.IsSpace(r) {
|
||||
return -1
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
|
@ -1,218 +0,0 @@
|
|||
package testutil
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/stringutils"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
)
|
||||
|
||||
// IsKilled process the specified error and returns whether the process was killed or not.
|
||||
func IsKilled(err error) bool {
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
status, ok := exitErr.Sys().(syscall.WaitStatus)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
// status.ExitStatus() is required on Windows because it does not
|
||||
// implement Signal() nor Signaled(). Just check it had a bad exit
|
||||
// status could mean it was killed (and in tests we do kill)
|
||||
return (status.Signaled() && status.Signal() == os.Kill) || status.ExitStatus() != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) {
|
||||
out, err := cmd.CombinedOutput()
|
||||
exitCode = system.ProcessExitCode(err)
|
||||
output = string(out)
|
||||
return
|
||||
}
|
||||
|
||||
// RunCommandPipelineWithOutput runs the array of commands with the output
|
||||
// of each pipelined with the following (like cmd1 | cmd2 | cmd3 would do).
|
||||
// It returns the final output, the exitCode different from 0 and the error
|
||||
// if something bad happened.
|
||||
func RunCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, exitCode int, err error) {
|
||||
if len(cmds) < 2 {
|
||||
return "", 0, errors.New("pipeline does not have multiple cmds")
|
||||
}
|
||||
|
||||
// connect stdin of each cmd to stdout pipe of previous cmd
|
||||
for i, cmd := range cmds {
|
||||
if i > 0 {
|
||||
prevCmd := cmds[i-1]
|
||||
cmd.Stdin, err = prevCmd.StdoutPipe()
|
||||
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("cannot set stdout pipe for %s: %v", cmd.Path, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start all cmds except the last
|
||||
for _, cmd := range cmds[:len(cmds)-1] {
|
||||
if err = cmd.Start(); err != nil {
|
||||
return "", 0, fmt.Errorf("starting %s failed with error: %v", cmd.Path, err)
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
var pipeErrMsgs []string
|
||||
// wait all cmds except the last to release their resources
|
||||
for _, cmd := range cmds[:len(cmds)-1] {
|
||||
if pipeErr := cmd.Wait(); pipeErr != nil {
|
||||
pipeErrMsgs = append(pipeErrMsgs, fmt.Sprintf("command %s failed with error: %v", cmd.Path, pipeErr))
|
||||
}
|
||||
}
|
||||
if len(pipeErrMsgs) > 0 && err == nil {
|
||||
err = fmt.Errorf("pipelineError from Wait: %v", strings.Join(pipeErrMsgs, ", "))
|
||||
}
|
||||
}()
|
||||
|
||||
// wait on last cmd
|
||||
return runCommandWithOutput(cmds[len(cmds)-1])
|
||||
}
|
||||
|
||||
// ConvertSliceOfStringsToMap converts a slices of string in a map
|
||||
// with the strings as key and an empty string as values.
|
||||
func ConvertSliceOfStringsToMap(input []string) map[string]struct{} {
|
||||
output := make(map[string]struct{})
|
||||
for _, v := range input {
|
||||
output[v] = struct{}{}
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// CompareDirectoryEntries compares two sets of FileInfo (usually taken from a directory)
|
||||
// and returns an error if different.
|
||||
func CompareDirectoryEntries(e1 []os.FileInfo, e2 []os.FileInfo) error {
|
||||
var (
|
||||
e1Entries = make(map[string]struct{})
|
||||
e2Entries = make(map[string]struct{})
|
||||
)
|
||||
for _, e := range e1 {
|
||||
e1Entries[e.Name()] = struct{}{}
|
||||
}
|
||||
for _, e := range e2 {
|
||||
e2Entries[e.Name()] = struct{}{}
|
||||
}
|
||||
if !reflect.DeepEqual(e1Entries, e2Entries) {
|
||||
return fmt.Errorf("entries differ")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListTar lists the entries of a tar.
|
||||
func ListTar(f io.Reader) ([]string, error) {
|
||||
tr := tar.NewReader(f)
|
||||
var entries []string
|
||||
|
||||
for {
|
||||
th, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
// end of tar archive
|
||||
return entries, nil
|
||||
}
|
||||
if err != nil {
|
||||
return entries, err
|
||||
}
|
||||
entries = append(entries, th.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// RandomTmpDirPath provides a temporary path with rand string appended.
|
||||
// does not create or checks if it exists.
|
||||
func RandomTmpDirPath(s string, platform string) string {
|
||||
tmp := "/tmp"
|
||||
if platform == "windows" {
|
||||
tmp = os.Getenv("TEMP")
|
||||
}
|
||||
path := filepath.Join(tmp, fmt.Sprintf("%s.%s", s, stringutils.GenerateRandomAlphaOnlyString(10)))
|
||||
if platform == "windows" {
|
||||
return filepath.FromSlash(path) // Using \
|
||||
}
|
||||
return filepath.ToSlash(path) // Using /
|
||||
}
|
||||
|
||||
// ConsumeWithSpeed reads chunkSize bytes from reader before sleeping
|
||||
// for interval duration. Returns total read bytes. Send true to the
|
||||
// stop channel to return before reading to EOF on the reader.
|
||||
func ConsumeWithSpeed(reader io.Reader, chunkSize int, interval time.Duration, stop chan bool) (n int, err error) {
|
||||
buffer := make([]byte, chunkSize)
|
||||
for {
|
||||
var readBytes int
|
||||
readBytes, err = reader.Read(buffer)
|
||||
n += readBytes
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-stop:
|
||||
return
|
||||
case <-time.After(interval):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ParseCgroupPaths parses 'procCgroupData', which is output of '/proc/<pid>/cgroup', and returns
|
||||
// a map which cgroup name as key and path as value.
|
||||
func ParseCgroupPaths(procCgroupData string) map[string]string {
|
||||
cgroupPaths := map[string]string{}
|
||||
for _, line := range strings.Split(procCgroupData, "\n") {
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) != 3 {
|
||||
continue
|
||||
}
|
||||
cgroupPaths[parts[1]] = parts[2]
|
||||
}
|
||||
return cgroupPaths
|
||||
}
|
||||
|
||||
// ChannelBuffer holds a chan of byte array that can be populate in a goroutine.
|
||||
type ChannelBuffer struct {
|
||||
C chan []byte
|
||||
}
|
||||
|
||||
// Write implements Writer.
|
||||
func (c *ChannelBuffer) Write(b []byte) (int, error) {
|
||||
c.C <- b
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// Close closes the go channel.
|
||||
func (c *ChannelBuffer) Close() error {
|
||||
close(c.C)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadTimeout reads the content of the channel in the specified byte array with
|
||||
// the specified duration as timeout.
|
||||
func (c *ChannelBuffer) ReadTimeout(p []byte, n time.Duration) (int, error) {
|
||||
select {
|
||||
case b := <-c.C:
|
||||
return copy(p[0:], b), nil
|
||||
case <-time.After(n):
|
||||
return -1, fmt.Errorf("timeout reading from channel")
|
||||
}
|
||||
}
|
||||
|
||||
// ReadBody read the specified ReadCloser content and returns it
|
||||
func ReadBody(b io.ReadCloser) ([]byte, error) {
|
||||
defer b.Close()
|
||||
return ioutil.ReadAll(b)
|
||||
}
|
|
@ -1,341 +0,0 @@
|
|||
package testutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestIsKilledFalseWithNonKilledProcess(t *testing.T) {
|
||||
var lsCmd *exec.Cmd
|
||||
if runtime.GOOS != "windows" {
|
||||
lsCmd = exec.Command("ls")
|
||||
} else {
|
||||
lsCmd = exec.Command("cmd", "/c", "dir")
|
||||
}
|
||||
|
||||
err := lsCmd.Run()
|
||||
if IsKilled(err) {
|
||||
t.Fatalf("Expected the ls command to not be killed, was.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsKilledTrueWithKilledProcess(t *testing.T) {
|
||||
var longCmd *exec.Cmd
|
||||
if runtime.GOOS != "windows" {
|
||||
longCmd = exec.Command("top")
|
||||
} else {
|
||||
longCmd = exec.Command("powershell", "while ($true) { sleep 1 }")
|
||||
}
|
||||
|
||||
// Start a command
|
||||
err := longCmd.Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Capture the error when *dying*
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
done <- longCmd.Wait()
|
||||
}()
|
||||
// Then kill it
|
||||
longCmd.Process.Kill()
|
||||
// Get the error
|
||||
err = <-done
|
||||
if !IsKilled(err) {
|
||||
t.Fatalf("Expected the command to be killed, was not.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCommandPipelineWithOutputWithNotEnoughCmds(t *testing.T) {
|
||||
_, _, err := RunCommandPipelineWithOutput(exec.Command("ls"))
|
||||
expectedError := "pipeline does not have multiple cmds"
|
||||
if err == nil || err.Error() != expectedError {
|
||||
t.Fatalf("Expected an error with %s, got err:%s", expectedError, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCommandPipelineWithOutputErrors(t *testing.T) {
|
||||
p := "$PATH"
|
||||
if runtime.GOOS == "windows" {
|
||||
p = "%PATH%"
|
||||
}
|
||||
cmd1 := exec.Command("ls")
|
||||
cmd1.Stdout = os.Stdout
|
||||
cmd2 := exec.Command("anything really")
|
||||
_, _, err := RunCommandPipelineWithOutput(cmd1, cmd2)
|
||||
if err == nil || err.Error() != "cannot set stdout pipe for anything really: exec: Stdout already set" {
|
||||
t.Fatalf("Expected an error, got %v", err)
|
||||
}
|
||||
|
||||
cmdWithError := exec.Command("doesnotexists")
|
||||
cmdCat := exec.Command("cat")
|
||||
_, _, err = RunCommandPipelineWithOutput(cmdWithError, cmdCat)
|
||||
if err == nil || err.Error() != `starting doesnotexists failed with error: exec: "doesnotexists": executable file not found in `+p {
|
||||
t.Fatalf("Expected an error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCommandPipelineWithOutput(t *testing.T) {
|
||||
//TODO: Should run on Solaris
|
||||
if runtime.GOOS == "solaris" {
|
||||
t.Skip()
|
||||
}
|
||||
cmds := []*exec.Cmd{
|
||||
// Print 2 characters
|
||||
exec.Command("echo", "-n", "11"),
|
||||
// Count the number or char from stdin (previous command)
|
||||
exec.Command("wc", "-m"),
|
||||
}
|
||||
out, exitCode, err := RunCommandPipelineWithOutput(cmds...)
|
||||
expectedOutput := "2\n"
|
||||
if out != expectedOutput || exitCode != 0 || err != nil {
|
||||
t.Fatalf("Expected %s for commands %v, got out:%s, exitCode:%d, err:%v", expectedOutput, cmds, out, exitCode, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertSliceOfStringsToMap(t *testing.T) {
|
||||
input := []string{"a", "b"}
|
||||
actual := ConvertSliceOfStringsToMap(input)
|
||||
for _, key := range input {
|
||||
if _, ok := actual[key]; !ok {
|
||||
t.Fatalf("Expected output to contains key %s, did not: %v", key, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompareDirectoryEntries(t *testing.T) {
|
||||
tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-compare-directories")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpFolder)
|
||||
|
||||
file1 := filepath.Join(tmpFolder, "file1")
|
||||
file2 := filepath.Join(tmpFolder, "file2")
|
||||
os.Create(file1)
|
||||
os.Create(file2)
|
||||
|
||||
fi1, err := os.Stat(file1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fi1bis, err := os.Stat(file1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fi2, err := os.Stat(file2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
e1 []os.FileInfo
|
||||
e2 []os.FileInfo
|
||||
shouldError bool
|
||||
}{
|
||||
// Empty directories
|
||||
{
|
||||
[]os.FileInfo{},
|
||||
[]os.FileInfo{},
|
||||
false,
|
||||
},
|
||||
// Same FileInfos
|
||||
{
|
||||
[]os.FileInfo{fi1},
|
||||
[]os.FileInfo{fi1},
|
||||
false,
|
||||
},
|
||||
// Different FileInfos but same names
|
||||
{
|
||||
[]os.FileInfo{fi1},
|
||||
[]os.FileInfo{fi1bis},
|
||||
false,
|
||||
},
|
||||
// Different FileInfos, different names
|
||||
{
|
||||
[]os.FileInfo{fi1},
|
||||
[]os.FileInfo{fi2},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, elt := range cases {
|
||||
err := CompareDirectoryEntries(elt.e1, elt.e2)
|
||||
if elt.shouldError && err == nil {
|
||||
t.Fatalf("Should have return an error, did not with %v and %v", elt.e1, elt.e2)
|
||||
}
|
||||
if !elt.shouldError && err != nil {
|
||||
t.Fatalf("Should have not returned an error, but did : %v with %v and %v", err, elt.e1, elt.e2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME make an "unhappy path" test for ListTar without "panicking" :-)
|
||||
func TestListTar(t *testing.T) {
|
||||
// TODO Windows: Figure out why this fails. Should be portable.
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("Failing on Windows - needs further investigation")
|
||||
}
|
||||
tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-list-tar")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpFolder)
|
||||
|
||||
// Let's create a Tar file
|
||||
srcFile := filepath.Join(tmpFolder, "src")
|
||||
tarFile := filepath.Join(tmpFolder, "src.tar")
|
||||
os.Create(srcFile)
|
||||
cmd := exec.Command("sh", "-c", "tar cf "+tarFile+" "+srcFile)
|
||||
_, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
reader, err := os.Open(tarFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
entries, err := ListTar(reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(entries) != 1 && entries[0] != "src" {
|
||||
t.Fatalf("Expected a tar file with 1 entry (%s), got %v", srcFile, entries)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandomTmpDirPath(t *testing.T) {
|
||||
path := RandomTmpDirPath("something", runtime.GOOS)
|
||||
|
||||
prefix := "/tmp/something"
|
||||
if runtime.GOOS == "windows" {
|
||||
prefix = os.Getenv("TEMP") + `\something`
|
||||
}
|
||||
expectedSize := len(prefix) + 11
|
||||
|
||||
if !strings.HasPrefix(path, prefix) {
|
||||
t.Fatalf("Expected generated path to have '%s' as prefix, got %s'", prefix, path)
|
||||
}
|
||||
if len(path) != expectedSize {
|
||||
t.Fatalf("Expected generated path to be %d, got %d", expectedSize, len(path))
|
||||
}
|
||||
}
|
||||
|
||||
func TestConsumeWithSpeed(t *testing.T) {
|
||||
reader := strings.NewReader("1234567890")
|
||||
chunksize := 2
|
||||
|
||||
bytes1, err := ConsumeWithSpeed(reader, chunksize, 10*time.Millisecond, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if bytes1 != 10 {
|
||||
t.Fatalf("Expected to have read 10 bytes, got %d", bytes1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestConsumeWithSpeedWithStop(t *testing.T) {
|
||||
reader := strings.NewReader("1234567890")
|
||||
chunksize := 2
|
||||
|
||||
stopIt := make(chan bool)
|
||||
|
||||
go func() {
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
stopIt <- true
|
||||
}()
|
||||
|
||||
bytes1, err := ConsumeWithSpeed(reader, chunksize, 20*time.Millisecond, stopIt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if bytes1 != 2 {
|
||||
t.Fatalf("Expected to have read 2 bytes, got %d", bytes1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestParseCgroupPathsEmpty(t *testing.T) {
|
||||
cgroupMap := ParseCgroupPaths("")
|
||||
if len(cgroupMap) != 0 {
|
||||
t.Fatalf("Expected an empty map, got %v", cgroupMap)
|
||||
}
|
||||
cgroupMap = ParseCgroupPaths("\n")
|
||||
if len(cgroupMap) != 0 {
|
||||
t.Fatalf("Expected an empty map, got %v", cgroupMap)
|
||||
}
|
||||
cgroupMap = ParseCgroupPaths("something:else\nagain:here")
|
||||
if len(cgroupMap) != 0 {
|
||||
t.Fatalf("Expected an empty map, got %v", cgroupMap)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCgroupPaths(t *testing.T) {
|
||||
cgroupMap := ParseCgroupPaths("2:memory:/a\n1:cpuset:/b")
|
||||
if len(cgroupMap) != 2 {
|
||||
t.Fatalf("Expected a map with 2 entries, got %v", cgroupMap)
|
||||
}
|
||||
if value, ok := cgroupMap["memory"]; !ok || value != "/a" {
|
||||
t.Fatalf("Expected cgroupMap to contains an entry for 'memory' with value '/a', got %v", cgroupMap)
|
||||
}
|
||||
if value, ok := cgroupMap["cpuset"]; !ok || value != "/b" {
|
||||
t.Fatalf("Expected cgroupMap to contains an entry for 'cpuset' with value '/b', got %v", cgroupMap)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelBufferTimeout(t *testing.T) {
|
||||
expected := "11"
|
||||
|
||||
buf := &ChannelBuffer{make(chan []byte, 1)}
|
||||
defer buf.Close()
|
||||
|
||||
done := make(chan struct{}, 1)
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
io.Copy(buf, strings.NewReader(expected))
|
||||
done <- struct{}{}
|
||||
}()
|
||||
|
||||
// Wait long enough
|
||||
b := make([]byte, 2)
|
||||
_, err := buf.ReadTimeout(b, 50*time.Millisecond)
|
||||
if err == nil && err.Error() != "timeout reading from channel" {
|
||||
t.Fatalf("Expected an error, got %s", err)
|
||||
}
|
||||
<-done
|
||||
}
|
||||
|
||||
func TestChannelBuffer(t *testing.T) {
|
||||
expected := "11"
|
||||
|
||||
buf := &ChannelBuffer{make(chan []byte, 1)}
|
||||
defer buf.Close()
|
||||
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
io.Copy(buf, strings.NewReader(expected))
|
||||
}()
|
||||
|
||||
// Wait long enough
|
||||
b := make([]byte, 2)
|
||||
_, err := buf.ReadTimeout(b, 200*time.Millisecond)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if string(b) != expected {
|
||||
t.Fatalf("Expected '%s', got '%s'", expected, string(b))
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue