Skip to content

Commit e4e0ea2

Browse files
committed
test: pull on run should be ctx cancellable
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
1 parent 2da6244 commit e4e0ea2

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

cli/command/container/run_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package container
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
7+
"fmt"
68
"io"
79
"net"
810
"syscall"
@@ -16,7 +18,9 @@ import (
1618
"github.com/docker/cli/internal/test/notary"
1719
"github.com/docker/docker/api/types"
1820
"github.com/docker/docker/api/types/container"
21+
"github.com/docker/docker/api/types/image"
1922
"github.com/docker/docker/api/types/network"
23+
"github.com/docker/docker/pkg/jsonmessage"
2024
specs "github.com/opencontainers/image-spec/specs-go/v1"
2125
"github.com/spf13/pflag"
2226
"gotest.tools/v3/assert"
@@ -217,6 +221,86 @@ func TestRunAttachTermination(t *testing.T) {
217221
}
218222
}
219223

224+
func TestRunPullTermination(t *testing.T) {
225+
ctx, cancel := context.WithCancel(context.Background())
226+
t.Cleanup(cancel)
227+
228+
attachCh := make(chan struct{})
229+
fakeCLI := test.NewFakeCli(&fakeClient{
230+
createContainerFunc: func(config *container.Config, hostConfig *container.HostConfig, networkingConfig *network.NetworkingConfig, platform *specs.Platform, containerName string) (container.CreateResponse, error) {
231+
select {
232+
case <-ctx.Done():
233+
return container.CreateResponse{}, ctx.Err()
234+
default:
235+
}
236+
return container.CreateResponse{}, fakeNotFound{}
237+
},
238+
containerAttachFunc: func(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error) {
239+
return types.HijackedResponse{}, errors.New("shouldn't try to attach to a container")
240+
},
241+
imageCreateFunc: func(ctx context.Context, parentReference string, options image.CreateOptions) (io.ReadCloser, error) {
242+
server, client := net.Pipe()
243+
t.Cleanup(func() {
244+
_ = server.Close()
245+
})
246+
go func() {
247+
enc := json.NewEncoder(server)
248+
for i := 0; i < 100; i++ {
249+
select {
250+
case <-ctx.Done():
251+
assert.NilError(t, server.Close(), "failed to close imageCreateFunc server")
252+
return
253+
default:
254+
}
255+
assert.NilError(t, enc.Encode(jsonmessage.JSONMessage{
256+
Status: "Downloading",
257+
ID: fmt.Sprintf("id-%d", i),
258+
TimeNano: time.Now().UnixNano(),
259+
Time: time.Now().Unix(),
260+
Progress: &jsonmessage.JSONProgress{
261+
Current: int64(i),
262+
Total: 100,
263+
Start: 0,
264+
},
265+
}))
266+
time.Sleep(100 * time.Millisecond)
267+
}
268+
}()
269+
attachCh <- struct{}{}
270+
return client, nil
271+
},
272+
Version: "1.30",
273+
})
274+
275+
cmd := NewRunCommand(fakeCLI)
276+
cmd.SetOut(io.Discard)
277+
cmd.SetErr(io.Discard)
278+
cmd.SetArgs([]string{"foobar:latest"})
279+
280+
cmdErrC := make(chan error, 1)
281+
go func() {
282+
cmdErrC <- cmd.ExecuteContext(ctx)
283+
}()
284+
285+
select {
286+
case <-time.After(5 * time.Second):
287+
t.Fatal("imageCreateFunc was not called before the timeout")
288+
case <-attachCh:
289+
}
290+
291+
cancel()
292+
293+
select {
294+
case cmdErr := <-cmdErrC:
295+
assert.Equal(t, cmdErr, cli.StatusError{
296+
StatusCode: 125,
297+
Status: "docker: context canceled\n\nRun 'docker run --help' for more information",
298+
})
299+
case <-time.After(10 * time.Second):
300+
t.Fatal("cmd did not return before the timeout")
301+
}
302+
}
303+
220304
func TestRunCommandWithContentTrustErrors(t *testing.T) {
221305
testCases := []struct {
222306
name string

0 commit comments

Comments
 (0)