@@ -2,7 +2,9 @@ package container
2
2
3
3
import (
4
4
"context"
5
+ "encoding/json"
5
6
"errors"
7
+ "fmt"
6
8
"io"
7
9
"net"
8
10
"syscall"
@@ -16,7 +18,9 @@ import (
16
18
"github.com/docker/cli/internal/test/notary"
17
19
"github.com/docker/docker/api/types"
18
20
"github.com/docker/docker/api/types/container"
21
+ "github.com/docker/docker/api/types/image"
19
22
"github.com/docker/docker/api/types/network"
23
+ "github.com/docker/docker/pkg/jsonmessage"
20
24
specs "github.com/opencontainers/image-spec/specs-go/v1"
21
25
"github.com/spf13/pflag"
22
26
"gotest.tools/v3/assert"
@@ -217,6 +221,88 @@ func TestRunAttachTermination(t *testing.T) {
217
221
}
218
222
}
219
223
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 ,
231
+ platform * specs.Platform , containerName string ,
232
+ ) (container.CreateResponse , error ) {
233
+ select {
234
+ case <- ctx .Done ():
235
+ return container.CreateResponse {}, ctx .Err ()
236
+ default :
237
+ }
238
+ return container.CreateResponse {}, fakeNotFound {}
239
+ },
240
+ containerAttachFunc : func (ctx context.Context , containerID string , options container.AttachOptions ) (types.HijackedResponse , error ) {
241
+ return types.HijackedResponse {}, errors .New ("shouldn't try to attach to a container" )
242
+ },
243
+ imageCreateFunc : func (ctx context.Context , parentReference string , options image.CreateOptions ) (io.ReadCloser , error ) {
244
+ server , client := net .Pipe ()
245
+ t .Cleanup (func () {
246
+ _ = server .Close ()
247
+ })
248
+ go func () {
249
+ enc := json .NewEncoder (server )
250
+ for i := 0 ; i < 100 ; i ++ {
251
+ select {
252
+ case <- ctx .Done ():
253
+ assert .NilError (t , server .Close (), "failed to close imageCreateFunc server" )
254
+ return
255
+ default :
256
+ }
257
+ assert .NilError (t , enc .Encode (jsonmessage.JSONMessage {
258
+ Status : "Downloading" ,
259
+ ID : fmt .Sprintf ("id-%d" , i ),
260
+ TimeNano : time .Now ().UnixNano (),
261
+ Time : time .Now ().Unix (),
262
+ Progress : & jsonmessage.JSONProgress {
263
+ Current : int64 (i ),
264
+ Total : 100 ,
265
+ Start : 0 ,
266
+ },
267
+ }))
268
+ time .Sleep (100 * time .Millisecond )
269
+ }
270
+ }()
271
+ attachCh <- struct {}{}
272
+ return client , nil
273
+ },
274
+ Version : "1.30" ,
275
+ })
276
+
277
+ cmd := NewRunCommand (fakeCLI )
278
+ cmd .SetOut (io .Discard )
279
+ cmd .SetErr (io .Discard )
280
+ cmd .SetArgs ([]string {"foobar:latest" })
281
+
282
+ cmdErrC := make (chan error , 1 )
283
+ go func () {
284
+ cmdErrC <- cmd .ExecuteContext (ctx )
285
+ }()
286
+
287
+ select {
288
+ case <- time .After (5 * time .Second ):
289
+ t .Fatal ("imageCreateFunc was not called before the timeout" )
290
+ case <- attachCh :
291
+ }
292
+
293
+ cancel ()
294
+
295
+ select {
296
+ case cmdErr := <- cmdErrC :
297
+ assert .Equal (t , cmdErr , cli.StatusError {
298
+ StatusCode : 125 ,
299
+ Status : "docker: context canceled\n \n Run 'docker run --help' for more information" ,
300
+ })
301
+ case <- time .After (10 * time .Second ):
302
+ t .Fatal ("cmd did not return before the timeout" )
303
+ }
304
+ }
305
+
220
306
func TestRunCommandWithContentTrustErrors (t * testing.T ) {
221
307
testCases := []struct {
222
308
name string
0 commit comments