Signed-off-by: Vincent Demeester <vincent@sbr.pm>
| 15 | 15 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,46 @@ |
| 0 |
+// Package checker provides Docker specific implementations of the go-check.Checker interface. |
|
| 1 |
+package checker |
|
| 2 |
+ |
|
| 3 |
+import ( |
|
| 4 |
+ "github.com/go-check/check" |
|
| 5 |
+ "github.com/vdemeester/shakers" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+// As a commodity, we bring all check.Checker variables into the current namespace to avoid having |
|
| 9 |
+// to think about check.X versus checker.X. |
|
| 10 |
+var ( |
|
| 11 |
+ DeepEquals = check.DeepEquals |
|
| 12 |
+ ErrorMatches = check.ErrorMatches |
|
| 13 |
+ FitsTypeOf = check.FitsTypeOf |
|
| 14 |
+ HasLen = check.HasLen |
|
| 15 |
+ Implements = check.Implements |
|
| 16 |
+ IsNil = check.IsNil |
|
| 17 |
+ Matches = check.Matches |
|
| 18 |
+ Not = check.Not |
|
| 19 |
+ NotNil = check.NotNil |
|
| 20 |
+ PanicMatches = check.PanicMatches |
|
| 21 |
+ Panics = check.Panics |
|
| 22 |
+ |
|
| 23 |
+ Contains = shakers.Contains |
|
| 24 |
+ ContainsAny = shakers.ContainsAny |
|
| 25 |
+ Count = shakers.Count |
|
| 26 |
+ Equals = shakers.Equals |
|
| 27 |
+ EqualFold = shakers.EqualFold |
|
| 28 |
+ False = shakers.False |
|
| 29 |
+ GreaterOrEqualThan = shakers.GreaterOrEqualThan |
|
| 30 |
+ GreaterThan = shakers.GreaterThan |
|
| 31 |
+ HasPrefix = shakers.HasPrefix |
|
| 32 |
+ HasSuffix = shakers.HasSuffix |
|
| 33 |
+ Index = shakers.Index |
|
| 34 |
+ IndexAny = shakers.IndexAny |
|
| 35 |
+ IsAfter = shakers.IsAfter |
|
| 36 |
+ IsBefore = shakers.IsBefore |
|
| 37 |
+ IsBetween = shakers.IsBetween |
|
| 38 |
+ IsLower = shakers.IsLower |
|
| 39 |
+ IsUpper = shakers.IsUpper |
|
| 40 |
+ LessOrEqualThan = shakers.LessOrEqualThan |
|
| 41 |
+ LessThan = shakers.LessThan |
|
| 42 |
+ TimeEquals = shakers.TimeEquals |
|
| 43 |
+ True = shakers.True |
|
| 44 |
+ TimeIgnore = shakers.TimeIgnore |
|
| 45 |
+) |
| ... | ... |
@@ -19,12 +19,12 @@ import ( |
| 19 | 19 |
"time" |
| 20 | 20 |
|
| 21 | 21 |
"github.com/docker/docker/api/types/events" |
| 22 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 22 | 23 |
"github.com/docker/docker/opts" |
| 23 |
- "github.com/docker/docker/pkg/integration" |
|
| 24 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 25 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 26 | 24 |
"github.com/docker/docker/pkg/ioutils" |
| 27 | 25 |
"github.com/docker/docker/pkg/stringid" |
| 26 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 27 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 28 | 28 |
"github.com/docker/go-connections/sockets" |
| 29 | 29 |
"github.com/docker/go-connections/tlsconfig" |
| 30 | 30 |
"github.com/go-check/check" |
| ... | ... |
@@ -543,7 +543,7 @@ func (d *Daemon) queryRootDir() (string, error) {
|
| 543 | 543 |
} |
| 544 | 544 |
var b []byte |
| 545 | 545 |
var i Info |
| 546 |
- b, err = integration.ReadBody(body) |
|
| 546 |
+ b, err = testutil.ReadBody(body) |
|
| 547 | 547 |
if err == nil && resp.StatusCode == http.StatusOK {
|
| 548 | 548 |
// read the docker root dir |
| 549 | 549 |
if err = json.Unmarshal(b, &i); err == nil {
|
| ... | ... |
@@ -570,7 +570,7 @@ func (d *Daemon) WaitRun(contID string) error {
|
| 570 | 570 |
|
| 571 | 571 |
// GetBaseDeviceSize returns the base device size of the daemon |
| 572 | 572 |
func (d *Daemon) GetBaseDeviceSize(c *check.C) int64 {
|
| 573 |
- infoCmdOutput, _, err := integration.RunCommandPipelineWithOutput( |
|
| 573 |
+ infoCmdOutput, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 574 | 574 |
exec.Command(d.dockerBinary, "-H", d.Sock(), "info"), |
| 575 | 575 |
exec.Command("grep", "Base Device Size"),
|
| 576 | 576 |
) |
| ... | ... |
@@ -617,7 +617,7 @@ func (d *Daemon) SockRequest(method, endpoint string, data interface{}) (int, []
|
| 617 | 617 |
if err != nil {
|
| 618 | 618 |
return -1, nil, err |
| 619 | 619 |
} |
| 620 |
- b, err := integration.ReadBody(body) |
|
| 620 |
+ b, err := testutil.ReadBody(body) |
|
| 621 | 621 |
return res.StatusCode, b, err |
| 622 | 622 |
} |
| 623 | 623 |
|
| ... | ... |
@@ -10,7 +10,7 @@ import ( |
| 10 | 10 |
"github.com/docker/docker/api/types" |
| 11 | 11 |
"github.com/docker/docker/api/types/filters" |
| 12 | 12 |
"github.com/docker/docker/api/types/swarm" |
| 13 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 13 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 14 | 14 |
"github.com/go-check/check" |
| 15 | 15 |
"github.com/pkg/errors" |
| 16 | 16 |
) |
| ... | ... |
@@ -12,9 +12,9 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
"github.com/docker/docker/api/types" |
| 14 | 14 |
"github.com/docker/docker/client" |
| 15 |
- "github.com/docker/docker/pkg/integration" |
|
| 16 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 15 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 17 | 16 |
"github.com/docker/docker/pkg/stdcopy" |
| 17 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 18 | 18 |
"github.com/go-check/check" |
| 19 | 19 |
"golang.org/x/net/websocket" |
| 20 | 20 |
) |
| ... | ... |
@@ -80,7 +80,7 @@ func (s *DockerSuite) TestPostContainersAttachContainerNotFound(c *check.C) {
|
| 80 | 80 |
// connection will shutdown, err should be "persistent connection closed" |
| 81 | 81 |
c.Assert(err, checker.NotNil) // Server shutdown connection |
| 82 | 82 |
|
| 83 |
- body, err := integration.ReadBody(resp.Body) |
|
| 83 |
+ body, err := testutil.ReadBody(resp.Body) |
|
| 84 | 84 |
c.Assert(err, checker.IsNil) |
| 85 | 85 |
c.Assert(resp.StatusCode, checker.Equals, http.StatusNotFound) |
| 86 | 86 |
expected := "No such container: doesnotexist\r\n" |
| ... | ... |
@@ -7,8 +7,8 @@ import ( |
| 7 | 7 |
"regexp" |
| 8 | 8 |
"strings" |
| 9 | 9 |
|
| 10 |
- "github.com/docker/docker/pkg/integration" |
|
| 11 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 10 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 11 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 12 | 12 |
"github.com/go-check/check" |
| 13 | 13 |
) |
| 14 | 14 |
|
| ... | ... |
@@ -35,7 +35,7 @@ RUN find /tmp/` |
| 35 | 35 |
c.Assert(err, checker.IsNil) |
| 36 | 36 |
c.Assert(res.StatusCode, checker.Equals, http.StatusOK) |
| 37 | 37 |
|
| 38 |
- buf, err := integration.ReadBody(body) |
|
| 38 |
+ buf, err := testutil.ReadBody(body) |
|
| 39 | 39 |
c.Assert(err, checker.IsNil) |
| 40 | 40 |
|
| 41 | 41 |
// Make sure Dockerfile exists. |
| ... | ... |
@@ -126,7 +126,7 @@ RUN echo 'right' |
| 126 | 126 |
c.Assert(res.StatusCode, checker.Equals, http.StatusOK) |
| 127 | 127 |
|
| 128 | 128 |
defer body.Close() |
| 129 |
- content, err := integration.ReadBody(body) |
|
| 129 |
+ content, err := testutil.ReadBody(body) |
|
| 130 | 130 |
c.Assert(err, checker.IsNil) |
| 131 | 131 |
|
| 132 | 132 |
// Build used the wrong dockerfile. |
| ... | ... |
@@ -145,7 +145,7 @@ RUN echo from dockerfile`, |
| 145 | 145 |
c.Assert(err, checker.IsNil) |
| 146 | 146 |
c.Assert(res.StatusCode, checker.Equals, http.StatusOK) |
| 147 | 147 |
|
| 148 |
- buf, err := integration.ReadBody(body) |
|
| 148 |
+ buf, err := testutil.ReadBody(body) |
|
| 149 | 149 |
c.Assert(err, checker.IsNil) |
| 150 | 150 |
|
| 151 | 151 |
out := string(buf) |
| ... | ... |
@@ -167,7 +167,7 @@ RUN echo from Dockerfile`, |
| 167 | 167 |
c.Assert(err, checker.IsNil) |
| 168 | 168 |
c.Assert(res.StatusCode, checker.Equals, http.StatusOK) |
| 169 | 169 |
|
| 170 |
- buf, err := integration.ReadBody(body) |
|
| 170 |
+ buf, err := testutil.ReadBody(body) |
|
| 171 | 171 |
c.Assert(err, checker.IsNil) |
| 172 | 172 |
|
| 173 | 173 |
out := string(buf) |
| ... | ... |
@@ -190,7 +190,7 @@ RUN echo from dockerfile`, |
| 190 | 190 |
c.Assert(err, checker.IsNil) |
| 191 | 191 |
c.Assert(res.StatusCode, checker.Equals, http.StatusOK) |
| 192 | 192 |
|
| 193 |
- buf, err := integration.ReadBody(body) |
|
| 193 |
+ buf, err := testutil.ReadBody(body) |
|
| 194 | 194 |
c.Assert(err, checker.IsNil) |
| 195 | 195 |
|
| 196 | 196 |
out := string(buf) |
| ... | ... |
@@ -237,7 +237,7 @@ func (s *DockerSuite) TestBuildAPIUnnormalizedTarPaths(c *check.C) {
|
| 237 | 237 |
c.Assert(err, checker.IsNil) |
| 238 | 238 |
c.Assert(res.StatusCode, checker.Equals, http.StatusOK) |
| 239 | 239 |
|
| 240 |
- out, err := integration.ReadBody(body) |
|
| 240 |
+ out, err := testutil.ReadBody(body) |
|
| 241 | 241 |
c.Assert(err, checker.IsNil) |
| 242 | 242 |
lines := strings.Split(string(out), "\n") |
| 243 | 243 |
c.Assert(len(lines), checker.GreaterThan, 1) |
| ... | ... |
@@ -21,11 +21,11 @@ import ( |
| 21 | 21 |
containertypes "github.com/docker/docker/api/types/container" |
| 22 | 22 |
mounttypes "github.com/docker/docker/api/types/mount" |
| 23 | 23 |
networktypes "github.com/docker/docker/api/types/network" |
| 24 |
- "github.com/docker/docker/pkg/integration" |
|
| 25 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 24 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 26 | 25 |
"github.com/docker/docker/pkg/ioutils" |
| 27 | 26 |
"github.com/docker/docker/pkg/mount" |
| 28 | 27 |
"github.com/docker/docker/pkg/stringid" |
| 28 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 29 | 29 |
"github.com/docker/docker/volume" |
| 30 | 30 |
"github.com/go-check/check" |
| 31 | 31 |
) |
| ... | ... |
@@ -215,7 +215,7 @@ func (s *DockerSuite) TestGetContainerStatsRmRunning(c *check.C) {
|
| 215 | 215 |
out, _ := runSleepingContainer(c) |
| 216 | 216 |
id := strings.TrimSpace(out) |
| 217 | 217 |
|
| 218 |
- buf := &integration.ChannelBuffer{make(chan []byte, 1)}
|
|
| 218 |
+ buf := &testutil.ChannelBuffer{make(chan []byte, 1)}
|
|
| 219 | 219 |
defer buf.Close() |
| 220 | 220 |
|
| 221 | 221 |
_, body, err := sockRequestRaw("GET", "/containers/"+id+"/stats?stream=1", nil, "application/json")
|
| ... | ... |
@@ -723,7 +723,7 @@ func (s *DockerSuite) TestContainerAPIInvalidPortSyntax(c *check.C) {
|
| 723 | 723 |
c.Assert(err, checker.IsNil) |
| 724 | 724 |
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) |
| 725 | 725 |
|
| 726 |
- b, err := integration.ReadBody(body) |
|
| 726 |
+ b, err := testutil.ReadBody(body) |
|
| 727 | 727 |
c.Assert(err, checker.IsNil) |
| 728 | 728 |
c.Assert(string(b[:]), checker.Contains, "invalid port") |
| 729 | 729 |
} |
| ... | ... |
@@ -743,7 +743,7 @@ func (s *DockerSuite) TestContainerAPIRestartPolicyInvalidPolicyName(c *check.C) |
| 743 | 743 |
c.Assert(err, checker.IsNil) |
| 744 | 744 |
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) |
| 745 | 745 |
|
| 746 |
- b, err := integration.ReadBody(body) |
|
| 746 |
+ b, err := testutil.ReadBody(body) |
|
| 747 | 747 |
c.Assert(err, checker.IsNil) |
| 748 | 748 |
c.Assert(string(b[:]), checker.Contains, "invalid restart policy") |
| 749 | 749 |
} |
| ... | ... |
@@ -763,7 +763,7 @@ func (s *DockerSuite) TestContainerAPIRestartPolicyRetryMismatch(c *check.C) {
|
| 763 | 763 |
c.Assert(err, checker.IsNil) |
| 764 | 764 |
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) |
| 765 | 765 |
|
| 766 |
- b, err := integration.ReadBody(body) |
|
| 766 |
+ b, err := testutil.ReadBody(body) |
|
| 767 | 767 |
c.Assert(err, checker.IsNil) |
| 768 | 768 |
c.Assert(string(b[:]), checker.Contains, "maximum retry count cannot be used with restart policy") |
| 769 | 769 |
} |
| ... | ... |
@@ -783,7 +783,7 @@ func (s *DockerSuite) TestContainerAPIRestartPolicyNegativeRetryCount(c *check.C |
| 783 | 783 |
c.Assert(err, checker.IsNil) |
| 784 | 784 |
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) |
| 785 | 785 |
|
| 786 |
- b, err := integration.ReadBody(body) |
|
| 786 |
+ b, err := testutil.ReadBody(body) |
|
| 787 | 787 |
c.Assert(err, checker.IsNil) |
| 788 | 788 |
c.Assert(string(b[:]), checker.Contains, "maximum retry count cannot be negative") |
| 789 | 789 |
} |
| ... | ... |
@@ -834,7 +834,7 @@ func (s *DockerSuite) TestContainerAPIPostCreateNull(c *check.C) {
|
| 834 | 834 |
c.Assert(err, checker.IsNil) |
| 835 | 835 |
c.Assert(res.StatusCode, checker.Equals, http.StatusCreated) |
| 836 | 836 |
|
| 837 |
- b, err := integration.ReadBody(body) |
|
| 837 |
+ b, err := testutil.ReadBody(body) |
|
| 838 | 838 |
c.Assert(err, checker.IsNil) |
| 839 | 839 |
type createResp struct {
|
| 840 | 840 |
ID string |
| ... | ... |
@@ -863,7 +863,7 @@ func (s *DockerSuite) TestCreateWithTooLowMemoryLimit(c *check.C) {
|
| 863 | 863 |
|
| 864 | 864 |
res, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
|
| 865 | 865 |
c.Assert(err, checker.IsNil) |
| 866 |
- b, err2 := integration.ReadBody(body) |
|
| 866 |
+ b, err2 := testutil.ReadBody(body) |
|
| 867 | 867 |
c.Assert(err2, checker.IsNil) |
| 868 | 868 |
|
| 869 | 869 |
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) |
| ... | ... |
@@ -10,8 +10,8 @@ import ( |
| 10 | 10 |
"strings" |
| 11 | 11 |
"time" |
| 12 | 12 |
|
| 13 |
- "github.com/docker/docker/pkg/integration" |
|
| 14 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 13 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 14 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 15 | 15 |
"github.com/go-check/check" |
| 16 | 16 |
) |
| 17 | 17 |
|
| ... | ... |
@@ -41,7 +41,7 @@ func (s *DockerSuite) TestExecAPICreateNoValidContentType(c *check.C) {
|
| 41 | 41 |
c.Assert(err, checker.IsNil) |
| 42 | 42 |
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) |
| 43 | 43 |
|
| 44 |
- b, err := integration.ReadBody(body) |
|
| 44 |
+ b, err := testutil.ReadBody(body) |
|
| 45 | 45 |
c.Assert(err, checker.IsNil) |
| 46 | 46 |
|
| 47 | 47 |
comment := check.Commentf("Expected message when creating exec command with invalid Content-Type specified")
|
| ... | ... |
@@ -108,7 +108,7 @@ func (s *DockerSuite) TestExecAPIStartBackwardsCompatible(c *check.C) {
|
| 108 | 108 |
resp, body, err := sockRequestRaw("POST", fmt.Sprintf("/v1.20/exec/%s/start", id), strings.NewReader(`{"Detach": true}`), "text/plain")
|
| 109 | 109 |
c.Assert(err, checker.IsNil) |
| 110 | 110 |
|
| 111 |
- b, err := integration.ReadBody(body) |
|
| 111 |
+ b, err := testutil.ReadBody(body) |
|
| 112 | 112 |
comment := check.Commentf("response body: %s", b)
|
| 113 | 113 |
c.Assert(err, checker.IsNil, comment) |
| 114 | 114 |
c.Assert(resp.StatusCode, checker.Equals, http.StatusOK, comment) |
| ... | ... |
@@ -157,7 +157,7 @@ func (s *DockerSuite) TestExecAPIStartWithDetach(c *check.C) {
|
| 157 | 157 |
_, body, err := sockRequestRaw("POST", fmt.Sprintf("/exec/%s/start", createResp.ID), strings.NewReader(`{"Detach": true}`), "application/json")
|
| 158 | 158 |
c.Assert(err, checker.IsNil) |
| 159 | 159 |
|
| 160 |
- b, err = integration.ReadBody(body) |
|
| 160 |
+ b, err = testutil.ReadBody(body) |
|
| 161 | 161 |
comment := check.Commentf("response body: %s", b)
|
| 162 | 162 |
c.Assert(err, checker.IsNil, comment) |
| 163 | 163 |
|
| ... | ... |
@@ -183,7 +183,7 @@ func startExec(c *check.C, id string, code int) {
|
| 183 | 183 |
resp, body, err := sockRequestRaw("POST", fmt.Sprintf("/exec/%s/start", id), strings.NewReader(`{"Detach": true}`), "application/json")
|
| 184 | 184 |
c.Assert(err, checker.IsNil) |
| 185 | 185 |
|
| 186 |
- b, err := integration.ReadBody(body) |
|
| 186 |
+ b, err := testutil.ReadBody(body) |
|
| 187 | 187 |
comment := check.Commentf("response body: %s", b)
|
| 188 | 188 |
c.Assert(err, checker.IsNil, comment) |
| 189 | 189 |
c.Assert(resp.StatusCode, checker.Equals, code, comment) |
| ... | ... |
@@ -7,7 +7,7 @@ import ( |
| 7 | 7 |
|
| 8 | 8 |
"github.com/docker/docker/api/types" |
| 9 | 9 |
"github.com/docker/docker/api/types/versions/v1p20" |
| 10 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 10 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 11 | 11 |
"github.com/docker/docker/pkg/stringutils" |
| 12 | 12 |
"github.com/go-check/check" |
| 13 | 13 |
) |
| ... | ... |
@@ -11,7 +11,7 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/api/types" |
| 12 | 12 |
"github.com/docker/docker/api/types/filters" |
| 13 | 13 |
"github.com/docker/docker/api/types/network" |
| 14 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 14 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 15 | 15 |
"github.com/go-check/check" |
| 16 | 16 |
) |
| 17 | 17 |
|
| ... | ... |
@@ -4,8 +4,8 @@ package main |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 | 6 |
"github.com/docker/docker/api/types/swarm" |
| 7 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 7 | 8 |
"github.com/docker/docker/integration-cli/daemon" |
| 8 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 9 | 9 |
"github.com/go-check/check" |
| 10 | 10 |
) |
| 11 | 11 |
|
| ... | ... |
@@ -14,8 +14,8 @@ import ( |
| 14 | 14 |
"time" |
| 15 | 15 |
|
| 16 | 16 |
"github.com/docker/docker/api/types/swarm" |
| 17 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 17 | 18 |
"github.com/docker/docker/integration-cli/daemon" |
| 18 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 19 | 19 |
"github.com/go-check/check" |
| 20 | 20 |
) |
| 21 | 21 |
|
| ... | ... |
@@ -9,9 +9,9 @@ import ( |
| 9 | 9 |
"strings" |
| 10 | 10 |
|
| 11 | 11 |
"github.com/docker/docker/api" |
| 12 |
- "github.com/docker/docker/pkg/integration" |
|
| 13 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 14 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 12 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 13 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 14 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 15 | 15 |
"github.com/go-check/check" |
| 16 | 16 |
) |
| 17 | 17 |
|
| ... | ... |
@@ -79,7 +79,7 @@ func (s *DockerSuite) TestAPIErrorJSON(c *check.C) {
|
| 79 | 79 |
c.Assert(err, checker.IsNil) |
| 80 | 80 |
c.Assert(httpResp.StatusCode, checker.Equals, http.StatusInternalServerError) |
| 81 | 81 |
c.Assert(httpResp.Header.Get("Content-Type"), checker.Equals, "application/json")
|
| 82 |
- b, err := integration.ReadBody(body) |
|
| 82 |
+ b, err := testutil.ReadBody(body) |
|
| 83 | 83 |
c.Assert(err, checker.IsNil) |
| 84 | 84 |
c.Assert(getErrorMessage(c, b), checker.Equals, "Config cannot be empty in order to create a container") |
| 85 | 85 |
} |
| ... | ... |
@@ -92,7 +92,7 @@ func (s *DockerSuite) TestAPIErrorPlainText(c *check.C) {
|
| 92 | 92 |
c.Assert(err, checker.IsNil) |
| 93 | 93 |
c.Assert(httpResp.StatusCode, checker.Equals, http.StatusInternalServerError) |
| 94 | 94 |
c.Assert(httpResp.Header.Get("Content-Type"), checker.Contains, "text/plain")
|
| 95 |
- b, err := integration.ReadBody(body) |
|
| 95 |
+ b, err := testutil.ReadBody(body) |
|
| 96 | 96 |
c.Assert(err, checker.IsNil) |
| 97 | 97 |
c.Assert(strings.TrimSpace(string(b)), checker.Equals, "Config cannot be empty in order to create a container") |
| 98 | 98 |
} |
| ... | ... |
@@ -103,7 +103,7 @@ func (s *DockerSuite) TestAPIErrorNotFoundJSON(c *check.C) {
|
| 103 | 103 |
c.Assert(err, checker.IsNil) |
| 104 | 104 |
c.Assert(httpResp.StatusCode, checker.Equals, http.StatusNotFound) |
| 105 | 105 |
c.Assert(httpResp.Header.Get("Content-Type"), checker.Equals, "application/json")
|
| 106 |
- b, err := integration.ReadBody(body) |
|
| 106 |
+ b, err := testutil.ReadBody(body) |
|
| 107 | 107 |
c.Assert(err, checker.IsNil) |
| 108 | 108 |
c.Assert(getErrorMessage(c, b), checker.Equals, "page not found") |
| 109 | 109 |
} |
| ... | ... |
@@ -113,7 +113,7 @@ func (s *DockerSuite) TestAPIErrorNotFoundPlainText(c *check.C) {
|
| 113 | 113 |
c.Assert(err, checker.IsNil) |
| 114 | 114 |
c.Assert(httpResp.StatusCode, checker.Equals, http.StatusNotFound) |
| 115 | 115 |
c.Assert(httpResp.Header.Get("Content-Type"), checker.Contains, "text/plain")
|
| 116 |
- b, err := integration.ReadBody(body) |
|
| 116 |
+ b, err := testutil.ReadBody(body) |
|
| 117 | 117 |
c.Assert(err, checker.IsNil) |
| 118 | 118 |
c.Assert(strings.TrimSpace(string(b)), checker.Equals, "page not found") |
| 119 | 119 |
} |
| ... | ... |
@@ -22,9 +22,9 @@ import ( |
| 22 | 22 |
"net/http/httputil" |
| 23 | 23 |
"net/url" |
| 24 | 24 |
|
| 25 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 25 | 26 |
"github.com/docker/docker/integration-cli/daemon" |
| 26 | 27 |
"github.com/docker/docker/pkg/authorization" |
| 27 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 28 | 28 |
"github.com/docker/docker/pkg/plugins" |
| 29 | 29 |
"github.com/go-check/check" |
| 30 | 30 |
) |
| ... | ... |
@@ -18,11 +18,11 @@ import ( |
| 18 | 18 |
"time" |
| 19 | 19 |
|
| 20 | 20 |
"github.com/docker/docker/builder/dockerfile/command" |
| 21 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 21 | 22 |
"github.com/docker/docker/pkg/archive" |
| 22 |
- "github.com/docker/docker/pkg/integration" |
|
| 23 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 24 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 25 | 23 |
"github.com/docker/docker/pkg/stringutils" |
| 24 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 25 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 26 | 26 |
"github.com/go-check/check" |
| 27 | 27 |
) |
| 28 | 28 |
|
| ... | ... |
@@ -2086,7 +2086,7 @@ func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
|
| 2086 | 2086 |
if err != nil {
|
| 2087 | 2087 |
c.Fatalf("failed to list contents of tmp dir: %s", err)
|
| 2088 | 2088 |
} |
| 2089 |
- if err = integration.CompareDirectoryEntries(entries, entriesFinal); err != nil {
|
|
| 2089 |
+ if err = testutil.CompareDirectoryEntries(entries, entriesFinal); err != nil {
|
|
| 2090 | 2090 |
c.Fatalf("context should have been deleted, but wasn't")
|
| 2091 | 2091 |
} |
| 2092 | 2092 |
|
| ... | ... |
@@ -2111,7 +2111,7 @@ func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
|
| 2111 | 2111 |
if err != nil {
|
| 2112 | 2112 |
c.Fatalf("failed to list contents of tmp dir: %s", err)
|
| 2113 | 2113 |
} |
| 2114 |
- if err = integration.CompareDirectoryEntries(entries, entriesFinal); err != nil {
|
|
| 2114 |
+ if err = testutil.CompareDirectoryEntries(entries, entriesFinal); err != nil {
|
|
| 2115 | 2115 |
c.Fatalf("context should have been deleted, but wasn't")
|
| 2116 | 2116 |
} |
| 2117 | 2117 |
|
| ... | ... |
@@ -5342,7 +5342,7 @@ func (s *DockerSuite) TestBuildContainerWithCgroupParent(c *check.C) {
|
| 5342 | 5342 |
if err != nil {
|
| 5343 | 5343 |
c.Fatalf("failed to read '/proc/self/cgroup - %v", err)
|
| 5344 | 5344 |
} |
| 5345 |
- selfCgroupPaths := integration.ParseCgroupPaths(string(data)) |
|
| 5345 |
+ selfCgroupPaths := testutil.ParseCgroupPaths(string(data)) |
|
| 5346 | 5346 |
_, found := selfCgroupPaths["memory"] |
| 5347 | 5347 |
if !found {
|
| 5348 | 5348 |
c.Fatalf("unable to find self memory cgroup path. CgroupsPath: %v", selfCgroupPaths)
|
| ... | ... |
@@ -14,8 +14,8 @@ import ( |
| 14 | 14 |
"strings" |
| 15 | 15 |
"time" |
| 16 | 16 |
|
| 17 |
- "github.com/docker/docker/pkg/integration" |
|
| 18 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 17 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 18 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 19 | 19 |
"github.com/docker/go-units" |
| 20 | 20 |
"github.com/go-check/check" |
| 21 | 21 |
) |
| ... | ... |
@@ -194,7 +194,7 @@ func (s *DockerSuite) TestBuildCancellationKillsSleep(c *check.C) {
|
| 194 | 194 |
} |
| 195 | 195 |
|
| 196 | 196 |
// Get the exit status of `docker build`, check it exited because killed. |
| 197 |
- if err := buildCmd.Wait(); err != nil && !integration.IsKilled(err) {
|
|
| 197 |
+ if err := buildCmd.Wait(); err != nil && !testutil.IsKilled(err) {
|
|
| 198 | 198 |
c.Fatalf("wait failed during build run: %T %s", err, err)
|
| 199 | 199 |
} |
| 200 | 200 |
|
| ... | ... |
@@ -12,7 +12,7 @@ import ( |
| 12 | 12 |
"github.com/docker/distribution/manifest/schema1" |
| 13 | 13 |
"github.com/docker/distribution/manifest/schema2" |
| 14 | 14 |
"github.com/docker/docker/api/types" |
| 15 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 15 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 16 | 16 |
"github.com/docker/docker/pkg/stringutils" |
| 17 | 17 |
"github.com/go-check/check" |
| 18 | 18 |
) |
| ... | ... |
@@ -11,8 +11,8 @@ import ( |
| 11 | 11 |
|
| 12 | 12 |
"github.com/docker/docker/api" |
| 13 | 13 |
"github.com/docker/docker/dockerversion" |
| 14 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 14 | 15 |
"github.com/docker/docker/pkg/homedir" |
| 15 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 16 | 16 |
"github.com/go-check/check" |
| 17 | 17 |
) |
| 18 | 18 |
|
| ... | ... |
@@ -10,9 +10,9 @@ import ( |
| 10 | 10 |
"path/filepath" |
| 11 | 11 |
"strings" |
| 12 | 12 |
|
| 13 |
- "github.com/docker/docker/pkg/integration" |
|
| 14 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 15 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 13 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 14 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 15 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 16 | 16 |
"github.com/go-check/check" |
| 17 | 17 |
) |
| 18 | 18 |
|
| ... | ... |
@@ -546,7 +546,7 @@ func (s *DockerSuite) TestCpToStdout(c *check.C) {
|
| 546 | 546 |
// failed to set up container |
| 547 | 547 |
c.Assert(strings.TrimSpace(out), checker.Equals, "0") |
| 548 | 548 |
|
| 549 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 549 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 550 | 550 |
exec.Command(dockerBinary, "cp", containerID+":/test", "-"), |
| 551 | 551 |
exec.Command("tar", "-vtf", "-"))
|
| 552 | 552 |
|
| ... | ... |
@@ -12,9 +12,9 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
"io/ioutil" |
| 14 | 14 |
|
| 15 |
- "github.com/docker/docker/pkg/integration" |
|
| 16 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 15 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 17 | 16 |
"github.com/docker/docker/pkg/stringid" |
| 17 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 18 | 18 |
"github.com/docker/go-connections/nat" |
| 19 | 19 |
"github.com/go-check/check" |
| 20 | 20 |
) |
| ... | ... |
@@ -356,7 +356,7 @@ func (s *DockerTrustSuite) TestCreateWhenCertExpired(c *check.C) {
|
| 356 | 356 |
// Certificates have 10 years of expiration |
| 357 | 357 |
elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11) |
| 358 | 358 |
|
| 359 |
- integration.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 359 |
+ testutil.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 360 | 360 |
// Try create |
| 361 | 361 |
createCmd := exec.Command(dockerBinary, "create", repoName) |
| 362 | 362 |
s.trustedCmd(createCmd) |
| ... | ... |
@@ -365,7 +365,7 @@ func (s *DockerTrustSuite) TestCreateWhenCertExpired(c *check.C) {
|
| 365 | 365 |
c.Assert(string(out), checker.Contains, "could not validate the path to a trusted root", check.Commentf("Missing expected output on trusted create in the distant future:\n%s", out))
|
| 366 | 366 |
}) |
| 367 | 367 |
|
| 368 |
- integration.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 368 |
+ testutil.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 369 | 369 |
// Try create |
| 370 | 370 |
createCmd := exec.Command(dockerBinary, "create", "--disable-content-trust", repoName) |
| 371 | 371 |
s.trustedCmd(createCmd) |
| ... | ... |
@@ -21,12 +21,12 @@ import ( |
| 21 | 21 |
"syscall" |
| 22 | 22 |
"time" |
| 23 | 23 |
|
| 24 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 24 | 25 |
"github.com/docker/docker/integration-cli/daemon" |
| 25 |
- "github.com/docker/docker/pkg/integration" |
|
| 26 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 27 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 28 | 26 |
"github.com/docker/docker/pkg/mount" |
| 29 | 27 |
"github.com/docker/docker/pkg/stringid" |
| 28 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 29 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 30 | 30 |
"github.com/docker/go-units" |
| 31 | 31 |
"github.com/docker/libnetwork/iptables" |
| 32 | 32 |
"github.com/docker/libtrust" |
| ... | ... |
@@ -1899,7 +1899,7 @@ func (s *DockerDaemonSuite) TestDaemonCgroupParent(c *check.C) {
|
| 1899 | 1899 |
|
| 1900 | 1900 |
out, err := s.d.Cmd("run", "--name", name, "busybox", "cat", "/proc/self/cgroup")
|
| 1901 | 1901 |
c.Assert(err, checker.IsNil) |
| 1902 |
- cgroupPaths := integration.ParseCgroupPaths(string(out)) |
|
| 1902 |
+ cgroupPaths := testutil.ParseCgroupPaths(string(out)) |
|
| 1903 | 1903 |
c.Assert(len(cgroupPaths), checker.Not(checker.Equals), 0, check.Commentf("unexpected output - %q", string(out)))
|
| 1904 | 1904 |
out, err = s.d.Cmd("inspect", "-f", "{{.Id}}", name)
|
| 1905 | 1905 |
c.Assert(err, checker.IsNil) |
| ... | ... |
@@ -14,9 +14,9 @@ import ( |
| 14 | 14 |
|
| 15 | 15 |
eventtypes "github.com/docker/docker/api/types/events" |
| 16 | 16 |
eventstestutils "github.com/docker/docker/daemon/events/testutils" |
| 17 |
- "github.com/docker/docker/pkg/integration" |
|
| 18 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 19 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 17 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 18 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 19 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 20 | 20 |
"github.com/go-check/check" |
| 21 | 21 |
) |
| 22 | 22 |
|
| ... | ... |
@@ -222,7 +222,7 @@ func (s *DockerSuite) TestEventsImageImport(c *check.C) {
|
| 222 | 222 |
cleanedContainerID := strings.TrimSpace(out) |
| 223 | 223 |
|
| 224 | 224 |
since := daemonUnixTime(c) |
| 225 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 225 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 226 | 226 |
exec.Command(dockerBinary, "export", cleanedContainerID), |
| 227 | 227 |
exec.Command(dockerBinary, "import", "-"), |
| 228 | 228 |
) |
| ... | ... |
@@ -15,8 +15,8 @@ import ( |
| 15 | 15 |
"sync" |
| 16 | 16 |
"time" |
| 17 | 17 |
|
| 18 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 19 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 18 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 19 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 20 | 20 |
"github.com/go-check/check" |
| 21 | 21 |
) |
| 22 | 22 |
|
| ... | ... |
@@ -16,8 +16,8 @@ import ( |
| 16 | 16 |
"time" |
| 17 | 17 |
|
| 18 | 18 |
"github.com/docker/docker/api/types" |
| 19 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 19 | 20 |
"github.com/docker/docker/integration-cli/daemon" |
| 20 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 21 | 21 |
"github.com/docker/docker/pkg/stringid" |
| 22 | 22 |
"github.com/docker/docker/volume" |
| 23 | 23 |
"github.com/go-check/check" |
| ... | ... |
@@ -7,9 +7,9 @@ import ( |
| 7 | 7 |
"strings" |
| 8 | 8 |
"unicode" |
| 9 | 9 |
|
| 10 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 10 | 11 |
"github.com/docker/docker/pkg/homedir" |
| 11 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 12 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 12 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 13 | 13 |
"github.com/go-check/check" |
| 14 | 14 |
) |
| 15 | 15 |
|
| ... | ... |
@@ -9,9 +9,9 @@ import ( |
| 9 | 9 |
"regexp" |
| 10 | 10 |
"strings" |
| 11 | 11 |
|
| 12 |
- "github.com/docker/docker/pkg/integration" |
|
| 13 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 14 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 12 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 13 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 14 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 15 | 15 |
"github.com/go-check/check" |
| 16 | 16 |
) |
| 17 | 17 |
|
| ... | ... |
@@ -20,7 +20,7 @@ func (s *DockerSuite) TestImportDisplay(c *check.C) {
|
| 20 | 20 |
out, _ := dockerCmd(c, "run", "-d", "busybox", "true") |
| 21 | 21 |
cleanedContainerID := strings.TrimSpace(out) |
| 22 | 22 |
|
| 23 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 23 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 24 | 24 |
exec.Command(dockerBinary, "export", cleanedContainerID), |
| 25 | 25 |
exec.Command(dockerBinary, "import", "-"), |
| 26 | 26 |
) |
| ... | ... |
@@ -10,9 +10,9 @@ import ( |
| 10 | 10 |
|
| 11 | 11 |
"github.com/docker/docker/api/types" |
| 12 | 12 |
"github.com/docker/docker/api/types/container" |
| 13 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 13 | 14 |
"github.com/docker/docker/integration-cli/environment" |
| 14 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 15 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 15 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 16 | 16 |
"github.com/go-check/check" |
| 17 | 17 |
) |
| 18 | 18 |
|
| ... | ... |
@@ -6,8 +6,8 @@ import ( |
| 6 | 6 |
"regexp" |
| 7 | 7 |
"strings" |
| 8 | 8 |
|
| 9 |
- "github.com/docker/docker/pkg/integration" |
|
| 10 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 9 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 10 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 11 | 11 |
"github.com/docker/docker/runconfig" |
| 12 | 12 |
"github.com/go-check/check" |
| 13 | 13 |
) |
| ... | ... |
@@ -102,7 +102,7 @@ func (s *DockerSuite) TestLinksInspectLinksStarted(c *check.C) {
|
| 102 | 102 |
err := json.Unmarshal([]byte(links), &result) |
| 103 | 103 |
c.Assert(err, checker.IsNil) |
| 104 | 104 |
|
| 105 |
- output := integration.ConvertSliceOfStringsToMap(result) |
|
| 105 |
+ output := testutil.ConvertSliceOfStringsToMap(result) |
|
| 106 | 106 |
|
| 107 | 107 |
c.Assert(output, checker.DeepEquals, expected) |
| 108 | 108 |
} |
| ... | ... |
@@ -121,7 +121,7 @@ func (s *DockerSuite) TestLinksInspectLinksStopped(c *check.C) {
|
| 121 | 121 |
err := json.Unmarshal([]byte(links), &result) |
| 122 | 122 |
c.Assert(err, checker.IsNil) |
| 123 | 123 |
|
| 124 |
- output := integration.ConvertSliceOfStringsToMap(result) |
|
| 124 |
+ output := testutil.ConvertSliceOfStringsToMap(result) |
|
| 125 | 125 |
|
| 126 | 126 |
c.Assert(output, checker.DeepEquals, expected) |
| 127 | 127 |
} |
| ... | ... |
@@ -8,9 +8,9 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
"time" |
| 10 | 10 |
|
| 11 |
- "github.com/docker/docker/pkg/integration" |
|
| 12 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 11 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 13 | 12 |
"github.com/docker/docker/pkg/jsonlog" |
| 13 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 14 | 14 |
"github.com/go-check/check" |
| 15 | 15 |
) |
| 16 | 16 |
|
| ... | ... |
@@ -254,11 +254,11 @@ func (s *DockerSuite) TestLogsFollowSlowStdoutConsumer(c *check.C) {
|
| 254 | 254 |
c.Assert(logCmd.Start(), checker.IsNil) |
| 255 | 255 |
|
| 256 | 256 |
// First read slowly |
| 257 |
- bytes1, err := integration.ConsumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead) |
|
| 257 |
+ bytes1, err := testutil.ConsumeWithSpeed(stdout, 10, 50*time.Millisecond, stopSlowRead) |
|
| 258 | 258 |
c.Assert(err, checker.IsNil) |
| 259 | 259 |
|
| 260 | 260 |
// After the container has finished we can continue reading fast |
| 261 |
- bytes2, err := integration.ConsumeWithSpeed(stdout, 32*1024, 0, nil) |
|
| 261 |
+ bytes2, err := testutil.ConsumeWithSpeed(stdout, 32*1024, 0, nil) |
|
| 262 | 262 |
c.Assert(err, checker.IsNil) |
| 263 | 263 |
|
| 264 | 264 |
actual := bytes1 + bytes2 |
| ... | ... |
@@ -16,10 +16,10 @@ import ( |
| 16 | 16 |
|
| 17 | 17 |
"github.com/docker/docker/api/types" |
| 18 | 18 |
"github.com/docker/docker/api/types/versions/v1p20" |
| 19 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 19 | 20 |
"github.com/docker/docker/integration-cli/daemon" |
| 20 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 21 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 22 | 21 |
"github.com/docker/docker/pkg/stringid" |
| 22 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 23 | 23 |
"github.com/docker/docker/runconfig" |
| 24 | 24 |
"github.com/docker/libnetwork/driverapi" |
| 25 | 25 |
remoteapi "github.com/docker/libnetwork/drivers/remote/api" |
| ... | ... |
@@ -11,9 +11,9 @@ import ( |
| 11 | 11 |
"strings" |
| 12 | 12 |
"time" |
| 13 | 13 |
|
| 14 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 15 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 14 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 16 | 15 |
"github.com/docker/docker/pkg/stringid" |
| 16 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 17 | 17 |
"github.com/go-check/check" |
| 18 | 18 |
) |
| 19 | 19 |
|
| ... | ... |
@@ -15,7 +15,7 @@ import ( |
| 15 | 15 |
"github.com/docker/distribution/manifest" |
| 16 | 16 |
"github.com/docker/distribution/manifest/manifestlist" |
| 17 | 17 |
"github.com/docker/distribution/manifest/schema2" |
| 18 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 18 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 19 | 19 |
"github.com/go-check/check" |
| 20 | 20 |
) |
| 21 | 21 |
|
| ... | ... |
@@ -7,8 +7,8 @@ import ( |
| 7 | 7 |
"strings" |
| 8 | 8 |
"time" |
| 9 | 9 |
|
| 10 |
- "github.com/docker/docker/pkg/integration" |
|
| 11 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 10 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 11 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 12 | 12 |
"github.com/go-check/check" |
| 13 | 13 |
) |
| 14 | 14 |
|
| ... | ... |
@@ -70,7 +70,7 @@ func (s *DockerTrustSuite) TestPullWhenCertExpired(c *check.C) {
|
| 70 | 70 |
// Certificates have 10 years of expiration |
| 71 | 71 |
elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11) |
| 72 | 72 |
|
| 73 |
- integration.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 73 |
+ testutil.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 74 | 74 |
// Try pull |
| 75 | 75 |
pullCmd := exec.Command(dockerBinary, "pull", repoName) |
| 76 | 76 |
s.trustedCmd(pullCmd) |
| ... | ... |
@@ -80,7 +80,7 @@ func (s *DockerTrustSuite) TestPullWhenCertExpired(c *check.C) {
|
| 80 | 80 |
c.Assert(string(out), checker.Contains, "could not validate the path to a trusted root", check.Commentf(out)) |
| 81 | 81 |
}) |
| 82 | 82 |
|
| 83 |
- integration.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 83 |
+ testutil.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 84 | 84 |
// Try pull |
| 85 | 85 |
pullCmd := exec.Command(dockerBinary, "pull", "--disable-content-trust", repoName) |
| 86 | 86 |
s.trustedCmd(pullCmd) |
| ... | ... |
@@ -167,7 +167,7 @@ func (s *DockerTrustSuite) TestTrustedPullWithExpiredSnapshot(c *check.C) {
|
| 167 | 167 |
// Snapshots last for three years. This should be expired |
| 168 | 168 |
fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4) |
| 169 | 169 |
|
| 170 |
- integration.RunAtDifferentDate(fourYearsLater, func() {
|
|
| 170 |
+ testutil.RunAtDifferentDate(fourYearsLater, func() {
|
|
| 171 | 171 |
// Try pull |
| 172 | 172 |
pullCmd := exec.Command(dockerBinary, "pull", repoName) |
| 173 | 173 |
s.trustedCmd(pullCmd) |
| ... | ... |
@@ -15,8 +15,8 @@ import ( |
| 15 | 15 |
|
| 16 | 16 |
"github.com/docker/distribution/reference" |
| 17 | 17 |
cliconfig "github.com/docker/docker/cli/config" |
| 18 |
- "github.com/docker/docker/pkg/integration" |
|
| 19 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 18 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 19 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 20 | 20 |
"github.com/go-check/check" |
| 21 | 21 |
) |
| 22 | 22 |
|
| ... | ... |
@@ -438,7 +438,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithExpiredSnapshot(c *check.C) {
|
| 438 | 438 |
// Snapshots last for three years. This should be expired |
| 439 | 439 |
fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4) |
| 440 | 440 |
|
| 441 |
- integration.RunAtDifferentDate(fourYearsLater, func() {
|
|
| 441 |
+ testutil.RunAtDifferentDate(fourYearsLater, func() {
|
|
| 442 | 442 |
// Push with wrong passphrases |
| 443 | 443 |
pushCmd = exec.Command(dockerBinary, "push", repoName) |
| 444 | 444 |
s.trustedCmd(pushCmd) |
| ... | ... |
@@ -465,7 +465,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) {
|
| 465 | 465 |
threeWeeksLater := time.Now().Add(time.Hour * 24 * 21) |
| 466 | 466 |
|
| 467 | 467 |
// Should succeed because the server transparently re-signs one |
| 468 |
- integration.RunAtDifferentDate(threeWeeksLater, func() {
|
|
| 468 |
+ testutil.RunAtDifferentDate(threeWeeksLater, func() {
|
|
| 469 | 469 |
pushCmd := exec.Command(dockerBinary, "push", repoName) |
| 470 | 470 |
s.trustedCmd(pushCmd) |
| 471 | 471 |
out, _, err := runCommandWithOutput(pushCmd) |
| ... | ... |
@@ -3,9 +3,9 @@ package main |
| 3 | 3 |
import ( |
| 4 | 4 |
"strings" |
| 5 | 5 |
|
| 6 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 7 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 6 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 8 | 7 |
"github.com/docker/docker/pkg/stringid" |
| 8 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 9 | 9 |
"github.com/go-check/check" |
| 10 | 10 |
) |
| 11 | 11 |
|
| ... | ... |
@@ -21,12 +21,12 @@ import ( |
| 21 | 21 |
"sync" |
| 22 | 22 |
"time" |
| 23 | 23 |
|
| 24 |
- "github.com/docker/docker/pkg/integration" |
|
| 25 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 26 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 24 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 27 | 25 |
"github.com/docker/docker/pkg/mount" |
| 28 | 26 |
"github.com/docker/docker/pkg/stringid" |
| 29 | 27 |
"github.com/docker/docker/pkg/stringutils" |
| 28 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 29 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 30 | 30 |
"github.com/docker/docker/runconfig" |
| 31 | 31 |
"github.com/docker/go-connections/nat" |
| 32 | 32 |
"github.com/docker/libnetwork/resolvconf" |
| ... | ... |
@@ -498,7 +498,7 @@ func (s *DockerSuite) TestRunVolumesFromInReadWriteMode(c *check.C) {
|
| 498 | 498 |
func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
|
| 499 | 499 |
testRequires(c, SameHostDaemon) |
| 500 | 500 |
prefix, slash := getPrefixAndSlashFromDaemonPlatform() |
| 501 |
- hostpath := integration.RandomTmpDirPath("test", daemonPlatform)
|
|
| 501 |
+ hostpath := testutil.RandomTmpDirPath("test", daemonPlatform)
|
|
| 502 | 502 |
if err := os.MkdirAll(hostpath, 0755); err != nil {
|
| 503 | 503 |
c.Fatalf("Failed to create %s: %q", hostpath, err)
|
| 504 | 504 |
} |
| ... | ... |
@@ -521,8 +521,8 @@ func (s *DockerSuite) TestVolumesFromGetsProperMode(c *check.C) {
|
| 521 | 521 |
|
| 522 | 522 |
// Test for GH#10618 |
| 523 | 523 |
func (s *DockerSuite) TestRunNoDupVolumes(c *check.C) {
|
| 524 |
- path1 := integration.RandomTmpDirPath("test1", daemonPlatform)
|
|
| 525 |
- path2 := integration.RandomTmpDirPath("test2", daemonPlatform)
|
|
| 524 |
+ path1 := testutil.RandomTmpDirPath("test1", daemonPlatform)
|
|
| 525 |
+ path2 := testutil.RandomTmpDirPath("test2", daemonPlatform)
|
|
| 526 | 526 |
|
| 527 | 527 |
someplace := ":/someplace" |
| 528 | 528 |
if daemonPlatform == "windows" {
|
| ... | ... |
@@ -2275,7 +2275,7 @@ func (s *DockerSuite) TestVolumesNoCopyData(c *check.C) {
|
| 2275 | 2275 |
c.Fatalf("Data was copied on volumes-from but shouldn't be:\n%q", out)
|
| 2276 | 2276 |
} |
| 2277 | 2277 |
|
| 2278 |
- tmpDir := integration.RandomTmpDirPath("docker_test_bind_mount_copy_data", daemonPlatform)
|
|
| 2278 |
+ tmpDir := testutil.RandomTmpDirPath("docker_test_bind_mount_copy_data", daemonPlatform)
|
|
| 2279 | 2279 |
if out, _, err := dockerCmdWithError("run", "-v", tmpDir+":/foo", "dataimage", "ls", "-lh", "/foo/bar"); err == nil || !strings.Contains(out, "No such file or directory") {
|
| 2280 | 2280 |
c.Fatalf("Data was copied on bind-mount but shouldn't be:\n%q", out)
|
| 2281 | 2281 |
} |
| ... | ... |
@@ -2344,7 +2344,7 @@ func (s *DockerSuite) TestRunSlowStdoutConsumer(c *check.C) {
|
| 2344 | 2344 |
if err := cont.Start(); err != nil {
|
| 2345 | 2345 |
c.Fatal(err) |
| 2346 | 2346 |
} |
| 2347 |
- n, err := integration.ConsumeWithSpeed(stdout, 10000, 5*time.Millisecond, nil) |
|
| 2347 |
+ n, err := testutil.ConsumeWithSpeed(stdout, 10000, 5*time.Millisecond, nil) |
|
| 2348 | 2348 |
if err != nil {
|
| 2349 | 2349 |
c.Fatal(err) |
| 2350 | 2350 |
} |
| ... | ... |
@@ -3326,7 +3326,7 @@ func (s *DockerTrustSuite) TestRunWhenCertExpired(c *check.C) {
|
| 3326 | 3326 |
// Certificates have 10 years of expiration |
| 3327 | 3327 |
elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11) |
| 3328 | 3328 |
|
| 3329 |
- integration.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 3329 |
+ testutil.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 3330 | 3330 |
// Try run |
| 3331 | 3331 |
runCmd := exec.Command(dockerBinary, "run", repoName) |
| 3332 | 3332 |
s.trustedCmd(runCmd) |
| ... | ... |
@@ -3340,7 +3340,7 @@ func (s *DockerTrustSuite) TestRunWhenCertExpired(c *check.C) {
|
| 3340 | 3340 |
} |
| 3341 | 3341 |
}) |
| 3342 | 3342 |
|
| 3343 |
- integration.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 3343 |
+ testutil.RunAtDifferentDate(elevenYearsFromNow, func() {
|
|
| 3344 | 3344 |
// Try run |
| 3345 | 3345 |
runCmd := exec.Command(dockerBinary, "run", "--disable-content-trust", repoName) |
| 3346 | 3346 |
s.trustedCmd(runCmd) |
| ... | ... |
@@ -3532,7 +3532,7 @@ func (s *DockerSuite) TestRunContainerWithCgroupParent(c *check.C) {
|
| 3532 | 3532 |
if err != nil {
|
| 3533 | 3533 |
c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
|
| 3534 | 3534 |
} |
| 3535 |
- cgroupPaths := integration.ParseCgroupPaths(string(out)) |
|
| 3535 |
+ cgroupPaths := testutil.ParseCgroupPaths(string(out)) |
|
| 3536 | 3536 |
if len(cgroupPaths) == 0 {
|
| 3537 | 3537 |
c.Fatalf("unexpected output - %q", string(out))
|
| 3538 | 3538 |
} |
| ... | ... |
@@ -3561,7 +3561,7 @@ func (s *DockerSuite) TestRunContainerWithCgroupParentAbsPath(c *check.C) {
|
| 3561 | 3561 |
if err != nil {
|
| 3562 | 3562 |
c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
|
| 3563 | 3563 |
} |
| 3564 |
- cgroupPaths := integration.ParseCgroupPaths(string(out)) |
|
| 3564 |
+ cgroupPaths := testutil.ParseCgroupPaths(string(out)) |
|
| 3565 | 3565 |
if len(cgroupPaths) == 0 {
|
| 3566 | 3566 |
c.Fatalf("unexpected output - %q", string(out))
|
| 3567 | 3567 |
} |
| ... | ... |
@@ -3600,7 +3600,7 @@ func (s *DockerSuite) TestRunInvalidCgroupParent(c *check.C) {
|
| 3600 | 3600 |
c.Fatalf("SECURITY: --cgroup-parent with ../../ relative paths cause files to be created in the host (this is bad) !!")
|
| 3601 | 3601 |
} |
| 3602 | 3602 |
|
| 3603 |
- cgroupPaths := integration.ParseCgroupPaths(string(out)) |
|
| 3603 |
+ cgroupPaths := testutil.ParseCgroupPaths(string(out)) |
|
| 3604 | 3604 |
if len(cgroupPaths) == 0 {
|
| 3605 | 3605 |
c.Fatalf("unexpected output - %q", string(out))
|
| 3606 | 3606 |
} |
| ... | ... |
@@ -3639,7 +3639,7 @@ func (s *DockerSuite) TestRunAbsoluteInvalidCgroupParent(c *check.C) {
|
| 3639 | 3639 |
c.Fatalf("SECURITY: --cgroup-parent with /../../ garbage paths cause files to be created in the host (this is bad) !!")
|
| 3640 | 3640 |
} |
| 3641 | 3641 |
|
| 3642 |
- cgroupPaths := integration.ParseCgroupPaths(string(out)) |
|
| 3642 |
+ cgroupPaths := testutil.ParseCgroupPaths(string(out)) |
|
| 3643 | 3643 |
if len(cgroupPaths) == 0 {
|
| 3644 | 3644 |
c.Fatalf("unexpected output - %q", string(out))
|
| 3645 | 3645 |
} |
| ... | ... |
@@ -16,8 +16,8 @@ import ( |
| 16 | 16 |
"syscall" |
| 17 | 17 |
"time" |
| 18 | 18 |
|
| 19 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 19 | 20 |
"github.com/docker/docker/pkg/homedir" |
| 20 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 21 | 21 |
"github.com/docker/docker/pkg/mount" |
| 22 | 22 |
"github.com/docker/docker/pkg/parsers" |
| 23 | 23 |
"github.com/docker/docker/pkg/sysinfo" |
| ... | ... |
@@ -14,8 +14,8 @@ import ( |
| 14 | 14 |
"time" |
| 15 | 15 |
|
| 16 | 16 |
"github.com/docker/distribution/digest" |
| 17 |
- "github.com/docker/docker/pkg/integration" |
|
| 18 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 17 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 18 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 19 | 19 |
"github.com/go-check/check" |
| 20 | 20 |
) |
| 21 | 21 |
|
| ... | ... |
@@ -30,7 +30,7 @@ func (s *DockerSuite) TestSaveXzAndLoadRepoStdout(c *check.C) {
|
| 30 | 30 |
|
| 31 | 31 |
dockerCmd(c, "inspect", repoName) |
| 32 | 32 |
|
| 33 |
- repoTarball, _, err := integration.RunCommandPipelineWithOutput( |
|
| 33 |
+ repoTarball, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 34 | 34 |
exec.Command(dockerBinary, "save", repoName), |
| 35 | 35 |
exec.Command("xz", "-c"),
|
| 36 | 36 |
exec.Command("gzip", "-c"))
|
| ... | ... |
@@ -57,7 +57,7 @@ func (s *DockerSuite) TestSaveXzGzAndLoadRepoStdout(c *check.C) {
|
| 57 | 57 |
|
| 58 | 58 |
dockerCmd(c, "inspect", repoName) |
| 59 | 59 |
|
| 60 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 60 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 61 | 61 |
exec.Command(dockerBinary, "save", repoName), |
| 62 | 62 |
exec.Command("xz", "-c"),
|
| 63 | 63 |
exec.Command("gzip", "-c"))
|
| ... | ... |
@@ -82,7 +82,7 @@ func (s *DockerSuite) TestSaveSingleTag(c *check.C) {
|
| 82 | 82 |
out, _ := dockerCmd(c, "images", "-q", "--no-trunc", repoName) |
| 83 | 83 |
cleanedImageID := strings.TrimSpace(out) |
| 84 | 84 |
|
| 85 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 85 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 86 | 86 |
exec.Command(dockerBinary, "save", fmt.Sprintf("%v:latest", repoName)),
|
| 87 | 87 |
exec.Command("tar", "t"),
|
| 88 | 88 |
exec.Command("grep", "-E", fmt.Sprintf("(^repositories$|%v)", cleanedImageID)))
|
| ... | ... |
@@ -101,7 +101,7 @@ func (s *DockerSuite) TestSaveCheckTimes(c *check.C) {
|
| 101 | 101 |
c.Assert(err, checker.IsNil, check.Commentf("failed to marshal from %q: err %v", repoName, err))
|
| 102 | 102 |
c.Assert(len(data), checker.Not(checker.Equals), 0, check.Commentf("failed to marshal the data from %q", repoName))
|
| 103 | 103 |
tarTvTimeFormat := "2006-01-02 15:04" |
| 104 |
- out, _, err = integration.RunCommandPipelineWithOutput( |
|
| 104 |
+ out, _, err = testutil.RunCommandPipelineWithOutput( |
|
| 105 | 105 |
exec.Command(dockerBinary, "save", repoName), |
| 106 | 106 |
exec.Command("tar", "tv"),
|
| 107 | 107 |
exec.Command("grep", "-E", fmt.Sprintf("%s %s", data[0].Created.Format(tarTvTimeFormat), digest.Digest(data[0].ID).Hex())))
|
| ... | ... |
@@ -159,7 +159,7 @@ func (s *DockerSuite) TestSaveAndLoadRepoFlags(c *check.C) {
|
| 159 | 159 |
|
| 160 | 160 |
before, _ := dockerCmd(c, "inspect", repoName) |
| 161 | 161 |
|
| 162 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 162 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 163 | 163 |
exec.Command(dockerBinary, "save", repoName), |
| 164 | 164 |
exec.Command(dockerBinary, "load")) |
| 165 | 165 |
c.Assert(err, checker.IsNil, check.Commentf("failed to save and load repo: %s, %v", out, err))
|
| ... | ... |
@@ -188,7 +188,7 @@ func (s *DockerSuite) TestSaveMultipleNames(c *check.C) {
|
| 188 | 188 |
// Make two images |
| 189 | 189 |
dockerCmd(c, "tag", "emptyfs:latest", fmt.Sprintf("%v-two:latest", repoName))
|
| 190 | 190 |
|
| 191 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 191 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 192 | 192 |
exec.Command(dockerBinary, "save", fmt.Sprintf("%v-one", repoName), fmt.Sprintf("%v-two:latest", repoName)),
|
| 193 | 193 |
exec.Command("tar", "xO", "repositories"),
|
| 194 | 194 |
exec.Command("grep", "-q", "-E", "(-one|-two)"),
|
| ... | ... |
@@ -220,7 +220,7 @@ func (s *DockerSuite) TestSaveRepoWithMultipleImages(c *check.C) {
|
| 220 | 220 |
deleteImages(repoName) |
| 221 | 221 |
|
| 222 | 222 |
// create the archive |
| 223 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 223 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 224 | 224 |
exec.Command(dockerBinary, "save", repoName, "busybox:latest"), |
| 225 | 225 |
exec.Command("tar", "t"))
|
| 226 | 226 |
c.Assert(err, checker.IsNil, check.Commentf("failed to save multiple images: %s, %v", out, err))
|
| ... | ... |
@@ -267,7 +267,7 @@ func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
|
| 267 | 267 |
true) |
| 268 | 268 |
c.Assert(err, checker.IsNil, check.Commentf("%v", err))
|
| 269 | 269 |
|
| 270 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 270 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 271 | 271 |
exec.Command(dockerBinary, "save", name), |
| 272 | 272 |
exec.Command("tar", "-xf", "-", "-C", extractionDirectory),
|
| 273 | 273 |
) |
| ... | ... |
@@ -286,7 +286,7 @@ func (s *DockerSuite) TestSaveDirectoryPermissions(c *check.C) {
|
| 286 | 286 |
c.Assert(err, checker.IsNil, check.Commentf("failed to open %s: %s", layerPath, err))
|
| 287 | 287 |
defer f.Close() |
| 288 | 288 |
|
| 289 |
- entries, err := integration.ListTar(f) |
|
| 289 |
+ entries, err := testutil.ListTar(f) |
|
| 290 | 290 |
for _, e := range entries {
|
| 291 | 291 |
if !strings.Contains(e, "dev/") {
|
| 292 | 292 |
entriesSansDev = append(entriesSansDev, e) |
| ... | ... |
@@ -364,7 +364,7 @@ func (s *DockerSuite) TestSaveLoadNoTag(c *check.C) {
|
| 364 | 364 |
id := inspectField(c, name, "Id") |
| 365 | 365 |
|
| 366 | 366 |
// Test to make sure that save w/o name just shows imageID during load |
| 367 |
- out, _, err := integration.RunCommandPipelineWithOutput( |
|
| 367 |
+ out, _, err := testutil.RunCommandPipelineWithOutput( |
|
| 368 | 368 |
exec.Command(dockerBinary, "save", id), |
| 369 | 369 |
exec.Command(dockerBinary, "load")) |
| 370 | 370 |
c.Assert(err, checker.IsNil, check.Commentf("failed to save and load repo: %s, %v", out, err))
|
| ... | ... |
@@ -375,7 +375,7 @@ func (s *DockerSuite) TestSaveLoadNoTag(c *check.C) {
|
| 375 | 375 |
c.Assert(out, checker.Contains, id) |
| 376 | 376 |
|
| 377 | 377 |
// Test to make sure that save by name shows that name during load |
| 378 |
- out, _, err = integration.RunCommandPipelineWithOutput( |
|
| 378 |
+ out, _, err = testutil.RunCommandPipelineWithOutput( |
|
| 379 | 379 |
exec.Command(dockerBinary, "save", name), |
| 380 | 380 |
exec.Command(dockerBinary, "load")) |
| 381 | 381 |
c.Assert(err, checker.IsNil, check.Commentf("failed to save and load repo: %s, %v", out, err))
|
| ... | ... |
@@ -11,8 +11,8 @@ import ( |
| 11 | 11 |
"strings" |
| 12 | 12 |
"time" |
| 13 | 13 |
|
| 14 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 15 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 14 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 15 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 16 | 16 |
"github.com/go-check/check" |
| 17 | 17 |
"github.com/kr/pty" |
| 18 | 18 |
) |
| ... | ... |
@@ -10,7 +10,7 @@ import ( |
| 10 | 10 |
"github.com/docker/docker/api/types" |
| 11 | 11 |
"github.com/docker/docker/api/types/mount" |
| 12 | 12 |
"github.com/docker/docker/api/types/swarm" |
| 13 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 13 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 14 | 14 |
"github.com/go-check/check" |
| 15 | 15 |
) |
| 16 | 16 |
|
| ... | ... |
@@ -8,7 +8,7 @@ import ( |
| 8 | 8 |
|
| 9 | 9 |
"github.com/docker/docker/api/types/swarm" |
| 10 | 10 |
"github.com/docker/docker/daemon/cluster/executor/container" |
| 11 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 11 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 12 | 12 |
"github.com/go-check/check" |
| 13 | 13 |
) |
| 14 | 14 |
|
| ... | ... |
@@ -5,8 +5,8 @@ import ( |
| 5 | 5 |
"strings" |
| 6 | 6 |
"time" |
| 7 | 7 |
|
| 8 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 9 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 8 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 9 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 10 | 10 |
"github.com/go-check/check" |
| 11 | 11 |
) |
| 12 | 12 |
|
| ... | ... |
@@ -15,8 +15,8 @@ import ( |
| 15 | 15 |
"time" |
| 16 | 16 |
|
| 17 | 17 |
"github.com/docker/docker/api/types/swarm" |
| 18 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 18 | 19 |
"github.com/docker/docker/integration-cli/daemon" |
| 19 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 20 | 20 |
"github.com/docker/libnetwork/driverapi" |
| 21 | 21 |
"github.com/docker/libnetwork/ipamapi" |
| 22 | 22 |
remoteipam "github.com/docker/libnetwork/ipams/remote/api" |
| ... | ... |
@@ -3,8 +3,8 @@ package main |
| 3 | 3 |
import ( |
| 4 | 4 |
"strings" |
| 5 | 5 |
|
| 6 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 7 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 6 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 7 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 8 | 8 |
"github.com/go-check/check" |
| 9 | 9 |
) |
| 10 | 10 |
|
| ... | ... |
@@ -11,7 +11,7 @@ import ( |
| 11 | 11 |
"time" |
| 12 | 12 |
|
| 13 | 13 |
"github.com/docker/docker/api/types" |
| 14 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 14 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 15 | 15 |
"github.com/docker/docker/pkg/parsers/kernel" |
| 16 | 16 |
"github.com/go-check/check" |
| 17 | 17 |
) |
| ... | ... |
@@ -12,10 +12,10 @@ import ( |
| 12 | 12 |
"strconv" |
| 13 | 13 |
"strings" |
| 14 | 14 |
|
| 15 |
- "github.com/docker/docker/pkg/integration" |
|
| 16 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 15 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 17 | 16 |
"github.com/docker/docker/pkg/stringid" |
| 18 | 17 |
"github.com/docker/docker/pkg/system" |
| 18 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 19 | 19 |
"github.com/go-check/check" |
| 20 | 20 |
) |
| 21 | 21 |
|
| ... | ... |
@@ -62,12 +62,12 @@ func (s *DockerDaemonSuite) TestDaemonUserNamespaceRootSetting(c *check.C) {
|
| 62 | 62 |
c.Assert(err, checker.IsNil, check.Commentf("Could not inspect running container: out: %q", pid))
|
| 63 | 63 |
// check the uid and gid maps for the PID to ensure root is remapped |
| 64 | 64 |
// (cmd = cat /proc/<pid>/uid_map | grep -E '0\s+9999\s+1') |
| 65 |
- out, rc1, err := integration.RunCommandPipelineWithOutput( |
|
| 65 |
+ out, rc1, err := testutil.RunCommandPipelineWithOutput( |
|
| 66 | 66 |
exec.Command("cat", "/proc/"+strings.TrimSpace(pid)+"/uid_map"),
|
| 67 | 67 |
exec.Command("grep", "-E", fmt.Sprintf("0[[:space:]]+%d[[:space:]]+", uid)))
|
| 68 | 68 |
c.Assert(rc1, checker.Equals, 0, check.Commentf("Didn't match uid_map: output: %s", out))
|
| 69 | 69 |
|
| 70 |
- out, rc2, err := integration.RunCommandPipelineWithOutput( |
|
| 70 |
+ out, rc2, err := testutil.RunCommandPipelineWithOutput( |
|
| 71 | 71 |
exec.Command("cat", "/proc/"+strings.TrimSpace(pid)+"/gid_map"),
|
| 72 | 72 |
exec.Command("grep", "-E", fmt.Sprintf("0[[:space:]]+%d[[:space:]]+", gid)))
|
| 73 | 73 |
c.Assert(rc2, checker.Equals, 0, check.Commentf("Didn't match gid_map: output: %s", out))
|
| ... | ... |
@@ -8,8 +8,8 @@ import ( |
| 8 | 8 |
"path/filepath" |
| 9 | 9 |
"strings" |
| 10 | 10 |
|
| 11 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 12 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 11 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 12 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 13 | 13 |
"github.com/go-check/check" |
| 14 | 14 |
) |
| 15 | 15 |
|
| ... | ... |
@@ -7,8 +7,8 @@ import ( |
| 7 | 7 |
"net/http" |
| 8 | 8 |
"strings" |
| 9 | 9 |
|
| 10 |
- "github.com/docker/docker/pkg/integration" |
|
| 11 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 10 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 11 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 12 | 12 |
"github.com/go-check/check" |
| 13 | 13 |
) |
| 14 | 14 |
|
| ... | ... |
@@ -45,7 +45,7 @@ func (s *DockerSuite) TestDeprecatedContainerAPIStartVolumeBinds(c *check.C) {
|
| 45 | 45 |
c.Assert(err, checker.IsNil) |
| 46 | 46 |
c.Assert(status, checker.Equals, http.StatusCreated) |
| 47 | 47 |
|
| 48 |
- bindPath := integration.RandomTmpDirPath("test", daemonPlatform)
|
|
| 48 |
+ bindPath := testutil.RandomTmpDirPath("test", daemonPlatform)
|
|
| 49 | 49 |
config = map[string]interface{}{
|
| 50 | 50 |
"Binds": []string{bindPath + ":" + path},
|
| 51 | 51 |
} |
| ... | ... |
@@ -72,8 +72,8 @@ func (s *DockerSuite) TestDeprecatedContainerAPIStartDupVolumeBinds(c *check.C) |
| 72 | 72 |
c.Assert(err, checker.IsNil) |
| 73 | 73 |
c.Assert(status, checker.Equals, http.StatusCreated) |
| 74 | 74 |
|
| 75 |
- bindPath1 := integration.RandomTmpDirPath("test1", daemonPlatform)
|
|
| 76 |
- bindPath2 := integration.RandomTmpDirPath("test2", daemonPlatform)
|
|
| 75 |
+ bindPath1 := testutil.RandomTmpDirPath("test1", daemonPlatform)
|
|
| 76 |
+ bindPath2 := testutil.RandomTmpDirPath("test2", daemonPlatform)
|
|
| 77 | 77 |
|
| 78 | 78 |
config = map[string]interface{}{
|
| 79 | 79 |
"Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"},
|
| ... | ... |
@@ -151,7 +151,7 @@ func (s *DockerSuite) TestDeprecatedStartWithTooLowMemoryLimit(c *check.C) {
|
| 151 | 151 |
|
| 152 | 152 |
res, body, err := sockRequestRaw("POST", formatV123StartAPIURL("/containers/"+containerID+"/start"), strings.NewReader(config), "application/json")
|
| 153 | 153 |
c.Assert(err, checker.IsNil) |
| 154 |
- b, err2 := integration.ReadBody(body) |
|
| 154 |
+ b, err2 := testutil.ReadBody(body) |
|
| 155 | 155 |
c.Assert(err2, checker.IsNil) |
| 156 | 156 |
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError) |
| 157 | 157 |
c.Assert(string(b), checker.Contains, "Minimum memory limit allowed is 4MB") |
| ... | ... |
@@ -7,9 +7,9 @@ import ( |
| 7 | 7 |
"strings" |
| 8 | 8 |
"time" |
| 9 | 9 |
|
| 10 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 11 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 10 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 12 | 11 |
"github.com/docker/docker/pkg/parsers/kernel" |
| 12 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 13 | 13 |
"github.com/go-check/check" |
| 14 | 14 |
) |
| 15 | 15 |
|
| ... | ... |
@@ -23,13 +23,13 @@ import ( |
| 23 | 23 |
|
| 24 | 24 |
"github.com/docker/docker/api/types" |
| 25 | 25 |
volumetypes "github.com/docker/docker/api/types/volume" |
| 26 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 26 | 27 |
"github.com/docker/docker/integration-cli/daemon" |
| 27 | 28 |
"github.com/docker/docker/opts" |
| 28 |
- "github.com/docker/docker/pkg/integration" |
|
| 29 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 30 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 31 | 29 |
"github.com/docker/docker/pkg/ioutils" |
| 32 | 30 |
"github.com/docker/docker/pkg/stringutils" |
| 31 |
+ "github.com/docker/docker/pkg/testutil" |
|
| 32 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 33 | 33 |
"github.com/go-check/check" |
| 34 | 34 |
) |
| 35 | 35 |
|
| ... | ... |
@@ -59,7 +59,7 @@ func sockRequest(method, endpoint string, data interface{}) (int, []byte, error)
|
| 59 | 59 |
if err != nil {
|
| 60 | 60 |
return -1, nil, err |
| 61 | 61 |
} |
| 62 |
- b, err := integration.ReadBody(body) |
|
| 62 |
+ b, err := testutil.ReadBody(body) |
|
| 63 | 63 |
return res.StatusCode, b, err |
| 64 | 64 |
} |
| 65 | 65 |
|
| ... | ... |
@@ -11,7 +11,7 @@ import ( |
| 11 | 11 |
|
| 12 | 12 |
"github.com/Sirupsen/logrus" |
| 13 | 13 |
eventstestutils "github.com/docker/docker/daemon/events/testutils" |
| 14 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 14 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 15 | 15 |
"github.com/go-check/check" |
| 16 | 16 |
) |
| 17 | 17 |
|
| ... | ... |
@@ -12,7 +12,7 @@ import ( |
| 12 | 12 |
"time" |
| 13 | 13 |
|
| 14 | 14 |
cliconfig "github.com/docker/docker/cli/config" |
| 15 |
- "github.com/docker/docker/pkg/integration/checker" |
|
| 15 |
+ "github.com/docker/docker/integration-cli/checker" |
|
| 16 | 16 |
"github.com/docker/go-connections/tlsconfig" |
| 17 | 17 |
"github.com/go-check/check" |
| 18 | 18 |
) |
| 8 | 8 |
deleted file mode 100644 |
| ... | ... |
@@ -1,46 +0,0 @@ |
| 1 |
-// Package checker provides Docker specific implementations of the go-check.Checker interface. |
|
| 2 |
-package checker |
|
| 3 |
- |
|
| 4 |
-import ( |
|
| 5 |
- "github.com/go-check/check" |
|
| 6 |
- "github.com/vdemeester/shakers" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-// As a commodity, we bring all check.Checker variables into the current namespace to avoid having |
|
| 10 |
-// to think about check.X versus checker.X. |
|
| 11 |
-var ( |
|
| 12 |
- DeepEquals = check.DeepEquals |
|
| 13 |
- ErrorMatches = check.ErrorMatches |
|
| 14 |
- FitsTypeOf = check.FitsTypeOf |
|
| 15 |
- HasLen = check.HasLen |
|
| 16 |
- Implements = check.Implements |
|
| 17 |
- IsNil = check.IsNil |
|
| 18 |
- Matches = check.Matches |
|
| 19 |
- Not = check.Not |
|
| 20 |
- NotNil = check.NotNil |
|
| 21 |
- PanicMatches = check.PanicMatches |
|
| 22 |
- Panics = check.Panics |
|
| 23 |
- |
|
| 24 |
- Contains = shakers.Contains |
|
| 25 |
- ContainsAny = shakers.ContainsAny |
|
| 26 |
- Count = shakers.Count |
|
| 27 |
- Equals = shakers.Equals |
|
| 28 |
- EqualFold = shakers.EqualFold |
|
| 29 |
- False = shakers.False |
|
| 30 |
- GreaterOrEqualThan = shakers.GreaterOrEqualThan |
|
| 31 |
- GreaterThan = shakers.GreaterThan |
|
| 32 |
- HasPrefix = shakers.HasPrefix |
|
| 33 |
- HasSuffix = shakers.HasSuffix |
|
| 34 |
- Index = shakers.Index |
|
| 35 |
- IndexAny = shakers.IndexAny |
|
| 36 |
- IsAfter = shakers.IsAfter |
|
| 37 |
- IsBefore = shakers.IsBefore |
|
| 38 |
- IsBetween = shakers.IsBetween |
|
| 39 |
- IsLower = shakers.IsLower |
|
| 40 |
- IsUpper = shakers.IsUpper |
|
| 41 |
- LessOrEqualThan = shakers.LessOrEqualThan |
|
| 42 |
- LessThan = shakers.LessThan |
|
| 43 |
- TimeEquals = shakers.TimeEquals |
|
| 44 |
- True = shakers.True |
|
| 45 |
- TimeIgnore = shakers.TimeIgnore |
|
| 46 |
-) |
| 47 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,294 +0,0 @@ |
| 1 |
-package cmd |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "fmt" |
|
| 6 |
- "io" |
|
| 7 |
- "os/exec" |
|
| 8 |
- "path/filepath" |
|
| 9 |
- "runtime" |
|
| 10 |
- "strings" |
|
| 11 |
- "sync" |
|
| 12 |
- "time" |
|
| 13 |
- |
|
| 14 |
- "github.com/docker/docker/pkg/system" |
|
| 15 |
- "github.com/go-check/check" |
|
| 16 |
-) |
|
| 17 |
- |
|
| 18 |
-type testingT interface {
|
|
| 19 |
- Fatalf(string, ...interface{})
|
|
| 20 |
-} |
|
| 21 |
- |
|
| 22 |
-const ( |
|
| 23 |
- // None is a token to inform Result.Assert that the output should be empty |
|
| 24 |
- None string = "<NOTHING>" |
|
| 25 |
-) |
|
| 26 |
- |
|
| 27 |
-type lockedBuffer struct {
|
|
| 28 |
- m sync.RWMutex |
|
| 29 |
- buf bytes.Buffer |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-func (buf *lockedBuffer) Write(b []byte) (int, error) {
|
|
| 33 |
- buf.m.Lock() |
|
| 34 |
- defer buf.m.Unlock() |
|
| 35 |
- return buf.buf.Write(b) |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-func (buf *lockedBuffer) String() string {
|
|
| 39 |
- buf.m.RLock() |
|
| 40 |
- defer buf.m.RUnlock() |
|
| 41 |
- return buf.buf.String() |
|
| 42 |
-} |
|
| 43 |
- |
|
| 44 |
-// Result stores the result of running a command |
|
| 45 |
-type Result struct {
|
|
| 46 |
- Cmd *exec.Cmd |
|
| 47 |
- ExitCode int |
|
| 48 |
- Error error |
|
| 49 |
- // Timeout is true if the command was killed because it ran for too long |
|
| 50 |
- Timeout bool |
|
| 51 |
- outBuffer *lockedBuffer |
|
| 52 |
- errBuffer *lockedBuffer |
|
| 53 |
-} |
|
| 54 |
- |
|
| 55 |
-// Assert compares the Result against the Expected struct, and fails the test if |
|
| 56 |
-// any of the expcetations are not met. |
|
| 57 |
-func (r *Result) Assert(t testingT, exp Expected) {
|
|
| 58 |
- err := r.Compare(exp) |
|
| 59 |
- if err == nil {
|
|
| 60 |
- return |
|
| 61 |
- } |
|
| 62 |
- |
|
| 63 |
- _, file, line, _ := runtime.Caller(1) |
|
| 64 |
- t.Fatalf("at %s:%d\n%s", filepath.Base(file), line, err.Error())
|
|
| 65 |
-} |
|
| 66 |
- |
|
| 67 |
-// Compare returns a formatted error with the command, stdout, stderr, exit |
|
| 68 |
-// code, and any failed expectations |
|
| 69 |
-func (r *Result) Compare(exp Expected) error {
|
|
| 70 |
- errors := []string{}
|
|
| 71 |
- add := func(format string, args ...interface{}) {
|
|
| 72 |
- errors = append(errors, fmt.Sprintf(format, args...)) |
|
| 73 |
- } |
|
| 74 |
- |
|
| 75 |
- if exp.ExitCode != r.ExitCode {
|
|
| 76 |
- add("ExitCode was %d expected %d", r.ExitCode, exp.ExitCode)
|
|
| 77 |
- } |
|
| 78 |
- if exp.Timeout != r.Timeout {
|
|
| 79 |
- if exp.Timeout {
|
|
| 80 |
- add("Expected command to timeout")
|
|
| 81 |
- } else {
|
|
| 82 |
- add("Expected command to finish, but it hit the timeout")
|
|
| 83 |
- } |
|
| 84 |
- } |
|
| 85 |
- if !matchOutput(exp.Out, r.Stdout()) {
|
|
| 86 |
- add("Expected stdout to contain %q", exp.Out)
|
|
| 87 |
- } |
|
| 88 |
- if !matchOutput(exp.Err, r.Stderr()) {
|
|
| 89 |
- add("Expected stderr to contain %q", exp.Err)
|
|
| 90 |
- } |
|
| 91 |
- switch {
|
|
| 92 |
- // If a non-zero exit code is expected there is going to be an error. |
|
| 93 |
- // Don't require an error message as well as an exit code because the |
|
| 94 |
- // error message is going to be "exit status <code> which is not useful |
|
| 95 |
- case exp.Error == "" && exp.ExitCode != 0: |
|
| 96 |
- case exp.Error == "" && r.Error != nil: |
|
| 97 |
- add("Expected no error")
|
|
| 98 |
- case exp.Error != "" && r.Error == nil: |
|
| 99 |
- add("Expected error to contain %q, but there was no error", exp.Error)
|
|
| 100 |
- case exp.Error != "" && !strings.Contains(r.Error.Error(), exp.Error): |
|
| 101 |
- add("Expected error to contain %q", exp.Error)
|
|
| 102 |
- } |
|
| 103 |
- |
|
| 104 |
- if len(errors) == 0 {
|
|
| 105 |
- return nil |
|
| 106 |
- } |
|
| 107 |
- return fmt.Errorf("%s\nFailures:\n%s\n", r, strings.Join(errors, "\n"))
|
|
| 108 |
-} |
|
| 109 |
- |
|
| 110 |
-func matchOutput(expected string, actual string) bool {
|
|
| 111 |
- switch expected {
|
|
| 112 |
- case None: |
|
| 113 |
- return actual == "" |
|
| 114 |
- default: |
|
| 115 |
- return strings.Contains(actual, expected) |
|
| 116 |
- } |
|
| 117 |
-} |
|
| 118 |
- |
|
| 119 |
-func (r *Result) String() string {
|
|
| 120 |
- var timeout string |
|
| 121 |
- if r.Timeout {
|
|
| 122 |
- timeout = " (timeout)" |
|
| 123 |
- } |
|
| 124 |
- |
|
| 125 |
- return fmt.Sprintf(` |
|
| 126 |
-Command: %s |
|
| 127 |
-ExitCode: %d%s, Error: %s |
|
| 128 |
-Stdout: %v |
|
| 129 |
-Stderr: %v |
|
| 130 |
-`, |
|
| 131 |
- strings.Join(r.Cmd.Args, " "), |
|
| 132 |
- r.ExitCode, |
|
| 133 |
- timeout, |
|
| 134 |
- r.Error, |
|
| 135 |
- r.Stdout(), |
|
| 136 |
- r.Stderr()) |
|
| 137 |
-} |
|
| 138 |
- |
|
| 139 |
-// Expected is the expected output from a Command. This struct is compared to a |
|
| 140 |
-// Result struct by Result.Assert(). |
|
| 141 |
-type Expected struct {
|
|
| 142 |
- ExitCode int |
|
| 143 |
- Timeout bool |
|
| 144 |
- Error string |
|
| 145 |
- Out string |
|
| 146 |
- Err string |
|
| 147 |
-} |
|
| 148 |
- |
|
| 149 |
-// Success is the default expected result |
|
| 150 |
-var Success = Expected{}
|
|
| 151 |
- |
|
| 152 |
-// Stdout returns the stdout of the process as a string |
|
| 153 |
-func (r *Result) Stdout() string {
|
|
| 154 |
- return r.outBuffer.String() |
|
| 155 |
-} |
|
| 156 |
- |
|
| 157 |
-// Stderr returns the stderr of the process as a string |
|
| 158 |
-func (r *Result) Stderr() string {
|
|
| 159 |
- return r.errBuffer.String() |
|
| 160 |
-} |
|
| 161 |
- |
|
| 162 |
-// Combined returns the stdout and stderr combined into a single string |
|
| 163 |
-func (r *Result) Combined() string {
|
|
| 164 |
- return r.outBuffer.String() + r.errBuffer.String() |
|
| 165 |
-} |
|
| 166 |
- |
|
| 167 |
-// SetExitError sets Error and ExitCode based on Error |
|
| 168 |
-func (r *Result) SetExitError(err error) {
|
|
| 169 |
- if err == nil {
|
|
| 170 |
- return |
|
| 171 |
- } |
|
| 172 |
- r.Error = err |
|
| 173 |
- r.ExitCode = system.ProcessExitCode(err) |
|
| 174 |
-} |
|
| 175 |
- |
|
| 176 |
-type matches struct{}
|
|
| 177 |
- |
|
| 178 |
-// Info returns the CheckerInfo |
|
| 179 |
-func (m *matches) Info() *check.CheckerInfo {
|
|
| 180 |
- return &check.CheckerInfo{
|
|
| 181 |
- Name: "CommandMatches", |
|
| 182 |
- Params: []string{"result", "expected"},
|
|
| 183 |
- } |
|
| 184 |
-} |
|
| 185 |
- |
|
| 186 |
-// Check compares a result against the expected |
|
| 187 |
-func (m *matches) Check(params []interface{}, names []string) (bool, string) {
|
|
| 188 |
- result, ok := params[0].(*Result) |
|
| 189 |
- if !ok {
|
|
| 190 |
- return false, fmt.Sprintf("result must be a *Result, not %T", params[0])
|
|
| 191 |
- } |
|
| 192 |
- expected, ok := params[1].(Expected) |
|
| 193 |
- if !ok {
|
|
| 194 |
- return false, fmt.Sprintf("expected must be an Expected, not %T", params[1])
|
|
| 195 |
- } |
|
| 196 |
- |
|
| 197 |
- err := result.Compare(expected) |
|
| 198 |
- if err == nil {
|
|
| 199 |
- return true, "" |
|
| 200 |
- } |
|
| 201 |
- return false, err.Error() |
|
| 202 |
-} |
|
| 203 |
- |
|
| 204 |
-// Matches is a gocheck.Checker for comparing a Result against an Expected |
|
| 205 |
-var Matches = &matches{}
|
|
| 206 |
- |
|
| 207 |
-// Cmd contains the arguments and options for a process to run as part of a test |
|
| 208 |
-// suite. |
|
| 209 |
-type Cmd struct {
|
|
| 210 |
- Command []string |
|
| 211 |
- Timeout time.Duration |
|
| 212 |
- Stdin io.Reader |
|
| 213 |
- Stdout io.Writer |
|
| 214 |
- Dir string |
|
| 215 |
- Env []string |
|
| 216 |
-} |
|
| 217 |
- |
|
| 218 |
-// RunCmd runs a command and returns a Result |
|
| 219 |
-func RunCmd(cmd Cmd) *Result {
|
|
| 220 |
- result := StartCmd(cmd) |
|
| 221 |
- if result.Error != nil {
|
|
| 222 |
- return result |
|
| 223 |
- } |
|
| 224 |
- return WaitOnCmd(cmd.Timeout, result) |
|
| 225 |
-} |
|
| 226 |
- |
|
| 227 |
-// RunCommand parses a command line and runs it, returning a result |
|
| 228 |
-func RunCommand(command string, args ...string) *Result {
|
|
| 229 |
- return RunCmd(Cmd{Command: append([]string{command}, args...)})
|
|
| 230 |
-} |
|
| 231 |
- |
|
| 232 |
-// StartCmd starts a command, but doesn't wait for it to finish |
|
| 233 |
-func StartCmd(cmd Cmd) *Result {
|
|
| 234 |
- result := buildCmd(cmd) |
|
| 235 |
- if result.Error != nil {
|
|
| 236 |
- return result |
|
| 237 |
- } |
|
| 238 |
- result.SetExitError(result.Cmd.Start()) |
|
| 239 |
- return result |
|
| 240 |
-} |
|
| 241 |
- |
|
| 242 |
-func buildCmd(cmd Cmd) *Result {
|
|
| 243 |
- var execCmd *exec.Cmd |
|
| 244 |
- switch len(cmd.Command) {
|
|
| 245 |
- case 1: |
|
| 246 |
- execCmd = exec.Command(cmd.Command[0]) |
|
| 247 |
- default: |
|
| 248 |
- execCmd = exec.Command(cmd.Command[0], cmd.Command[1:]...) |
|
| 249 |
- } |
|
| 250 |
- outBuffer := new(lockedBuffer) |
|
| 251 |
- errBuffer := new(lockedBuffer) |
|
| 252 |
- |
|
| 253 |
- execCmd.Stdin = cmd.Stdin |
|
| 254 |
- execCmd.Dir = cmd.Dir |
|
| 255 |
- execCmd.Env = cmd.Env |
|
| 256 |
- if cmd.Stdout != nil {
|
|
| 257 |
- execCmd.Stdout = io.MultiWriter(outBuffer, cmd.Stdout) |
|
| 258 |
- } else {
|
|
| 259 |
- execCmd.Stdout = outBuffer |
|
| 260 |
- } |
|
| 261 |
- execCmd.Stderr = errBuffer |
|
| 262 |
- return &Result{
|
|
| 263 |
- Cmd: execCmd, |
|
| 264 |
- outBuffer: outBuffer, |
|
| 265 |
- errBuffer: errBuffer, |
|
| 266 |
- } |
|
| 267 |
-} |
|
| 268 |
- |
|
| 269 |
-// WaitOnCmd waits for a command to complete. If timeout is non-nil then |
|
| 270 |
-// only wait until the timeout. |
|
| 271 |
-func WaitOnCmd(timeout time.Duration, result *Result) *Result {
|
|
| 272 |
- if timeout == time.Duration(0) {
|
|
| 273 |
- result.SetExitError(result.Cmd.Wait()) |
|
| 274 |
- return result |
|
| 275 |
- } |
|
| 276 |
- |
|
| 277 |
- done := make(chan error, 1) |
|
| 278 |
- // Wait for command to exit in a goroutine |
|
| 279 |
- go func() {
|
|
| 280 |
- done <- result.Cmd.Wait() |
|
| 281 |
- }() |
|
| 282 |
- |
|
| 283 |
- select {
|
|
| 284 |
- case <-time.After(timeout): |
|
| 285 |
- killErr := result.Cmd.Process.Kill() |
|
| 286 |
- if killErr != nil {
|
|
| 287 |
- fmt.Printf("failed to kill (pid=%d): %v\n", result.Cmd.Process.Pid, killErr)
|
|
| 288 |
- } |
|
| 289 |
- result.Timeout = true |
|
| 290 |
- case err := <-done: |
|
| 291 |
- result.SetExitError(err) |
|
| 292 |
- } |
|
| 293 |
- return result |
|
| 294 |
-} |
| 295 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,118 +0,0 @@ |
| 1 |
-package cmd |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "runtime" |
|
| 5 |
- "strings" |
|
| 6 |
- "testing" |
|
| 7 |
- "time" |
|
| 8 |
- |
|
| 9 |
- "github.com/docker/docker/pkg/testutil/assert" |
|
| 10 |
-) |
|
| 11 |
- |
|
| 12 |
-func TestRunCommand(t *testing.T) {
|
|
| 13 |
- // TODO Windows: Port this test |
|
| 14 |
- if runtime.GOOS == "windows" {
|
|
| 15 |
- t.Skip("Needs porting to Windows")
|
|
| 16 |
- } |
|
| 17 |
- |
|
| 18 |
- var cmd string |
|
| 19 |
- if runtime.GOOS == "solaris" {
|
|
| 20 |
- cmd = "gls" |
|
| 21 |
- } else {
|
|
| 22 |
- cmd = "ls" |
|
| 23 |
- } |
|
| 24 |
- result := RunCommand(cmd) |
|
| 25 |
- result.Assert(t, Expected{})
|
|
| 26 |
- |
|
| 27 |
- result = RunCommand("doesnotexists")
|
|
| 28 |
- expectedError := `exec: "doesnotexists": executable file not found` |
|
| 29 |
- result.Assert(t, Expected{ExitCode: 127, Error: expectedError})
|
|
| 30 |
- |
|
| 31 |
- result = RunCommand(cmd, "-z") |
|
| 32 |
- result.Assert(t, Expected{
|
|
| 33 |
- ExitCode: 2, |
|
| 34 |
- Error: "exit status 2", |
|
| 35 |
- Err: "invalid option", |
|
| 36 |
- }) |
|
| 37 |
- assert.Contains(t, result.Combined(), "invalid option") |
|
| 38 |
-} |
|
| 39 |
- |
|
| 40 |
-func TestRunCommandWithCombined(t *testing.T) {
|
|
| 41 |
- // TODO Windows: Port this test |
|
| 42 |
- if runtime.GOOS == "windows" {
|
|
| 43 |
- t.Skip("Needs porting to Windows")
|
|
| 44 |
- } |
|
| 45 |
- |
|
| 46 |
- result := RunCommand("ls", "-a")
|
|
| 47 |
- result.Assert(t, Expected{})
|
|
| 48 |
- |
|
| 49 |
- assert.Contains(t, result.Combined(), "..") |
|
| 50 |
- assert.Contains(t, result.Stdout(), "..") |
|
| 51 |
-} |
|
| 52 |
- |
|
| 53 |
-func TestRunCommandWithTimeoutFinished(t *testing.T) {
|
|
| 54 |
- // TODO Windows: Port this test |
|
| 55 |
- if runtime.GOOS == "windows" {
|
|
| 56 |
- t.Skip("Needs porting to Windows")
|
|
| 57 |
- } |
|
| 58 |
- |
|
| 59 |
- result := RunCmd(Cmd{
|
|
| 60 |
- Command: []string{"ls", "-a"},
|
|
| 61 |
- Timeout: 50 * time.Millisecond, |
|
| 62 |
- }) |
|
| 63 |
- result.Assert(t, Expected{Out: ".."})
|
|
| 64 |
-} |
|
| 65 |
- |
|
| 66 |
-func TestRunCommandWithTimeoutKilled(t *testing.T) {
|
|
| 67 |
- // TODO Windows: Port this test |
|
| 68 |
- if runtime.GOOS == "windows" {
|
|
| 69 |
- t.Skip("Needs porting to Windows")
|
|
| 70 |
- } |
|
| 71 |
- |
|
| 72 |
- command := []string{"sh", "-c", "while true ; do echo 1 ; sleep .5 ; done"}
|
|
| 73 |
- result := RunCmd(Cmd{Command: command, Timeout: 1250 * time.Millisecond})
|
|
| 74 |
- result.Assert(t, Expected{Timeout: true})
|
|
| 75 |
- |
|
| 76 |
- ones := strings.Split(result.Stdout(), "\n") |
|
| 77 |
- assert.Equal(t, len(ones), 4) |
|
| 78 |
-} |
|
| 79 |
- |
|
| 80 |
-func TestRunCommandWithErrors(t *testing.T) {
|
|
| 81 |
- result := RunCommand("/foobar")
|
|
| 82 |
- result.Assert(t, Expected{Error: "foobar", ExitCode: 127})
|
|
| 83 |
-} |
|
| 84 |
- |
|
| 85 |
-func TestRunCommandWithStdoutStderr(t *testing.T) {
|
|
| 86 |
- result := RunCommand("echo", "hello", "world")
|
|
| 87 |
- result.Assert(t, Expected{Out: "hello world\n", Err: None})
|
|
| 88 |
-} |
|
| 89 |
- |
|
| 90 |
-func TestRunCommandWithStdoutStderrError(t *testing.T) {
|
|
| 91 |
- result := RunCommand("doesnotexists")
|
|
| 92 |
- |
|
| 93 |
- expected := `exec: "doesnotexists": executable file not found` |
|
| 94 |
- result.Assert(t, Expected{Out: None, Err: None, ExitCode: 127, Error: expected})
|
|
| 95 |
- |
|
| 96 |
- switch runtime.GOOS {
|
|
| 97 |
- case "windows": |
|
| 98 |
- expected = "ls: unknown option" |
|
| 99 |
- case "solaris": |
|
| 100 |
- expected = "gls: invalid option" |
|
| 101 |
- default: |
|
| 102 |
- expected = "ls: invalid option" |
|
| 103 |
- } |
|
| 104 |
- |
|
| 105 |
- var cmd string |
|
| 106 |
- if runtime.GOOS == "solaris" {
|
|
| 107 |
- cmd = "gls" |
|
| 108 |
- } else {
|
|
| 109 |
- cmd = "ls" |
|
| 110 |
- } |
|
| 111 |
- result = RunCommand(cmd, "-z") |
|
| 112 |
- result.Assert(t, Expected{
|
|
| 113 |
- Out: None, |
|
| 114 |
- Err: expected, |
|
| 115 |
- ExitCode: 2, |
|
| 116 |
- Error: "exit status 2", |
|
| 117 |
- }) |
|
| 118 |
-} |
| 119 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,234 +0,0 @@ |
| 1 |
-package integration |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "archive/tar" |
|
| 5 |
- "errors" |
|
| 6 |
- "fmt" |
|
| 7 |
- "io" |
|
| 8 |
- "io/ioutil" |
|
| 9 |
- "os" |
|
| 10 |
- "os/exec" |
|
| 11 |
- "path/filepath" |
|
| 12 |
- "reflect" |
|
| 13 |
- "strings" |
|
| 14 |
- "syscall" |
|
| 15 |
- "time" |
|
| 16 |
- |
|
| 17 |
- icmd "github.com/docker/docker/pkg/integration/cmd" |
|
| 18 |
- "github.com/docker/docker/pkg/stringutils" |
|
| 19 |
- "github.com/docker/docker/pkg/system" |
|
| 20 |
-) |
|
| 21 |
- |
|
| 22 |
-// IsKilled process the specified error and returns whether the process was killed or not. |
|
| 23 |
-func IsKilled(err error) bool {
|
|
| 24 |
- if exitErr, ok := err.(*exec.ExitError); ok {
|
|
| 25 |
- status, ok := exitErr.Sys().(syscall.WaitStatus) |
|
| 26 |
- if !ok {
|
|
| 27 |
- return false |
|
| 28 |
- } |
|
| 29 |
- // status.ExitStatus() is required on Windows because it does not |
|
| 30 |
- // implement Signal() nor Signaled(). Just check it had a bad exit |
|
| 31 |
- // status could mean it was killed (and in tests we do kill) |
|
| 32 |
- return (status.Signaled() && status.Signal() == os.Kill) || status.ExitStatus() != 0 |
|
| 33 |
- } |
|
| 34 |
- return false |
|
| 35 |
-} |
|
| 36 |
- |
|
| 37 |
-func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) {
|
|
| 38 |
- exitCode = 0 |
|
| 39 |
- out, err := cmd.CombinedOutput() |
|
| 40 |
- exitCode = system.ProcessExitCode(err) |
|
| 41 |
- output = string(out) |
|
| 42 |
- return |
|
| 43 |
-} |
|
| 44 |
- |
|
| 45 |
-// RunCommandPipelineWithOutput runs the array of commands with the output |
|
| 46 |
-// of each pipelined with the following (like cmd1 | cmd2 | cmd3 would do). |
|
| 47 |
-// It returns the final output, the exitCode different from 0 and the error |
|
| 48 |
-// if something bad happened. |
|
| 49 |
-func RunCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, exitCode int, err error) {
|
|
| 50 |
- if len(cmds) < 2 {
|
|
| 51 |
- return "", 0, errors.New("pipeline does not have multiple cmds")
|
|
| 52 |
- } |
|
| 53 |
- |
|
| 54 |
- // connect stdin of each cmd to stdout pipe of previous cmd |
|
| 55 |
- for i, cmd := range cmds {
|
|
| 56 |
- if i > 0 {
|
|
| 57 |
- prevCmd := cmds[i-1] |
|
| 58 |
- cmd.Stdin, err = prevCmd.StdoutPipe() |
|
| 59 |
- |
|
| 60 |
- if err != nil {
|
|
| 61 |
- return "", 0, fmt.Errorf("cannot set stdout pipe for %s: %v", cmd.Path, err)
|
|
| 62 |
- } |
|
| 63 |
- } |
|
| 64 |
- } |
|
| 65 |
- |
|
| 66 |
- // start all cmds except the last |
|
| 67 |
- for _, cmd := range cmds[:len(cmds)-1] {
|
|
| 68 |
- if err = cmd.Start(); err != nil {
|
|
| 69 |
- return "", 0, fmt.Errorf("starting %s failed with error: %v", cmd.Path, err)
|
|
| 70 |
- } |
|
| 71 |
- } |
|
| 72 |
- |
|
| 73 |
- defer func() {
|
|
| 74 |
- var pipeErrMsgs []string |
|
| 75 |
- // wait all cmds except the last to release their resources |
|
| 76 |
- for _, cmd := range cmds[:len(cmds)-1] {
|
|
| 77 |
- if pipeErr := cmd.Wait(); pipeErr != nil {
|
|
| 78 |
- pipeErrMsgs = append(pipeErrMsgs, fmt.Sprintf("command %s failed with error: %v", cmd.Path, pipeErr))
|
|
| 79 |
- } |
|
| 80 |
- } |
|
| 81 |
- if len(pipeErrMsgs) > 0 && err == nil {
|
|
| 82 |
- err = fmt.Errorf("pipelineError from Wait: %v", strings.Join(pipeErrMsgs, ", "))
|
|
| 83 |
- } |
|
| 84 |
- }() |
|
| 85 |
- |
|
| 86 |
- // wait on last cmd |
|
| 87 |
- return runCommandWithOutput(cmds[len(cmds)-1]) |
|
| 88 |
-} |
|
| 89 |
- |
|
| 90 |
-// ConvertSliceOfStringsToMap converts a slices of string in a map |
|
| 91 |
-// with the strings as key and an empty string as values. |
|
| 92 |
-func ConvertSliceOfStringsToMap(input []string) map[string]struct{} {
|
|
| 93 |
- output := make(map[string]struct{})
|
|
| 94 |
- for _, v := range input {
|
|
| 95 |
- output[v] = struct{}{}
|
|
| 96 |
- } |
|
| 97 |
- return output |
|
| 98 |
-} |
|
| 99 |
- |
|
| 100 |
-// CompareDirectoryEntries compares two sets of FileInfo (usually taken from a directory) |
|
| 101 |
-// and returns an error if different. |
|
| 102 |
-func CompareDirectoryEntries(e1 []os.FileInfo, e2 []os.FileInfo) error {
|
|
| 103 |
- var ( |
|
| 104 |
- e1Entries = make(map[string]struct{})
|
|
| 105 |
- e2Entries = make(map[string]struct{})
|
|
| 106 |
- ) |
|
| 107 |
- for _, e := range e1 {
|
|
| 108 |
- e1Entries[e.Name()] = struct{}{}
|
|
| 109 |
- } |
|
| 110 |
- for _, e := range e2 {
|
|
| 111 |
- e2Entries[e.Name()] = struct{}{}
|
|
| 112 |
- } |
|
| 113 |
- if !reflect.DeepEqual(e1Entries, e2Entries) {
|
|
| 114 |
- return fmt.Errorf("entries differ")
|
|
| 115 |
- } |
|
| 116 |
- return nil |
|
| 117 |
-} |
|
| 118 |
- |
|
| 119 |
-// ListTar lists the entries of a tar. |
|
| 120 |
-func ListTar(f io.Reader) ([]string, error) {
|
|
| 121 |
- tr := tar.NewReader(f) |
|
| 122 |
- var entries []string |
|
| 123 |
- |
|
| 124 |
- for {
|
|
| 125 |
- th, err := tr.Next() |
|
| 126 |
- if err == io.EOF {
|
|
| 127 |
- // end of tar archive |
|
| 128 |
- return entries, nil |
|
| 129 |
- } |
|
| 130 |
- if err != nil {
|
|
| 131 |
- return entries, err |
|
| 132 |
- } |
|
| 133 |
- entries = append(entries, th.Name) |
|
| 134 |
- } |
|
| 135 |
-} |
|
| 136 |
- |
|
| 137 |
-// RandomTmpDirPath provides a temporary path with rand string appended. |
|
| 138 |
-// does not create or checks if it exists. |
|
| 139 |
-func RandomTmpDirPath(s string, platform string) string {
|
|
| 140 |
- tmp := "/tmp" |
|
| 141 |
- if platform == "windows" {
|
|
| 142 |
- tmp = os.Getenv("TEMP")
|
|
| 143 |
- } |
|
| 144 |
- path := filepath.Join(tmp, fmt.Sprintf("%s.%s", s, stringutils.GenerateRandomAlphaOnlyString(10)))
|
|
| 145 |
- if platform == "windows" {
|
|
| 146 |
- return filepath.FromSlash(path) // Using \ |
|
| 147 |
- } |
|
| 148 |
- return filepath.ToSlash(path) // Using / |
|
| 149 |
-} |
|
| 150 |
- |
|
| 151 |
-// ConsumeWithSpeed reads chunkSize bytes from reader before sleeping |
|
| 152 |
-// for interval duration. Returns total read bytes. Send true to the |
|
| 153 |
-// stop channel to return before reading to EOF on the reader. |
|
| 154 |
-func ConsumeWithSpeed(reader io.Reader, chunkSize int, interval time.Duration, stop chan bool) (n int, err error) {
|
|
| 155 |
- buffer := make([]byte, chunkSize) |
|
| 156 |
- for {
|
|
| 157 |
- var readBytes int |
|
| 158 |
- readBytes, err = reader.Read(buffer) |
|
| 159 |
- n += readBytes |
|
| 160 |
- if err != nil {
|
|
| 161 |
- if err == io.EOF {
|
|
| 162 |
- err = nil |
|
| 163 |
- } |
|
| 164 |
- return |
|
| 165 |
- } |
|
| 166 |
- select {
|
|
| 167 |
- case <-stop: |
|
| 168 |
- return |
|
| 169 |
- case <-time.After(interval): |
|
| 170 |
- } |
|
| 171 |
- } |
|
| 172 |
-} |
|
| 173 |
- |
|
| 174 |
-// ParseCgroupPaths parses 'procCgroupData', which is output of '/proc/<pid>/cgroup', and returns |
|
| 175 |
-// a map which cgroup name as key and path as value. |
|
| 176 |
-func ParseCgroupPaths(procCgroupData string) map[string]string {
|
|
| 177 |
- cgroupPaths := map[string]string{}
|
|
| 178 |
- for _, line := range strings.Split(procCgroupData, "\n") {
|
|
| 179 |
- parts := strings.Split(line, ":") |
|
| 180 |
- if len(parts) != 3 {
|
|
| 181 |
- continue |
|
| 182 |
- } |
|
| 183 |
- cgroupPaths[parts[1]] = parts[2] |
|
| 184 |
- } |
|
| 185 |
- return cgroupPaths |
|
| 186 |
-} |
|
| 187 |
- |
|
| 188 |
-// ChannelBuffer holds a chan of byte array that can be populate in a goroutine. |
|
| 189 |
-type ChannelBuffer struct {
|
|
| 190 |
- C chan []byte |
|
| 191 |
-} |
|
| 192 |
- |
|
| 193 |
-// Write implements Writer. |
|
| 194 |
-func (c *ChannelBuffer) Write(b []byte) (int, error) {
|
|
| 195 |
- c.C <- b |
|
| 196 |
- return len(b), nil |
|
| 197 |
-} |
|
| 198 |
- |
|
| 199 |
-// Close closes the go channel. |
|
| 200 |
-func (c *ChannelBuffer) Close() error {
|
|
| 201 |
- close(c.C) |
|
| 202 |
- return nil |
|
| 203 |
-} |
|
| 204 |
- |
|
| 205 |
-// ReadTimeout reads the content of the channel in the specified byte array with |
|
| 206 |
-// the specified duration as timeout. |
|
| 207 |
-func (c *ChannelBuffer) ReadTimeout(p []byte, n time.Duration) (int, error) {
|
|
| 208 |
- select {
|
|
| 209 |
- case b := <-c.C: |
|
| 210 |
- return copy(p[0:], b), nil |
|
| 211 |
- case <-time.After(n): |
|
| 212 |
- return -1, fmt.Errorf("timeout reading from channel")
|
|
| 213 |
- } |
|
| 214 |
-} |
|
| 215 |
- |
|
| 216 |
-// RunAtDifferentDate runs the specified function with the given time. |
|
| 217 |
-// It changes the date of the system, which can led to weird behaviors. |
|
| 218 |
-func RunAtDifferentDate(date time.Time, block func()) {
|
|
| 219 |
- // Layout for date. MMDDhhmmYYYY |
|
| 220 |
- const timeLayout = "010203042006" |
|
| 221 |
- // Ensure we bring time back to now |
|
| 222 |
- now := time.Now().Format(timeLayout) |
|
| 223 |
- defer icmd.RunCommand("date", now)
|
|
| 224 |
- |
|
| 225 |
- icmd.RunCommand("date", date.Format(timeLayout))
|
|
| 226 |
- block() |
|
| 227 |
- return |
|
| 228 |
-} |
|
| 229 |
- |
|
| 230 |
-// ReadBody read the specified ReadCloser content and returns it |
|
| 231 |
-func ReadBody(b io.ReadCloser) ([]byte, error) {
|
|
| 232 |
- defer b.Close() |
|
| 233 |
- return ioutil.ReadAll(b) |
|
| 234 |
-} |
| 235 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,363 +0,0 @@ |
| 1 |
-package integration |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "io" |
|
| 5 |
- "io/ioutil" |
|
| 6 |
- "os" |
|
| 7 |
- "os/exec" |
|
| 8 |
- "path/filepath" |
|
| 9 |
- "runtime" |
|
| 10 |
- "strings" |
|
| 11 |
- "testing" |
|
| 12 |
- "time" |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-func TestIsKilledFalseWithNonKilledProcess(t *testing.T) {
|
|
| 16 |
- var lsCmd *exec.Cmd |
|
| 17 |
- if runtime.GOOS != "windows" {
|
|
| 18 |
- lsCmd = exec.Command("ls")
|
|
| 19 |
- } else {
|
|
| 20 |
- lsCmd = exec.Command("cmd", "/c", "dir")
|
|
| 21 |
- } |
|
| 22 |
- |
|
| 23 |
- err := lsCmd.Run() |
|
| 24 |
- if IsKilled(err) {
|
|
| 25 |
- t.Fatalf("Expected the ls command to not be killed, was.")
|
|
| 26 |
- } |
|
| 27 |
-} |
|
| 28 |
- |
|
| 29 |
-func TestIsKilledTrueWithKilledProcess(t *testing.T) {
|
|
| 30 |
- var longCmd *exec.Cmd |
|
| 31 |
- if runtime.GOOS != "windows" {
|
|
| 32 |
- longCmd = exec.Command("top")
|
|
| 33 |
- } else {
|
|
| 34 |
- longCmd = exec.Command("powershell", "while ($true) { sleep 1 }")
|
|
| 35 |
- } |
|
| 36 |
- |
|
| 37 |
- // Start a command |
|
| 38 |
- err := longCmd.Start() |
|
| 39 |
- if err != nil {
|
|
| 40 |
- t.Fatal(err) |
|
| 41 |
- } |
|
| 42 |
- // Capture the error when *dying* |
|
| 43 |
- done := make(chan error, 1) |
|
| 44 |
- go func() {
|
|
| 45 |
- done <- longCmd.Wait() |
|
| 46 |
- }() |
|
| 47 |
- // Then kill it |
|
| 48 |
- longCmd.Process.Kill() |
|
| 49 |
- // Get the error |
|
| 50 |
- err = <-done |
|
| 51 |
- if !IsKilled(err) {
|
|
| 52 |
- t.Fatalf("Expected the command to be killed, was not.")
|
|
| 53 |
- } |
|
| 54 |
-} |
|
| 55 |
- |
|
| 56 |
-func TestRunCommandPipelineWithOutputWithNotEnoughCmds(t *testing.T) {
|
|
| 57 |
- _, _, err := RunCommandPipelineWithOutput(exec.Command("ls"))
|
|
| 58 |
- expectedError := "pipeline does not have multiple cmds" |
|
| 59 |
- if err == nil || err.Error() != expectedError {
|
|
| 60 |
- t.Fatalf("Expected an error with %s, got err:%s", expectedError, err)
|
|
| 61 |
- } |
|
| 62 |
-} |
|
| 63 |
- |
|
| 64 |
-func TestRunCommandPipelineWithOutputErrors(t *testing.T) {
|
|
| 65 |
- p := "$PATH" |
|
| 66 |
- if runtime.GOOS == "windows" {
|
|
| 67 |
- p = "%PATH%" |
|
| 68 |
- } |
|
| 69 |
- cmd1 := exec.Command("ls")
|
|
| 70 |
- cmd1.Stdout = os.Stdout |
|
| 71 |
- cmd2 := exec.Command("anything really")
|
|
| 72 |
- _, _, err := RunCommandPipelineWithOutput(cmd1, cmd2) |
|
| 73 |
- if err == nil || err.Error() != "cannot set stdout pipe for anything really: exec: Stdout already set" {
|
|
| 74 |
- t.Fatalf("Expected an error, got %v", err)
|
|
| 75 |
- } |
|
| 76 |
- |
|
| 77 |
- cmdWithError := exec.Command("doesnotexists")
|
|
| 78 |
- cmdCat := exec.Command("cat")
|
|
| 79 |
- _, _, err = RunCommandPipelineWithOutput(cmdWithError, cmdCat) |
|
| 80 |
- if err == nil || err.Error() != `starting doesnotexists failed with error: exec: "doesnotexists": executable file not found in `+p {
|
|
| 81 |
- t.Fatalf("Expected an error, got %v", err)
|
|
| 82 |
- } |
|
| 83 |
-} |
|
| 84 |
- |
|
| 85 |
-func TestRunCommandPipelineWithOutput(t *testing.T) {
|
|
| 86 |
- //TODO: Should run on Solaris |
|
| 87 |
- if runtime.GOOS == "solaris" {
|
|
| 88 |
- t.Skip() |
|
| 89 |
- } |
|
| 90 |
- cmds := []*exec.Cmd{
|
|
| 91 |
- // Print 2 characters |
|
| 92 |
- exec.Command("echo", "-n", "11"),
|
|
| 93 |
- // Count the number or char from stdin (previous command) |
|
| 94 |
- exec.Command("wc", "-m"),
|
|
| 95 |
- } |
|
| 96 |
- out, exitCode, err := RunCommandPipelineWithOutput(cmds...) |
|
| 97 |
- expectedOutput := "2\n" |
|
| 98 |
- if out != expectedOutput || exitCode != 0 || err != nil {
|
|
| 99 |
- t.Fatalf("Expected %s for commands %v, got out:%s, exitCode:%d, err:%v", expectedOutput, cmds, out, exitCode, err)
|
|
| 100 |
- } |
|
| 101 |
-} |
|
| 102 |
- |
|
| 103 |
-func TestConvertSliceOfStringsToMap(t *testing.T) {
|
|
| 104 |
- input := []string{"a", "b"}
|
|
| 105 |
- actual := ConvertSliceOfStringsToMap(input) |
|
| 106 |
- for _, key := range input {
|
|
| 107 |
- if _, ok := actual[key]; !ok {
|
|
| 108 |
- t.Fatalf("Expected output to contains key %s, did not: %v", key, actual)
|
|
| 109 |
- } |
|
| 110 |
- } |
|
| 111 |
-} |
|
| 112 |
- |
|
| 113 |
-func TestCompareDirectoryEntries(t *testing.T) {
|
|
| 114 |
- tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-compare-directories")
|
|
| 115 |
- if err != nil {
|
|
| 116 |
- t.Fatal(err) |
|
| 117 |
- } |
|
| 118 |
- defer os.RemoveAll(tmpFolder) |
|
| 119 |
- |
|
| 120 |
- file1 := filepath.Join(tmpFolder, "file1") |
|
| 121 |
- file2 := filepath.Join(tmpFolder, "file2") |
|
| 122 |
- os.Create(file1) |
|
| 123 |
- os.Create(file2) |
|
| 124 |
- |
|
| 125 |
- fi1, err := os.Stat(file1) |
|
| 126 |
- if err != nil {
|
|
| 127 |
- t.Fatal(err) |
|
| 128 |
- } |
|
| 129 |
- fi1bis, err := os.Stat(file1) |
|
| 130 |
- if err != nil {
|
|
| 131 |
- t.Fatal(err) |
|
| 132 |
- } |
|
| 133 |
- fi2, err := os.Stat(file2) |
|
| 134 |
- if err != nil {
|
|
| 135 |
- t.Fatal(err) |
|
| 136 |
- } |
|
| 137 |
- |
|
| 138 |
- cases := []struct {
|
|
| 139 |
- e1 []os.FileInfo |
|
| 140 |
- e2 []os.FileInfo |
|
| 141 |
- shouldError bool |
|
| 142 |
- }{
|
|
| 143 |
- // Empty directories |
|
| 144 |
- {
|
|
| 145 |
- []os.FileInfo{},
|
|
| 146 |
- []os.FileInfo{},
|
|
| 147 |
- false, |
|
| 148 |
- }, |
|
| 149 |
- // Same FileInfos |
|
| 150 |
- {
|
|
| 151 |
- []os.FileInfo{fi1},
|
|
| 152 |
- []os.FileInfo{fi1},
|
|
| 153 |
- false, |
|
| 154 |
- }, |
|
| 155 |
- // Different FileInfos but same names |
|
| 156 |
- {
|
|
| 157 |
- []os.FileInfo{fi1},
|
|
| 158 |
- []os.FileInfo{fi1bis},
|
|
| 159 |
- false, |
|
| 160 |
- }, |
|
| 161 |
- // Different FileInfos, different names |
|
| 162 |
- {
|
|
| 163 |
- []os.FileInfo{fi1},
|
|
| 164 |
- []os.FileInfo{fi2},
|
|
| 165 |
- true, |
|
| 166 |
- }, |
|
| 167 |
- } |
|
| 168 |
- for _, elt := range cases {
|
|
| 169 |
- err := CompareDirectoryEntries(elt.e1, elt.e2) |
|
| 170 |
- if elt.shouldError && err == nil {
|
|
| 171 |
- t.Fatalf("Should have return an error, did not with %v and %v", elt.e1, elt.e2)
|
|
| 172 |
- } |
|
| 173 |
- if !elt.shouldError && err != nil {
|
|
| 174 |
- t.Fatalf("Should have not returned an error, but did : %v with %v and %v", err, elt.e1, elt.e2)
|
|
| 175 |
- } |
|
| 176 |
- } |
|
| 177 |
-} |
|
| 178 |
- |
|
| 179 |
-// FIXME make an "unhappy path" test for ListTar without "panicking" :-) |
|
| 180 |
-func TestListTar(t *testing.T) {
|
|
| 181 |
- // TODO Windows: Figure out why this fails. Should be portable. |
|
| 182 |
- if runtime.GOOS == "windows" {
|
|
| 183 |
- t.Skip("Failing on Windows - needs further investigation")
|
|
| 184 |
- } |
|
| 185 |
- tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-list-tar")
|
|
| 186 |
- if err != nil {
|
|
| 187 |
- t.Fatal(err) |
|
| 188 |
- } |
|
| 189 |
- defer os.RemoveAll(tmpFolder) |
|
| 190 |
- |
|
| 191 |
- // Let's create a Tar file |
|
| 192 |
- srcFile := filepath.Join(tmpFolder, "src") |
|
| 193 |
- tarFile := filepath.Join(tmpFolder, "src.tar") |
|
| 194 |
- os.Create(srcFile) |
|
| 195 |
- cmd := exec.Command("sh", "-c", "tar cf "+tarFile+" "+srcFile)
|
|
| 196 |
- _, err = cmd.CombinedOutput() |
|
| 197 |
- if err != nil {
|
|
| 198 |
- t.Fatal(err) |
|
| 199 |
- } |
|
| 200 |
- |
|
| 201 |
- reader, err := os.Open(tarFile) |
|
| 202 |
- if err != nil {
|
|
| 203 |
- t.Fatal(err) |
|
| 204 |
- } |
|
| 205 |
- defer reader.Close() |
|
| 206 |
- |
|
| 207 |
- entries, err := ListTar(reader) |
|
| 208 |
- if err != nil {
|
|
| 209 |
- t.Fatal(err) |
|
| 210 |
- } |
|
| 211 |
- if len(entries) != 1 && entries[0] != "src" {
|
|
| 212 |
- t.Fatalf("Expected a tar file with 1 entry (%s), got %v", srcFile, entries)
|
|
| 213 |
- } |
|
| 214 |
-} |
|
| 215 |
- |
|
| 216 |
-func TestRandomTmpDirPath(t *testing.T) {
|
|
| 217 |
- path := RandomTmpDirPath("something", runtime.GOOS)
|
|
| 218 |
- |
|
| 219 |
- prefix := "/tmp/something" |
|
| 220 |
- if runtime.GOOS == "windows" {
|
|
| 221 |
- prefix = os.Getenv("TEMP") + `\something`
|
|
| 222 |
- } |
|
| 223 |
- expectedSize := len(prefix) + 11 |
|
| 224 |
- |
|
| 225 |
- if !strings.HasPrefix(path, prefix) {
|
|
| 226 |
- t.Fatalf("Expected generated path to have '%s' as prefix, got %s'", prefix, path)
|
|
| 227 |
- } |
|
| 228 |
- if len(path) != expectedSize {
|
|
| 229 |
- t.Fatalf("Expected generated path to be %d, got %d", expectedSize, len(path))
|
|
| 230 |
- } |
|
| 231 |
-} |
|
| 232 |
- |
|
| 233 |
-func TestConsumeWithSpeed(t *testing.T) {
|
|
| 234 |
- reader := strings.NewReader("1234567890")
|
|
| 235 |
- chunksize := 2 |
|
| 236 |
- |
|
| 237 |
- bytes1, err := ConsumeWithSpeed(reader, chunksize, 10*time.Millisecond, nil) |
|
| 238 |
- if err != nil {
|
|
| 239 |
- t.Fatal(err) |
|
| 240 |
- } |
|
| 241 |
- |
|
| 242 |
- if bytes1 != 10 {
|
|
| 243 |
- t.Fatalf("Expected to have read 10 bytes, got %d", bytes1)
|
|
| 244 |
- } |
|
| 245 |
- |
|
| 246 |
-} |
|
| 247 |
- |
|
| 248 |
-func TestConsumeWithSpeedWithStop(t *testing.T) {
|
|
| 249 |
- reader := strings.NewReader("1234567890")
|
|
| 250 |
- chunksize := 2 |
|
| 251 |
- |
|
| 252 |
- stopIt := make(chan bool) |
|
| 253 |
- |
|
| 254 |
- go func() {
|
|
| 255 |
- time.Sleep(1 * time.Millisecond) |
|
| 256 |
- stopIt <- true |
|
| 257 |
- }() |
|
| 258 |
- |
|
| 259 |
- bytes1, err := ConsumeWithSpeed(reader, chunksize, 20*time.Millisecond, stopIt) |
|
| 260 |
- if err != nil {
|
|
| 261 |
- t.Fatal(err) |
|
| 262 |
- } |
|
| 263 |
- |
|
| 264 |
- if bytes1 != 2 {
|
|
| 265 |
- t.Fatalf("Expected to have read 2 bytes, got %d", bytes1)
|
|
| 266 |
- } |
|
| 267 |
- |
|
| 268 |
-} |
|
| 269 |
- |
|
| 270 |
-func TestParseCgroupPathsEmpty(t *testing.T) {
|
|
| 271 |
- cgroupMap := ParseCgroupPaths("")
|
|
| 272 |
- if len(cgroupMap) != 0 {
|
|
| 273 |
- t.Fatalf("Expected an empty map, got %v", cgroupMap)
|
|
| 274 |
- } |
|
| 275 |
- cgroupMap = ParseCgroupPaths("\n")
|
|
| 276 |
- if len(cgroupMap) != 0 {
|
|
| 277 |
- t.Fatalf("Expected an empty map, got %v", cgroupMap)
|
|
| 278 |
- } |
|
| 279 |
- cgroupMap = ParseCgroupPaths("something:else\nagain:here")
|
|
| 280 |
- if len(cgroupMap) != 0 {
|
|
| 281 |
- t.Fatalf("Expected an empty map, got %v", cgroupMap)
|
|
| 282 |
- } |
|
| 283 |
-} |
|
| 284 |
- |
|
| 285 |
-func TestParseCgroupPaths(t *testing.T) {
|
|
| 286 |
- cgroupMap := ParseCgroupPaths("2:memory:/a\n1:cpuset:/b")
|
|
| 287 |
- if len(cgroupMap) != 2 {
|
|
| 288 |
- t.Fatalf("Expected a map with 2 entries, got %v", cgroupMap)
|
|
| 289 |
- } |
|
| 290 |
- if value, ok := cgroupMap["memory"]; !ok || value != "/a" {
|
|
| 291 |
- t.Fatalf("Expected cgroupMap to contains an entry for 'memory' with value '/a', got %v", cgroupMap)
|
|
| 292 |
- } |
|
| 293 |
- if value, ok := cgroupMap["cpuset"]; !ok || value != "/b" {
|
|
| 294 |
- t.Fatalf("Expected cgroupMap to contains an entry for 'cpuset' with value '/b', got %v", cgroupMap)
|
|
| 295 |
- } |
|
| 296 |
-} |
|
| 297 |
- |
|
| 298 |
-func TestChannelBufferTimeout(t *testing.T) {
|
|
| 299 |
- expected := "11" |
|
| 300 |
- |
|
| 301 |
- buf := &ChannelBuffer{make(chan []byte, 1)}
|
|
| 302 |
- defer buf.Close() |
|
| 303 |
- |
|
| 304 |
- done := make(chan struct{}, 1)
|
|
| 305 |
- go func() {
|
|
| 306 |
- time.Sleep(100 * time.Millisecond) |
|
| 307 |
- io.Copy(buf, strings.NewReader(expected)) |
|
| 308 |
- done <- struct{}{}
|
|
| 309 |
- }() |
|
| 310 |
- |
|
| 311 |
- // Wait long enough |
|
| 312 |
- b := make([]byte, 2) |
|
| 313 |
- _, err := buf.ReadTimeout(b, 50*time.Millisecond) |
|
| 314 |
- if err == nil && err.Error() != "timeout reading from channel" {
|
|
| 315 |
- t.Fatalf("Expected an error, got %s", err)
|
|
| 316 |
- } |
|
| 317 |
- <-done |
|
| 318 |
-} |
|
| 319 |
- |
|
| 320 |
-func TestChannelBuffer(t *testing.T) {
|
|
| 321 |
- expected := "11" |
|
| 322 |
- |
|
| 323 |
- buf := &ChannelBuffer{make(chan []byte, 1)}
|
|
| 324 |
- defer buf.Close() |
|
| 325 |
- |
|
| 326 |
- go func() {
|
|
| 327 |
- time.Sleep(100 * time.Millisecond) |
|
| 328 |
- io.Copy(buf, strings.NewReader(expected)) |
|
| 329 |
- }() |
|
| 330 |
- |
|
| 331 |
- // Wait long enough |
|
| 332 |
- b := make([]byte, 2) |
|
| 333 |
- _, err := buf.ReadTimeout(b, 200*time.Millisecond) |
|
| 334 |
- if err != nil {
|
|
| 335 |
- t.Fatal(err) |
|
| 336 |
- } |
|
| 337 |
- |
|
| 338 |
- if string(b) != expected {
|
|
| 339 |
- t.Fatalf("Expected '%s', got '%s'", expected, string(b))
|
|
| 340 |
- } |
|
| 341 |
-} |
|
| 342 |
- |
|
| 343 |
-// FIXME doesn't work |
|
| 344 |
-// func TestRunAtDifferentDate(t *testing.T) {
|
|
| 345 |
-// var date string |
|
| 346 |
- |
|
| 347 |
-// // Layout for date. MMDDhhmmYYYY |
|
| 348 |
-// const timeLayout = "20060102" |
|
| 349 |
-// expectedDate := "20100201" |
|
| 350 |
-// theDate, err := time.Parse(timeLayout, expectedDate) |
|
| 351 |
-// if err != nil {
|
|
| 352 |
-// t.Fatal(err) |
|
| 353 |
-// } |
|
| 354 |
- |
|
| 355 |
-// RunAtDifferentDate(theDate, func() {
|
|
| 356 |
-// cmd := exec.Command("date", "+%Y%M%d")
|
|
| 357 |
-// out, err := cmd.Output() |
|
| 358 |
-// if err != nil {
|
|
| 359 |
-// t.Fatal(err) |
|
| 360 |
-// } |
|
| 361 |
-// date = string(out) |
|
| 362 |
-// }) |
|
| 363 |
-// } |
| 364 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,294 @@ |
| 0 |
+package cmd |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "io" |
|
| 6 |
+ "os/exec" |
|
| 7 |
+ "path/filepath" |
|
| 8 |
+ "runtime" |
|
| 9 |
+ "strings" |
|
| 10 |
+ "sync" |
|
| 11 |
+ "time" |
|
| 12 |
+ |
|
| 13 |
+ "github.com/docker/docker/pkg/system" |
|
| 14 |
+ "github.com/go-check/check" |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+type testingT interface {
|
|
| 18 |
+ Fatalf(string, ...interface{})
|
|
| 19 |
+} |
|
| 20 |
+ |
|
| 21 |
+const ( |
|
| 22 |
+ // None is a token to inform Result.Assert that the output should be empty |
|
| 23 |
+ None string = "<NOTHING>" |
|
| 24 |
+) |
|
| 25 |
+ |
|
| 26 |
+type lockedBuffer struct {
|
|
| 27 |
+ m sync.RWMutex |
|
| 28 |
+ buf bytes.Buffer |
|
| 29 |
+} |
|
| 30 |
+ |
|
| 31 |
+func (buf *lockedBuffer) Write(b []byte) (int, error) {
|
|
| 32 |
+ buf.m.Lock() |
|
| 33 |
+ defer buf.m.Unlock() |
|
| 34 |
+ return buf.buf.Write(b) |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func (buf *lockedBuffer) String() string {
|
|
| 38 |
+ buf.m.RLock() |
|
| 39 |
+ defer buf.m.RUnlock() |
|
| 40 |
+ return buf.buf.String() |
|
| 41 |
+} |
|
| 42 |
+ |
|
| 43 |
+// Result stores the result of running a command |
|
| 44 |
+type Result struct {
|
|
| 45 |
+ Cmd *exec.Cmd |
|
| 46 |
+ ExitCode int |
|
| 47 |
+ Error error |
|
| 48 |
+ // Timeout is true if the command was killed because it ran for too long |
|
| 49 |
+ Timeout bool |
|
| 50 |
+ outBuffer *lockedBuffer |
|
| 51 |
+ errBuffer *lockedBuffer |
|
| 52 |
+} |
|
| 53 |
+ |
|
| 54 |
+// Assert compares the Result against the Expected struct, and fails the test if |
|
| 55 |
+// any of the expcetations are not met. |
|
| 56 |
+func (r *Result) Assert(t testingT, exp Expected) {
|
|
| 57 |
+ err := r.Compare(exp) |
|
| 58 |
+ if err == nil {
|
|
| 59 |
+ return |
|
| 60 |
+ } |
|
| 61 |
+ |
|
| 62 |
+ _, file, line, _ := runtime.Caller(1) |
|
| 63 |
+ t.Fatalf("at %s:%d\n%s", filepath.Base(file), line, err.Error())
|
|
| 64 |
+} |
|
| 65 |
+ |
|
| 66 |
+// Compare returns a formatted error with the command, stdout, stderr, exit |
|
| 67 |
+// code, and any failed expectations |
|
| 68 |
+func (r *Result) Compare(exp Expected) error {
|
|
| 69 |
+ errors := []string{}
|
|
| 70 |
+ add := func(format string, args ...interface{}) {
|
|
| 71 |
+ errors = append(errors, fmt.Sprintf(format, args...)) |
|
| 72 |
+ } |
|
| 73 |
+ |
|
| 74 |
+ if exp.ExitCode != r.ExitCode {
|
|
| 75 |
+ add("ExitCode was %d expected %d", r.ExitCode, exp.ExitCode)
|
|
| 76 |
+ } |
|
| 77 |
+ if exp.Timeout != r.Timeout {
|
|
| 78 |
+ if exp.Timeout {
|
|
| 79 |
+ add("Expected command to timeout")
|
|
| 80 |
+ } else {
|
|
| 81 |
+ add("Expected command to finish, but it hit the timeout")
|
|
| 82 |
+ } |
|
| 83 |
+ } |
|
| 84 |
+ if !matchOutput(exp.Out, r.Stdout()) {
|
|
| 85 |
+ add("Expected stdout to contain %q", exp.Out)
|
|
| 86 |
+ } |
|
| 87 |
+ if !matchOutput(exp.Err, r.Stderr()) {
|
|
| 88 |
+ add("Expected stderr to contain %q", exp.Err)
|
|
| 89 |
+ } |
|
| 90 |
+ switch {
|
|
| 91 |
+ // If a non-zero exit code is expected there is going to be an error. |
|
| 92 |
+ // Don't require an error message as well as an exit code because the |
|
| 93 |
+ // error message is going to be "exit status <code> which is not useful |
|
| 94 |
+ case exp.Error == "" && exp.ExitCode != 0: |
|
| 95 |
+ case exp.Error == "" && r.Error != nil: |
|
| 96 |
+ add("Expected no error")
|
|
| 97 |
+ case exp.Error != "" && r.Error == nil: |
|
| 98 |
+ add("Expected error to contain %q, but there was no error", exp.Error)
|
|
| 99 |
+ case exp.Error != "" && !strings.Contains(r.Error.Error(), exp.Error): |
|
| 100 |
+ add("Expected error to contain %q", exp.Error)
|
|
| 101 |
+ } |
|
| 102 |
+ |
|
| 103 |
+ if len(errors) == 0 {
|
|
| 104 |
+ return nil |
|
| 105 |
+ } |
|
| 106 |
+ return fmt.Errorf("%s\nFailures:\n%s\n", r, strings.Join(errors, "\n"))
|
|
| 107 |
+} |
|
| 108 |
+ |
|
| 109 |
+func matchOutput(expected string, actual string) bool {
|
|
| 110 |
+ switch expected {
|
|
| 111 |
+ case None: |
|
| 112 |
+ return actual == "" |
|
| 113 |
+ default: |
|
| 114 |
+ return strings.Contains(actual, expected) |
|
| 115 |
+ } |
|
| 116 |
+} |
|
| 117 |
+ |
|
| 118 |
+func (r *Result) String() string {
|
|
| 119 |
+ var timeout string |
|
| 120 |
+ if r.Timeout {
|
|
| 121 |
+ timeout = " (timeout)" |
|
| 122 |
+ } |
|
| 123 |
+ |
|
| 124 |
+ return fmt.Sprintf(` |
|
| 125 |
+Command: %s |
|
| 126 |
+ExitCode: %d%s, Error: %s |
|
| 127 |
+Stdout: %v |
|
| 128 |
+Stderr: %v |
|
| 129 |
+`, |
|
| 130 |
+ strings.Join(r.Cmd.Args, " "), |
|
| 131 |
+ r.ExitCode, |
|
| 132 |
+ timeout, |
|
| 133 |
+ r.Error, |
|
| 134 |
+ r.Stdout(), |
|
| 135 |
+ r.Stderr()) |
|
| 136 |
+} |
|
| 137 |
+ |
|
| 138 |
+// Expected is the expected output from a Command. This struct is compared to a |
|
| 139 |
+// Result struct by Result.Assert(). |
|
| 140 |
+type Expected struct {
|
|
| 141 |
+ ExitCode int |
|
| 142 |
+ Timeout bool |
|
| 143 |
+ Error string |
|
| 144 |
+ Out string |
|
| 145 |
+ Err string |
|
| 146 |
+} |
|
| 147 |
+ |
|
| 148 |
+// Success is the default expected result |
|
| 149 |
+var Success = Expected{}
|
|
| 150 |
+ |
|
| 151 |
+// Stdout returns the stdout of the process as a string |
|
| 152 |
+func (r *Result) Stdout() string {
|
|
| 153 |
+ return r.outBuffer.String() |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 156 |
+// Stderr returns the stderr of the process as a string |
|
| 157 |
+func (r *Result) Stderr() string {
|
|
| 158 |
+ return r.errBuffer.String() |
|
| 159 |
+} |
|
| 160 |
+ |
|
| 161 |
+// Combined returns the stdout and stderr combined into a single string |
|
| 162 |
+func (r *Result) Combined() string {
|
|
| 163 |
+ return r.outBuffer.String() + r.errBuffer.String() |
|
| 164 |
+} |
|
| 165 |
+ |
|
| 166 |
+// SetExitError sets Error and ExitCode based on Error |
|
| 167 |
+func (r *Result) SetExitError(err error) {
|
|
| 168 |
+ if err == nil {
|
|
| 169 |
+ return |
|
| 170 |
+ } |
|
| 171 |
+ r.Error = err |
|
| 172 |
+ r.ExitCode = system.ProcessExitCode(err) |
|
| 173 |
+} |
|
| 174 |
+ |
|
| 175 |
+type matches struct{}
|
|
| 176 |
+ |
|
| 177 |
+// Info returns the CheckerInfo |
|
| 178 |
+func (m *matches) Info() *check.CheckerInfo {
|
|
| 179 |
+ return &check.CheckerInfo{
|
|
| 180 |
+ Name: "CommandMatches", |
|
| 181 |
+ Params: []string{"result", "expected"},
|
|
| 182 |
+ } |
|
| 183 |
+} |
|
| 184 |
+ |
|
| 185 |
+// Check compares a result against the expected |
|
| 186 |
+func (m *matches) Check(params []interface{}, names []string) (bool, string) {
|
|
| 187 |
+ result, ok := params[0].(*Result) |
|
| 188 |
+ if !ok {
|
|
| 189 |
+ return false, fmt.Sprintf("result must be a *Result, not %T", params[0])
|
|
| 190 |
+ } |
|
| 191 |
+ expected, ok := params[1].(Expected) |
|
| 192 |
+ if !ok {
|
|
| 193 |
+ return false, fmt.Sprintf("expected must be an Expected, not %T", params[1])
|
|
| 194 |
+ } |
|
| 195 |
+ |
|
| 196 |
+ err := result.Compare(expected) |
|
| 197 |
+ if err == nil {
|
|
| 198 |
+ return true, "" |
|
| 199 |
+ } |
|
| 200 |
+ return false, err.Error() |
|
| 201 |
+} |
|
| 202 |
+ |
|
| 203 |
+// Matches is a gocheck.Checker for comparing a Result against an Expected |
|
| 204 |
+var Matches = &matches{}
|
|
| 205 |
+ |
|
| 206 |
+// Cmd contains the arguments and options for a process to run as part of a test |
|
| 207 |
+// suite. |
|
| 208 |
+type Cmd struct {
|
|
| 209 |
+ Command []string |
|
| 210 |
+ Timeout time.Duration |
|
| 211 |
+ Stdin io.Reader |
|
| 212 |
+ Stdout io.Writer |
|
| 213 |
+ Dir string |
|
| 214 |
+ Env []string |
|
| 215 |
+} |
|
| 216 |
+ |
|
| 217 |
+// RunCmd runs a command and returns a Result |
|
| 218 |
+func RunCmd(cmd Cmd) *Result {
|
|
| 219 |
+ result := StartCmd(cmd) |
|
| 220 |
+ if result.Error != nil {
|
|
| 221 |
+ return result |
|
| 222 |
+ } |
|
| 223 |
+ return WaitOnCmd(cmd.Timeout, result) |
|
| 224 |
+} |
|
| 225 |
+ |
|
| 226 |
+// RunCommand parses a command line and runs it, returning a result |
|
| 227 |
+func RunCommand(command string, args ...string) *Result {
|
|
| 228 |
+ return RunCmd(Cmd{Command: append([]string{command}, args...)})
|
|
| 229 |
+} |
|
| 230 |
+ |
|
| 231 |
+// StartCmd starts a command, but doesn't wait for it to finish |
|
| 232 |
+func StartCmd(cmd Cmd) *Result {
|
|
| 233 |
+ result := buildCmd(cmd) |
|
| 234 |
+ if result.Error != nil {
|
|
| 235 |
+ return result |
|
| 236 |
+ } |
|
| 237 |
+ result.SetExitError(result.Cmd.Start()) |
|
| 238 |
+ return result |
|
| 239 |
+} |
|
| 240 |
+ |
|
| 241 |
+func buildCmd(cmd Cmd) *Result {
|
|
| 242 |
+ var execCmd *exec.Cmd |
|
| 243 |
+ switch len(cmd.Command) {
|
|
| 244 |
+ case 1: |
|
| 245 |
+ execCmd = exec.Command(cmd.Command[0]) |
|
| 246 |
+ default: |
|
| 247 |
+ execCmd = exec.Command(cmd.Command[0], cmd.Command[1:]...) |
|
| 248 |
+ } |
|
| 249 |
+ outBuffer := new(lockedBuffer) |
|
| 250 |
+ errBuffer := new(lockedBuffer) |
|
| 251 |
+ |
|
| 252 |
+ execCmd.Stdin = cmd.Stdin |
|
| 253 |
+ execCmd.Dir = cmd.Dir |
|
| 254 |
+ execCmd.Env = cmd.Env |
|
| 255 |
+ if cmd.Stdout != nil {
|
|
| 256 |
+ execCmd.Stdout = io.MultiWriter(outBuffer, cmd.Stdout) |
|
| 257 |
+ } else {
|
|
| 258 |
+ execCmd.Stdout = outBuffer |
|
| 259 |
+ } |
|
| 260 |
+ execCmd.Stderr = errBuffer |
|
| 261 |
+ return &Result{
|
|
| 262 |
+ Cmd: execCmd, |
|
| 263 |
+ outBuffer: outBuffer, |
|
| 264 |
+ errBuffer: errBuffer, |
|
| 265 |
+ } |
|
| 266 |
+} |
|
| 267 |
+ |
|
| 268 |
+// WaitOnCmd waits for a command to complete. If timeout is non-nil then |
|
| 269 |
+// only wait until the timeout. |
|
| 270 |
+func WaitOnCmd(timeout time.Duration, result *Result) *Result {
|
|
| 271 |
+ if timeout == time.Duration(0) {
|
|
| 272 |
+ result.SetExitError(result.Cmd.Wait()) |
|
| 273 |
+ return result |
|
| 274 |
+ } |
|
| 275 |
+ |
|
| 276 |
+ done := make(chan error, 1) |
|
| 277 |
+ // Wait for command to exit in a goroutine |
|
| 278 |
+ go func() {
|
|
| 279 |
+ done <- result.Cmd.Wait() |
|
| 280 |
+ }() |
|
| 281 |
+ |
|
| 282 |
+ select {
|
|
| 283 |
+ case <-time.After(timeout): |
|
| 284 |
+ killErr := result.Cmd.Process.Kill() |
|
| 285 |
+ if killErr != nil {
|
|
| 286 |
+ fmt.Printf("failed to kill (pid=%d): %v\n", result.Cmd.Process.Pid, killErr)
|
|
| 287 |
+ } |
|
| 288 |
+ result.Timeout = true |
|
| 289 |
+ case err := <-done: |
|
| 290 |
+ result.SetExitError(err) |
|
| 291 |
+ } |
|
| 292 |
+ return result |
|
| 293 |
+} |
| 0 | 294 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,118 @@ |
| 0 |
+package cmd |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "runtime" |
|
| 4 |
+ "strings" |
|
| 5 |
+ "testing" |
|
| 6 |
+ "time" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/pkg/testutil/assert" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+func TestRunCommand(t *testing.T) {
|
|
| 12 |
+ // TODO Windows: Port this test |
|
| 13 |
+ if runtime.GOOS == "windows" {
|
|
| 14 |
+ t.Skip("Needs porting to Windows")
|
|
| 15 |
+ } |
|
| 16 |
+ |
|
| 17 |
+ var cmd string |
|
| 18 |
+ if runtime.GOOS == "solaris" {
|
|
| 19 |
+ cmd = "gls" |
|
| 20 |
+ } else {
|
|
| 21 |
+ cmd = "ls" |
|
| 22 |
+ } |
|
| 23 |
+ result := RunCommand(cmd) |
|
| 24 |
+ result.Assert(t, Expected{})
|
|
| 25 |
+ |
|
| 26 |
+ result = RunCommand("doesnotexists")
|
|
| 27 |
+ expectedError := `exec: "doesnotexists": executable file not found` |
|
| 28 |
+ result.Assert(t, Expected{ExitCode: 127, Error: expectedError})
|
|
| 29 |
+ |
|
| 30 |
+ result = RunCommand(cmd, "-z") |
|
| 31 |
+ result.Assert(t, Expected{
|
|
| 32 |
+ ExitCode: 2, |
|
| 33 |
+ Error: "exit status 2", |
|
| 34 |
+ Err: "invalid option", |
|
| 35 |
+ }) |
|
| 36 |
+ assert.Contains(t, result.Combined(), "invalid option") |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+func TestRunCommandWithCombined(t *testing.T) {
|
|
| 40 |
+ // TODO Windows: Port this test |
|
| 41 |
+ if runtime.GOOS == "windows" {
|
|
| 42 |
+ t.Skip("Needs porting to Windows")
|
|
| 43 |
+ } |
|
| 44 |
+ |
|
| 45 |
+ result := RunCommand("ls", "-a")
|
|
| 46 |
+ result.Assert(t, Expected{})
|
|
| 47 |
+ |
|
| 48 |
+ assert.Contains(t, result.Combined(), "..") |
|
| 49 |
+ assert.Contains(t, result.Stdout(), "..") |
|
| 50 |
+} |
|
| 51 |
+ |
|
| 52 |
+func TestRunCommandWithTimeoutFinished(t *testing.T) {
|
|
| 53 |
+ // TODO Windows: Port this test |
|
| 54 |
+ if runtime.GOOS == "windows" {
|
|
| 55 |
+ t.Skip("Needs porting to Windows")
|
|
| 56 |
+ } |
|
| 57 |
+ |
|
| 58 |
+ result := RunCmd(Cmd{
|
|
| 59 |
+ Command: []string{"ls", "-a"},
|
|
| 60 |
+ Timeout: 50 * time.Millisecond, |
|
| 61 |
+ }) |
|
| 62 |
+ result.Assert(t, Expected{Out: ".."})
|
|
| 63 |
+} |
|
| 64 |
+ |
|
| 65 |
+func TestRunCommandWithTimeoutKilled(t *testing.T) {
|
|
| 66 |
+ // TODO Windows: Port this test |
|
| 67 |
+ if runtime.GOOS == "windows" {
|
|
| 68 |
+ t.Skip("Needs porting to Windows")
|
|
| 69 |
+ } |
|
| 70 |
+ |
|
| 71 |
+ command := []string{"sh", "-c", "while true ; do echo 1 ; sleep .5 ; done"}
|
|
| 72 |
+ result := RunCmd(Cmd{Command: command, Timeout: 1250 * time.Millisecond})
|
|
| 73 |
+ result.Assert(t, Expected{Timeout: true})
|
|
| 74 |
+ |
|
| 75 |
+ ones := strings.Split(result.Stdout(), "\n") |
|
| 76 |
+ assert.Equal(t, len(ones), 4) |
|
| 77 |
+} |
|
| 78 |
+ |
|
| 79 |
+func TestRunCommandWithErrors(t *testing.T) {
|
|
| 80 |
+ result := RunCommand("/foobar")
|
|
| 81 |
+ result.Assert(t, Expected{Error: "foobar", ExitCode: 127})
|
|
| 82 |
+} |
|
| 83 |
+ |
|
| 84 |
+func TestRunCommandWithStdoutStderr(t *testing.T) {
|
|
| 85 |
+ result := RunCommand("echo", "hello", "world")
|
|
| 86 |
+ result.Assert(t, Expected{Out: "hello world\n", Err: None})
|
|
| 87 |
+} |
|
| 88 |
+ |
|
| 89 |
+func TestRunCommandWithStdoutStderrError(t *testing.T) {
|
|
| 90 |
+ result := RunCommand("doesnotexists")
|
|
| 91 |
+ |
|
| 92 |
+ expected := `exec: "doesnotexists": executable file not found` |
|
| 93 |
+ result.Assert(t, Expected{Out: None, Err: None, ExitCode: 127, Error: expected})
|
|
| 94 |
+ |
|
| 95 |
+ switch runtime.GOOS {
|
|
| 96 |
+ case "windows": |
|
| 97 |
+ expected = "ls: unknown option" |
|
| 98 |
+ case "solaris": |
|
| 99 |
+ expected = "gls: invalid option" |
|
| 100 |
+ default: |
|
| 101 |
+ expected = "ls: invalid option" |
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ var cmd string |
|
| 105 |
+ if runtime.GOOS == "solaris" {
|
|
| 106 |
+ cmd = "gls" |
|
| 107 |
+ } else {
|
|
| 108 |
+ cmd = "ls" |
|
| 109 |
+ } |
|
| 110 |
+ result = RunCommand(cmd, "-z") |
|
| 111 |
+ result.Assert(t, Expected{
|
|
| 112 |
+ Out: None, |
|
| 113 |
+ Err: expected, |
|
| 114 |
+ ExitCode: 2, |
|
| 115 |
+ Error: "exit status 2", |
|
| 116 |
+ }) |
|
| 117 |
+} |
| 0 | 118 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,234 @@ |
| 0 |
+package testutil |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "archive/tar" |
|
| 4 |
+ "errors" |
|
| 5 |
+ "fmt" |
|
| 6 |
+ "io" |
|
| 7 |
+ "io/ioutil" |
|
| 8 |
+ "os" |
|
| 9 |
+ "os/exec" |
|
| 10 |
+ "path/filepath" |
|
| 11 |
+ "reflect" |
|
| 12 |
+ "strings" |
|
| 13 |
+ "syscall" |
|
| 14 |
+ "time" |
|
| 15 |
+ |
|
| 16 |
+ "github.com/docker/docker/pkg/stringutils" |
|
| 17 |
+ "github.com/docker/docker/pkg/system" |
|
| 18 |
+ icmd "github.com/docker/docker/pkg/testutil/cmd" |
|
| 19 |
+) |
|
| 20 |
+ |
|
| 21 |
+// IsKilled process the specified error and returns whether the process was killed or not. |
|
| 22 |
+func IsKilled(err error) bool {
|
|
| 23 |
+ if exitErr, ok := err.(*exec.ExitError); ok {
|
|
| 24 |
+ status, ok := exitErr.Sys().(syscall.WaitStatus) |
|
| 25 |
+ if !ok {
|
|
| 26 |
+ return false |
|
| 27 |
+ } |
|
| 28 |
+ // status.ExitStatus() is required on Windows because it does not |
|
| 29 |
+ // implement Signal() nor Signaled(). Just check it had a bad exit |
|
| 30 |
+ // status could mean it was killed (and in tests we do kill) |
|
| 31 |
+ return (status.Signaled() && status.Signal() == os.Kill) || status.ExitStatus() != 0 |
|
| 32 |
+ } |
|
| 33 |
+ return false |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 36 |
+func runCommandWithOutput(cmd *exec.Cmd) (output string, exitCode int, err error) {
|
|
| 37 |
+ exitCode = 0 |
|
| 38 |
+ out, err := cmd.CombinedOutput() |
|
| 39 |
+ exitCode = system.ProcessExitCode(err) |
|
| 40 |
+ output = string(out) |
|
| 41 |
+ return |
|
| 42 |
+} |
|
| 43 |
+ |
|
| 44 |
+// RunCommandPipelineWithOutput runs the array of commands with the output |
|
| 45 |
+// of each pipelined with the following (like cmd1 | cmd2 | cmd3 would do). |
|
| 46 |
+// It returns the final output, the exitCode different from 0 and the error |
|
| 47 |
+// if something bad happened. |
|
| 48 |
+func RunCommandPipelineWithOutput(cmds ...*exec.Cmd) (output string, exitCode int, err error) {
|
|
| 49 |
+ if len(cmds) < 2 {
|
|
| 50 |
+ return "", 0, errors.New("pipeline does not have multiple cmds")
|
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+ // connect stdin of each cmd to stdout pipe of previous cmd |
|
| 54 |
+ for i, cmd := range cmds {
|
|
| 55 |
+ if i > 0 {
|
|
| 56 |
+ prevCmd := cmds[i-1] |
|
| 57 |
+ cmd.Stdin, err = prevCmd.StdoutPipe() |
|
| 58 |
+ |
|
| 59 |
+ if err != nil {
|
|
| 60 |
+ return "", 0, fmt.Errorf("cannot set stdout pipe for %s: %v", cmd.Path, err)
|
|
| 61 |
+ } |
|
| 62 |
+ } |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ // start all cmds except the last |
|
| 66 |
+ for _, cmd := range cmds[:len(cmds)-1] {
|
|
| 67 |
+ if err = cmd.Start(); err != nil {
|
|
| 68 |
+ return "", 0, fmt.Errorf("starting %s failed with error: %v", cmd.Path, err)
|
|
| 69 |
+ } |
|
| 70 |
+ } |
|
| 71 |
+ |
|
| 72 |
+ defer func() {
|
|
| 73 |
+ var pipeErrMsgs []string |
|
| 74 |
+ // wait all cmds except the last to release their resources |
|
| 75 |
+ for _, cmd := range cmds[:len(cmds)-1] {
|
|
| 76 |
+ if pipeErr := cmd.Wait(); pipeErr != nil {
|
|
| 77 |
+ pipeErrMsgs = append(pipeErrMsgs, fmt.Sprintf("command %s failed with error: %v", cmd.Path, pipeErr))
|
|
| 78 |
+ } |
|
| 79 |
+ } |
|
| 80 |
+ if len(pipeErrMsgs) > 0 && err == nil {
|
|
| 81 |
+ err = fmt.Errorf("pipelineError from Wait: %v", strings.Join(pipeErrMsgs, ", "))
|
|
| 82 |
+ } |
|
| 83 |
+ }() |
|
| 84 |
+ |
|
| 85 |
+ // wait on last cmd |
|
| 86 |
+ return runCommandWithOutput(cmds[len(cmds)-1]) |
|
| 87 |
+} |
|
| 88 |
+ |
|
| 89 |
+// ConvertSliceOfStringsToMap converts a slices of string in a map |
|
| 90 |
+// with the strings as key and an empty string as values. |
|
| 91 |
+func ConvertSliceOfStringsToMap(input []string) map[string]struct{} {
|
|
| 92 |
+ output := make(map[string]struct{})
|
|
| 93 |
+ for _, v := range input {
|
|
| 94 |
+ output[v] = struct{}{}
|
|
| 95 |
+ } |
|
| 96 |
+ return output |
|
| 97 |
+} |
|
| 98 |
+ |
|
| 99 |
+// CompareDirectoryEntries compares two sets of FileInfo (usually taken from a directory) |
|
| 100 |
+// and returns an error if different. |
|
| 101 |
+func CompareDirectoryEntries(e1 []os.FileInfo, e2 []os.FileInfo) error {
|
|
| 102 |
+ var ( |
|
| 103 |
+ e1Entries = make(map[string]struct{})
|
|
| 104 |
+ e2Entries = make(map[string]struct{})
|
|
| 105 |
+ ) |
|
| 106 |
+ for _, e := range e1 {
|
|
| 107 |
+ e1Entries[e.Name()] = struct{}{}
|
|
| 108 |
+ } |
|
| 109 |
+ for _, e := range e2 {
|
|
| 110 |
+ e2Entries[e.Name()] = struct{}{}
|
|
| 111 |
+ } |
|
| 112 |
+ if !reflect.DeepEqual(e1Entries, e2Entries) {
|
|
| 113 |
+ return fmt.Errorf("entries differ")
|
|
| 114 |
+ } |
|
| 115 |
+ return nil |
|
| 116 |
+} |
|
| 117 |
+ |
|
| 118 |
+// ListTar lists the entries of a tar. |
|
| 119 |
+func ListTar(f io.Reader) ([]string, error) {
|
|
| 120 |
+ tr := tar.NewReader(f) |
|
| 121 |
+ var entries []string |
|
| 122 |
+ |
|
| 123 |
+ for {
|
|
| 124 |
+ th, err := tr.Next() |
|
| 125 |
+ if err == io.EOF {
|
|
| 126 |
+ // end of tar archive |
|
| 127 |
+ return entries, nil |
|
| 128 |
+ } |
|
| 129 |
+ if err != nil {
|
|
| 130 |
+ return entries, err |
|
| 131 |
+ } |
|
| 132 |
+ entries = append(entries, th.Name) |
|
| 133 |
+ } |
|
| 134 |
+} |
|
| 135 |
+ |
|
| 136 |
+// RandomTmpDirPath provides a temporary path with rand string appended. |
|
| 137 |
+// does not create or checks if it exists. |
|
| 138 |
+func RandomTmpDirPath(s string, platform string) string {
|
|
| 139 |
+ tmp := "/tmp" |
|
| 140 |
+ if platform == "windows" {
|
|
| 141 |
+ tmp = os.Getenv("TEMP")
|
|
| 142 |
+ } |
|
| 143 |
+ path := filepath.Join(tmp, fmt.Sprintf("%s.%s", s, stringutils.GenerateRandomAlphaOnlyString(10)))
|
|
| 144 |
+ if platform == "windows" {
|
|
| 145 |
+ return filepath.FromSlash(path) // Using \ |
|
| 146 |
+ } |
|
| 147 |
+ return filepath.ToSlash(path) // Using / |
|
| 148 |
+} |
|
| 149 |
+ |
|
| 150 |
+// ConsumeWithSpeed reads chunkSize bytes from reader before sleeping |
|
| 151 |
+// for interval duration. Returns total read bytes. Send true to the |
|
| 152 |
+// stop channel to return before reading to EOF on the reader. |
|
| 153 |
+func ConsumeWithSpeed(reader io.Reader, chunkSize int, interval time.Duration, stop chan bool) (n int, err error) {
|
|
| 154 |
+ buffer := make([]byte, chunkSize) |
|
| 155 |
+ for {
|
|
| 156 |
+ var readBytes int |
|
| 157 |
+ readBytes, err = reader.Read(buffer) |
|
| 158 |
+ n += readBytes |
|
| 159 |
+ if err != nil {
|
|
| 160 |
+ if err == io.EOF {
|
|
| 161 |
+ err = nil |
|
| 162 |
+ } |
|
| 163 |
+ return |
|
| 164 |
+ } |
|
| 165 |
+ select {
|
|
| 166 |
+ case <-stop: |
|
| 167 |
+ return |
|
| 168 |
+ case <-time.After(interval): |
|
| 169 |
+ } |
|
| 170 |
+ } |
|
| 171 |
+} |
|
| 172 |
+ |
|
| 173 |
+// ParseCgroupPaths parses 'procCgroupData', which is output of '/proc/<pid>/cgroup', and returns |
|
| 174 |
+// a map which cgroup name as key and path as value. |
|
| 175 |
+func ParseCgroupPaths(procCgroupData string) map[string]string {
|
|
| 176 |
+ cgroupPaths := map[string]string{}
|
|
| 177 |
+ for _, line := range strings.Split(procCgroupData, "\n") {
|
|
| 178 |
+ parts := strings.Split(line, ":") |
|
| 179 |
+ if len(parts) != 3 {
|
|
| 180 |
+ continue |
|
| 181 |
+ } |
|
| 182 |
+ cgroupPaths[parts[1]] = parts[2] |
|
| 183 |
+ } |
|
| 184 |
+ return cgroupPaths |
|
| 185 |
+} |
|
| 186 |
+ |
|
| 187 |
+// ChannelBuffer holds a chan of byte array that can be populate in a goroutine. |
|
| 188 |
+type ChannelBuffer struct {
|
|
| 189 |
+ C chan []byte |
|
| 190 |
+} |
|
| 191 |
+ |
|
| 192 |
+// Write implements Writer. |
|
| 193 |
+func (c *ChannelBuffer) Write(b []byte) (int, error) {
|
|
| 194 |
+ c.C <- b |
|
| 195 |
+ return len(b), nil |
|
| 196 |
+} |
|
| 197 |
+ |
|
| 198 |
+// Close closes the go channel. |
|
| 199 |
+func (c *ChannelBuffer) Close() error {
|
|
| 200 |
+ close(c.C) |
|
| 201 |
+ return nil |
|
| 202 |
+} |
|
| 203 |
+ |
|
| 204 |
+// ReadTimeout reads the content of the channel in the specified byte array with |
|
| 205 |
+// the specified duration as timeout. |
|
| 206 |
+func (c *ChannelBuffer) ReadTimeout(p []byte, n time.Duration) (int, error) {
|
|
| 207 |
+ select {
|
|
| 208 |
+ case b := <-c.C: |
|
| 209 |
+ return copy(p[0:], b), nil |
|
| 210 |
+ case <-time.After(n): |
|
| 211 |
+ return -1, fmt.Errorf("timeout reading from channel")
|
|
| 212 |
+ } |
|
| 213 |
+} |
|
| 214 |
+ |
|
| 215 |
+// RunAtDifferentDate runs the specified function with the given time. |
|
| 216 |
+// It changes the date of the system, which can led to weird behaviors. |
|
| 217 |
+func RunAtDifferentDate(date time.Time, block func()) {
|
|
| 218 |
+ // Layout for date. MMDDhhmmYYYY |
|
| 219 |
+ const timeLayout = "010203042006" |
|
| 220 |
+ // Ensure we bring time back to now |
|
| 221 |
+ now := time.Now().Format(timeLayout) |
|
| 222 |
+ defer icmd.RunCommand("date", now)
|
|
| 223 |
+ |
|
| 224 |
+ icmd.RunCommand("date", date.Format(timeLayout))
|
|
| 225 |
+ block() |
|
| 226 |
+ return |
|
| 227 |
+} |
|
| 228 |
+ |
|
| 229 |
+// ReadBody read the specified ReadCloser content and returns it |
|
| 230 |
+func ReadBody(b io.ReadCloser) ([]byte, error) {
|
|
| 231 |
+ defer b.Close() |
|
| 232 |
+ return ioutil.ReadAll(b) |
|
| 233 |
+} |
| 0 | 234 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,363 @@ |
| 0 |
+package testutil |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "io" |
|
| 4 |
+ "io/ioutil" |
|
| 5 |
+ "os" |
|
| 6 |
+ "os/exec" |
|
| 7 |
+ "path/filepath" |
|
| 8 |
+ "runtime" |
|
| 9 |
+ "strings" |
|
| 10 |
+ "testing" |
|
| 11 |
+ "time" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+func TestIsKilledFalseWithNonKilledProcess(t *testing.T) {
|
|
| 15 |
+ var lsCmd *exec.Cmd |
|
| 16 |
+ if runtime.GOOS != "windows" {
|
|
| 17 |
+ lsCmd = exec.Command("ls")
|
|
| 18 |
+ } else {
|
|
| 19 |
+ lsCmd = exec.Command("cmd", "/c", "dir")
|
|
| 20 |
+ } |
|
| 21 |
+ |
|
| 22 |
+ err := lsCmd.Run() |
|
| 23 |
+ if IsKilled(err) {
|
|
| 24 |
+ t.Fatalf("Expected the ls command to not be killed, was.")
|
|
| 25 |
+ } |
|
| 26 |
+} |
|
| 27 |
+ |
|
| 28 |
+func TestIsKilledTrueWithKilledProcess(t *testing.T) {
|
|
| 29 |
+ var longCmd *exec.Cmd |
|
| 30 |
+ if runtime.GOOS != "windows" {
|
|
| 31 |
+ longCmd = exec.Command("top")
|
|
| 32 |
+ } else {
|
|
| 33 |
+ longCmd = exec.Command("powershell", "while ($true) { sleep 1 }")
|
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ // Start a command |
|
| 37 |
+ err := longCmd.Start() |
|
| 38 |
+ if err != nil {
|
|
| 39 |
+ t.Fatal(err) |
|
| 40 |
+ } |
|
| 41 |
+ // Capture the error when *dying* |
|
| 42 |
+ done := make(chan error, 1) |
|
| 43 |
+ go func() {
|
|
| 44 |
+ done <- longCmd.Wait() |
|
| 45 |
+ }() |
|
| 46 |
+ // Then kill it |
|
| 47 |
+ longCmd.Process.Kill() |
|
| 48 |
+ // Get the error |
|
| 49 |
+ err = <-done |
|
| 50 |
+ if !IsKilled(err) {
|
|
| 51 |
+ t.Fatalf("Expected the command to be killed, was not.")
|
|
| 52 |
+ } |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+func TestRunCommandPipelineWithOutputWithNotEnoughCmds(t *testing.T) {
|
|
| 56 |
+ _, _, err := RunCommandPipelineWithOutput(exec.Command("ls"))
|
|
| 57 |
+ expectedError := "pipeline does not have multiple cmds" |
|
| 58 |
+ if err == nil || err.Error() != expectedError {
|
|
| 59 |
+ t.Fatalf("Expected an error with %s, got err:%s", expectedError, err)
|
|
| 60 |
+ } |
|
| 61 |
+} |
|
| 62 |
+ |
|
| 63 |
+func TestRunCommandPipelineWithOutputErrors(t *testing.T) {
|
|
| 64 |
+ p := "$PATH" |
|
| 65 |
+ if runtime.GOOS == "windows" {
|
|
| 66 |
+ p = "%PATH%" |
|
| 67 |
+ } |
|
| 68 |
+ cmd1 := exec.Command("ls")
|
|
| 69 |
+ cmd1.Stdout = os.Stdout |
|
| 70 |
+ cmd2 := exec.Command("anything really")
|
|
| 71 |
+ _, _, err := RunCommandPipelineWithOutput(cmd1, cmd2) |
|
| 72 |
+ if err == nil || err.Error() != "cannot set stdout pipe for anything really: exec: Stdout already set" {
|
|
| 73 |
+ t.Fatalf("Expected an error, got %v", err)
|
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ cmdWithError := exec.Command("doesnotexists")
|
|
| 77 |
+ cmdCat := exec.Command("cat")
|
|
| 78 |
+ _, _, err = RunCommandPipelineWithOutput(cmdWithError, cmdCat) |
|
| 79 |
+ if err == nil || err.Error() != `starting doesnotexists failed with error: exec: "doesnotexists": executable file not found in `+p {
|
|
| 80 |
+ t.Fatalf("Expected an error, got %v", err)
|
|
| 81 |
+ } |
|
| 82 |
+} |
|
| 83 |
+ |
|
| 84 |
+func TestRunCommandPipelineWithOutput(t *testing.T) {
|
|
| 85 |
+ //TODO: Should run on Solaris |
|
| 86 |
+ if runtime.GOOS == "solaris" {
|
|
| 87 |
+ t.Skip() |
|
| 88 |
+ } |
|
| 89 |
+ cmds := []*exec.Cmd{
|
|
| 90 |
+ // Print 2 characters |
|
| 91 |
+ exec.Command("echo", "-n", "11"),
|
|
| 92 |
+ // Count the number or char from stdin (previous command) |
|
| 93 |
+ exec.Command("wc", "-m"),
|
|
| 94 |
+ } |
|
| 95 |
+ out, exitCode, err := RunCommandPipelineWithOutput(cmds...) |
|
| 96 |
+ expectedOutput := "2\n" |
|
| 97 |
+ if out != expectedOutput || exitCode != 0 || err != nil {
|
|
| 98 |
+ t.Fatalf("Expected %s for commands %v, got out:%s, exitCode:%d, err:%v", expectedOutput, cmds, out, exitCode, err)
|
|
| 99 |
+ } |
|
| 100 |
+} |
|
| 101 |
+ |
|
| 102 |
+func TestConvertSliceOfStringsToMap(t *testing.T) {
|
|
| 103 |
+ input := []string{"a", "b"}
|
|
| 104 |
+ actual := ConvertSliceOfStringsToMap(input) |
|
| 105 |
+ for _, key := range input {
|
|
| 106 |
+ if _, ok := actual[key]; !ok {
|
|
| 107 |
+ t.Fatalf("Expected output to contains key %s, did not: %v", key, actual)
|
|
| 108 |
+ } |
|
| 109 |
+ } |
|
| 110 |
+} |
|
| 111 |
+ |
|
| 112 |
+func TestCompareDirectoryEntries(t *testing.T) {
|
|
| 113 |
+ tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-compare-directories")
|
|
| 114 |
+ if err != nil {
|
|
| 115 |
+ t.Fatal(err) |
|
| 116 |
+ } |
|
| 117 |
+ defer os.RemoveAll(tmpFolder) |
|
| 118 |
+ |
|
| 119 |
+ file1 := filepath.Join(tmpFolder, "file1") |
|
| 120 |
+ file2 := filepath.Join(tmpFolder, "file2") |
|
| 121 |
+ os.Create(file1) |
|
| 122 |
+ os.Create(file2) |
|
| 123 |
+ |
|
| 124 |
+ fi1, err := os.Stat(file1) |
|
| 125 |
+ if err != nil {
|
|
| 126 |
+ t.Fatal(err) |
|
| 127 |
+ } |
|
| 128 |
+ fi1bis, err := os.Stat(file1) |
|
| 129 |
+ if err != nil {
|
|
| 130 |
+ t.Fatal(err) |
|
| 131 |
+ } |
|
| 132 |
+ fi2, err := os.Stat(file2) |
|
| 133 |
+ if err != nil {
|
|
| 134 |
+ t.Fatal(err) |
|
| 135 |
+ } |
|
| 136 |
+ |
|
| 137 |
+ cases := []struct {
|
|
| 138 |
+ e1 []os.FileInfo |
|
| 139 |
+ e2 []os.FileInfo |
|
| 140 |
+ shouldError bool |
|
| 141 |
+ }{
|
|
| 142 |
+ // Empty directories |
|
| 143 |
+ {
|
|
| 144 |
+ []os.FileInfo{},
|
|
| 145 |
+ []os.FileInfo{},
|
|
| 146 |
+ false, |
|
| 147 |
+ }, |
|
| 148 |
+ // Same FileInfos |
|
| 149 |
+ {
|
|
| 150 |
+ []os.FileInfo{fi1},
|
|
| 151 |
+ []os.FileInfo{fi1},
|
|
| 152 |
+ false, |
|
| 153 |
+ }, |
|
| 154 |
+ // Different FileInfos but same names |
|
| 155 |
+ {
|
|
| 156 |
+ []os.FileInfo{fi1},
|
|
| 157 |
+ []os.FileInfo{fi1bis},
|
|
| 158 |
+ false, |
|
| 159 |
+ }, |
|
| 160 |
+ // Different FileInfos, different names |
|
| 161 |
+ {
|
|
| 162 |
+ []os.FileInfo{fi1},
|
|
| 163 |
+ []os.FileInfo{fi2},
|
|
| 164 |
+ true, |
|
| 165 |
+ }, |
|
| 166 |
+ } |
|
| 167 |
+ for _, elt := range cases {
|
|
| 168 |
+ err := CompareDirectoryEntries(elt.e1, elt.e2) |
|
| 169 |
+ if elt.shouldError && err == nil {
|
|
| 170 |
+ t.Fatalf("Should have return an error, did not with %v and %v", elt.e1, elt.e2)
|
|
| 171 |
+ } |
|
| 172 |
+ if !elt.shouldError && err != nil {
|
|
| 173 |
+ t.Fatalf("Should have not returned an error, but did : %v with %v and %v", err, elt.e1, elt.e2)
|
|
| 174 |
+ } |
|
| 175 |
+ } |
|
| 176 |
+} |
|
| 177 |
+ |
|
| 178 |
+// FIXME make an "unhappy path" test for ListTar without "panicking" :-) |
|
| 179 |
+func TestListTar(t *testing.T) {
|
|
| 180 |
+ // TODO Windows: Figure out why this fails. Should be portable. |
|
| 181 |
+ if runtime.GOOS == "windows" {
|
|
| 182 |
+ t.Skip("Failing on Windows - needs further investigation")
|
|
| 183 |
+ } |
|
| 184 |
+ tmpFolder, err := ioutil.TempDir("", "integration-cli-utils-list-tar")
|
|
| 185 |
+ if err != nil {
|
|
| 186 |
+ t.Fatal(err) |
|
| 187 |
+ } |
|
| 188 |
+ defer os.RemoveAll(tmpFolder) |
|
| 189 |
+ |
|
| 190 |
+ // Let's create a Tar file |
|
| 191 |
+ srcFile := filepath.Join(tmpFolder, "src") |
|
| 192 |
+ tarFile := filepath.Join(tmpFolder, "src.tar") |
|
| 193 |
+ os.Create(srcFile) |
|
| 194 |
+ cmd := exec.Command("sh", "-c", "tar cf "+tarFile+" "+srcFile)
|
|
| 195 |
+ _, err = cmd.CombinedOutput() |
|
| 196 |
+ if err != nil {
|
|
| 197 |
+ t.Fatal(err) |
|
| 198 |
+ } |
|
| 199 |
+ |
|
| 200 |
+ reader, err := os.Open(tarFile) |
|
| 201 |
+ if err != nil {
|
|
| 202 |
+ t.Fatal(err) |
|
| 203 |
+ } |
|
| 204 |
+ defer reader.Close() |
|
| 205 |
+ |
|
| 206 |
+ entries, err := ListTar(reader) |
|
| 207 |
+ if err != nil {
|
|
| 208 |
+ t.Fatal(err) |
|
| 209 |
+ } |
|
| 210 |
+ if len(entries) != 1 && entries[0] != "src" {
|
|
| 211 |
+ t.Fatalf("Expected a tar file with 1 entry (%s), got %v", srcFile, entries)
|
|
| 212 |
+ } |
|
| 213 |
+} |
|
| 214 |
+ |
|
| 215 |
+func TestRandomTmpDirPath(t *testing.T) {
|
|
| 216 |
+ path := RandomTmpDirPath("something", runtime.GOOS)
|
|
| 217 |
+ |
|
| 218 |
+ prefix := "/tmp/something" |
|
| 219 |
+ if runtime.GOOS == "windows" {
|
|
| 220 |
+ prefix = os.Getenv("TEMP") + `\something`
|
|
| 221 |
+ } |
|
| 222 |
+ expectedSize := len(prefix) + 11 |
|
| 223 |
+ |
|
| 224 |
+ if !strings.HasPrefix(path, prefix) {
|
|
| 225 |
+ t.Fatalf("Expected generated path to have '%s' as prefix, got %s'", prefix, path)
|
|
| 226 |
+ } |
|
| 227 |
+ if len(path) != expectedSize {
|
|
| 228 |
+ t.Fatalf("Expected generated path to be %d, got %d", expectedSize, len(path))
|
|
| 229 |
+ } |
|
| 230 |
+} |
|
| 231 |
+ |
|
| 232 |
+func TestConsumeWithSpeed(t *testing.T) {
|
|
| 233 |
+ reader := strings.NewReader("1234567890")
|
|
| 234 |
+ chunksize := 2 |
|
| 235 |
+ |
|
| 236 |
+ bytes1, err := ConsumeWithSpeed(reader, chunksize, 10*time.Millisecond, nil) |
|
| 237 |
+ if err != nil {
|
|
| 238 |
+ t.Fatal(err) |
|
| 239 |
+ } |
|
| 240 |
+ |
|
| 241 |
+ if bytes1 != 10 {
|
|
| 242 |
+ t.Fatalf("Expected to have read 10 bytes, got %d", bytes1)
|
|
| 243 |
+ } |
|
| 244 |
+ |
|
| 245 |
+} |
|
| 246 |
+ |
|
| 247 |
+func TestConsumeWithSpeedWithStop(t *testing.T) {
|
|
| 248 |
+ reader := strings.NewReader("1234567890")
|
|
| 249 |
+ chunksize := 2 |
|
| 250 |
+ |
|
| 251 |
+ stopIt := make(chan bool) |
|
| 252 |
+ |
|
| 253 |
+ go func() {
|
|
| 254 |
+ time.Sleep(1 * time.Millisecond) |
|
| 255 |
+ stopIt <- true |
|
| 256 |
+ }() |
|
| 257 |
+ |
|
| 258 |
+ bytes1, err := ConsumeWithSpeed(reader, chunksize, 20*time.Millisecond, stopIt) |
|
| 259 |
+ if err != nil {
|
|
| 260 |
+ t.Fatal(err) |
|
| 261 |
+ } |
|
| 262 |
+ |
|
| 263 |
+ if bytes1 != 2 {
|
|
| 264 |
+ t.Fatalf("Expected to have read 2 bytes, got %d", bytes1)
|
|
| 265 |
+ } |
|
| 266 |
+ |
|
| 267 |
+} |
|
| 268 |
+ |
|
| 269 |
+func TestParseCgroupPathsEmpty(t *testing.T) {
|
|
| 270 |
+ cgroupMap := ParseCgroupPaths("")
|
|
| 271 |
+ if len(cgroupMap) != 0 {
|
|
| 272 |
+ t.Fatalf("Expected an empty map, got %v", cgroupMap)
|
|
| 273 |
+ } |
|
| 274 |
+ cgroupMap = ParseCgroupPaths("\n")
|
|
| 275 |
+ if len(cgroupMap) != 0 {
|
|
| 276 |
+ t.Fatalf("Expected an empty map, got %v", cgroupMap)
|
|
| 277 |
+ } |
|
| 278 |
+ cgroupMap = ParseCgroupPaths("something:else\nagain:here")
|
|
| 279 |
+ if len(cgroupMap) != 0 {
|
|
| 280 |
+ t.Fatalf("Expected an empty map, got %v", cgroupMap)
|
|
| 281 |
+ } |
|
| 282 |
+} |
|
| 283 |
+ |
|
| 284 |
+func TestParseCgroupPaths(t *testing.T) {
|
|
| 285 |
+ cgroupMap := ParseCgroupPaths("2:memory:/a\n1:cpuset:/b")
|
|
| 286 |
+ if len(cgroupMap) != 2 {
|
|
| 287 |
+ t.Fatalf("Expected a map with 2 entries, got %v", cgroupMap)
|
|
| 288 |
+ } |
|
| 289 |
+ if value, ok := cgroupMap["memory"]; !ok || value != "/a" {
|
|
| 290 |
+ t.Fatalf("Expected cgroupMap to contains an entry for 'memory' with value '/a', got %v", cgroupMap)
|
|
| 291 |
+ } |
|
| 292 |
+ if value, ok := cgroupMap["cpuset"]; !ok || value != "/b" {
|
|
| 293 |
+ t.Fatalf("Expected cgroupMap to contains an entry for 'cpuset' with value '/b', got %v", cgroupMap)
|
|
| 294 |
+ } |
|
| 295 |
+} |
|
| 296 |
+ |
|
| 297 |
+func TestChannelBufferTimeout(t *testing.T) {
|
|
| 298 |
+ expected := "11" |
|
| 299 |
+ |
|
| 300 |
+ buf := &ChannelBuffer{make(chan []byte, 1)}
|
|
| 301 |
+ defer buf.Close() |
|
| 302 |
+ |
|
| 303 |
+ done := make(chan struct{}, 1)
|
|
| 304 |
+ go func() {
|
|
| 305 |
+ time.Sleep(100 * time.Millisecond) |
|
| 306 |
+ io.Copy(buf, strings.NewReader(expected)) |
|
| 307 |
+ done <- struct{}{}
|
|
| 308 |
+ }() |
|
| 309 |
+ |
|
| 310 |
+ // Wait long enough |
|
| 311 |
+ b := make([]byte, 2) |
|
| 312 |
+ _, err := buf.ReadTimeout(b, 50*time.Millisecond) |
|
| 313 |
+ if err == nil && err.Error() != "timeout reading from channel" {
|
|
| 314 |
+ t.Fatalf("Expected an error, got %s", err)
|
|
| 315 |
+ } |
|
| 316 |
+ <-done |
|
| 317 |
+} |
|
| 318 |
+ |
|
| 319 |
+func TestChannelBuffer(t *testing.T) {
|
|
| 320 |
+ expected := "11" |
|
| 321 |
+ |
|
| 322 |
+ buf := &ChannelBuffer{make(chan []byte, 1)}
|
|
| 323 |
+ defer buf.Close() |
|
| 324 |
+ |
|
| 325 |
+ go func() {
|
|
| 326 |
+ time.Sleep(100 * time.Millisecond) |
|
| 327 |
+ io.Copy(buf, strings.NewReader(expected)) |
|
| 328 |
+ }() |
|
| 329 |
+ |
|
| 330 |
+ // Wait long enough |
|
| 331 |
+ b := make([]byte, 2) |
|
| 332 |
+ _, err := buf.ReadTimeout(b, 200*time.Millisecond) |
|
| 333 |
+ if err != nil {
|
|
| 334 |
+ t.Fatal(err) |
|
| 335 |
+ } |
|
| 336 |
+ |
|
| 337 |
+ if string(b) != expected {
|
|
| 338 |
+ t.Fatalf("Expected '%s', got '%s'", expected, string(b))
|
|
| 339 |
+ } |
|
| 340 |
+} |
|
| 341 |
+ |
|
| 342 |
+// FIXME doesn't work |
|
| 343 |
+// func TestRunAtDifferentDate(t *testing.T) {
|
|
| 344 |
+// var date string |
|
| 345 |
+ |
|
| 346 |
+// // Layout for date. MMDDhhmmYYYY |
|
| 347 |
+// const timeLayout = "20060102" |
|
| 348 |
+// expectedDate := "20100201" |
|
| 349 |
+// theDate, err := time.Parse(timeLayout, expectedDate) |
|
| 350 |
+// if err != nil {
|
|
| 351 |
+// t.Fatal(err) |
|
| 352 |
+// } |
|
| 353 |
+ |
|
| 354 |
+// RunAtDifferentDate(theDate, func() {
|
|
| 355 |
+// cmd := exec.Command("date", "+%Y%M%d")
|
|
| 356 |
+// out, err := cmd.Output() |
|
| 357 |
+// if err != nil {
|
|
| 358 |
+// t.Fatal(err) |
|
| 359 |
+// } |
|
| 360 |
+// date = string(out) |
|
| 361 |
+// }) |
|
| 362 |
+// } |