@@ -24,81 +24,99 @@ import (
2424 "gotest.tools/v3/assert"
2525
2626 "github.com/containerd/nerdctl/v2/pkg/testutil"
27+ "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
28+ "github.com/containerd/nerdctl/v2/pkg/testutil/test"
2729)
2830
29- // skipAttachForDocker should be called by attach-related tests that assert 'read detach keys' in stdout.
30- func skipAttachForDocker (t * testing.T ) {
31- t .Helper ()
32- if testutil .GetTarget () == testutil .Docker {
33- t .Skip ("When detaching from a container, for a session started with 'docker attach'" +
34- ", it prints 'read escape sequence', but for one started with 'docker (run|start)', it prints nothing." +
35- " However, the flag is called '--detach-keys' in all cases" +
36- ", so nerdctl prints 'read detach keys' for all cases" +
37- ", and that's why this test is skipped for Docker." )
38- }
39- }
40-
41- // prepareContainerToAttach spins up a container (entrypoint = shell) with `-it` and detaches from it
42- // so that it can be re-attached to later.
43- func prepareContainerToAttach (base * testutil.Base , containerName string ) {
44- opts := []func (* testutil.Cmd ){
45- testutil .WithStdin (testutil .NewDelayOnceReader (bytes .NewReader (
31+ func TestAttachDetachKeys (t * testing.T ) {
32+ testCase := nerdtest .Setup ()
33+
34+ setup := func (data test.Data , helpers test.Helpers ) {
35+ // unbuffer(1) emulates tty, which is required by `nerdctl run -t`.
36+ // unbuffer(1) can be installed with `apt-get install expect`.
37+ //
38+ // "-p" is needed because we need unbuffer to read from stdin, and from [1]:
39+ // "Normally, unbuffer does not read from stdin. This simplifies use of unbuffer in some situations.
40+ // To use unbuffer in a pipeline, use the -p flag."
41+ //
42+ // [1] https://linux.die.net/man/1/unbuffer
43+
44+ si := testutil .NewDelayOnceReader (bytes .NewReader (
4645 []byte {16 , 17 }, // ctrl+p,ctrl+q, see https://www.physics.udel.edu/~watson/scen103/ascii.html
47- ))),
46+ ))
47+
48+ cmd := helpers .
49+ Command ("run" , "-it" , "--name" , data .Identifier (), testutil .CommonImage )
50+ cmd .WithWrapper ("unbuffer" , "-p" )
51+ cmd .WithStdin (si )
52+ cmd .Run (& test.Expected {
53+ Output : test .All (
54+ // NOTE:
55+ // When detaching from a container, for a session started with 'docker attach',
56+ // it prints 'read escape sequence', but for one started with 'docker (run|start)', it prints nothing.
57+ // However, the flag is called '--detach-keys' in all cases, and nerdctl does print read detach keys
58+ // in all cases.
59+ // Disabling the contains test here allow both cli to run the test.
60+ // test.Contains("read detach keys"),
61+ func (stdout string , info string , t * testing.T ) {
62+ container := nerdtest .InspectContainer (helpers , data .Identifier ())
63+ assert .Equal (t , container .State .Running , true , info )
64+ }),
65+ })
4866 }
49- // unbuffer(1) emulates tty, which is required by `nerdctl run -t`.
50- // unbuffer(1) can be installed with `apt-get install expect`.
51- //
52- // "-p" is needed because we need unbuffer to read from stdin, and from [1]:
53- // "Normally, unbuffer does not read from stdin. This simplifies use of unbuffer in some situations.
54- // To use unbuffer in a pipeline, use the -p flag."
55- //
56- // [1] https://linux.die.net/man/1/unbuffer
57- base .CmdWithHelper ([]string {"unbuffer" , "-p" }, "run" , "-it" , "--name" , containerName , testutil .CommonImage ).
58- CmdOption (opts ... ).AssertOutContains ("read detach keys" )
59- container := base .InspectContainer (containerName )
60- assert .Equal (base .T , container .State .Running , true )
61- }
62-
63- func TestAttach (t * testing.T ) {
64- t .Parallel ()
65-
66- skipAttachForDocker (t )
67-
68- base := testutil .NewBase (t )
69- containerName := testutil .Identifier (t )
7067
71- defer base .Cmd ("container" , "rm" , "-f" , containerName ).AssertOK ()
72- prepareContainerToAttach (base , containerName )
73-
74- opts := []func (* testutil.Cmd ){
75- testutil .WithStdin (testutil .NewDelayOnceReader (strings .NewReader ("expr 1 + 1\n exit\n " ))),
68+ testCase .SubTests = []* test.Case {
69+ {
70+ Description : "TestAttachDefaultKeys" ,
71+ Require : test .Binary ("unbuffer" ),
72+ Cleanup : func (data test.Data , helpers test.Helpers ) {
73+ helpers .Anyhow ("container" , "rm" , "-f" , data .Identifier ())
74+ },
75+ Setup : setup ,
76+ Command : func (data test.Data , helpers test.Helpers ) test.TestableCommand {
77+ si := testutil .NewDelayOnceReader (strings .NewReader ("expr 1 + 1\n exit\n " ))
78+ // `unbuffer -p` returns 0 even if the underlying nerdctl process returns a non-zero exit code,
79+ // so the exit code cannot be easily tested here.
80+ cmd := helpers .Command ("attach" , data .Identifier ())
81+ cmd .WithStdin (si )
82+ cmd .WithWrapper ("unbuffer" , "-p" )
83+
84+ return cmd
85+ },
86+ Expected : func (data test.Data , helpers test.Helpers ) * test.Expected {
87+ return & test.Expected {
88+ Output : func (stdout string , info string , t * testing.T ) {
89+ container := nerdtest .InspectContainer (helpers , data .Identifier ())
90+ assert .Equal (t , container .State .Running , false , info )
91+ },
92+ }
93+ },
94+ },
95+ {
96+ Description : "TestAttachCustomKeys" ,
97+ Require : test .Binary ("unbuffer" ),
98+ Cleanup : func (data test.Data , helpers test.Helpers ) {
99+ helpers .Anyhow ("container" , "rm" , "-f" , data .Identifier ())
100+ },
101+ Setup : setup ,
102+ Command : func (data test.Data , helpers test.Helpers ) test.TestableCommand {
103+ si := testutil .NewDelayOnceReader (bytes .NewReader ([]byte {1 , 2 }))
104+ cmd := helpers .
105+ Command ("attach" , "--detach-keys=ctrl-a,ctrl-b" , data .Identifier ())
106+ cmd .WithStdin (si )
107+ cmd .WithWrapper ("unbuffer" , "-p" )
108+ return cmd
109+ },
110+ Expected : func (data test.Data , helpers test.Helpers ) * test.Expected {
111+ return & test.Expected {
112+ Output : func (stdout string , info string , t * testing.T ) {
113+ container := nerdtest .InspectContainer (helpers , data .Identifier ())
114+ assert .Equal (t , container .State .Running , true , info )
115+ },
116+ }
117+ },
118+ },
76119 }
77- // `unbuffer -p` returns 0 even if the underlying nerdctl process returns a non-zero exit code,
78- // so the exit code cannot be easily tested here.
79- base .CmdWithHelper ([]string {"unbuffer" , "-p" }, "attach" , containerName ).CmdOption (opts ... ).AssertOutContains ("2" )
80- container := base .InspectContainer (containerName )
81- assert .Equal (base .T , container .State .Running , false )
82- }
83-
84- func TestAttachDetachKeys (t * testing.T ) {
85- t .Parallel ()
86120
87- skipAttachForDocker (t )
88-
89- base := testutil .NewBase (t )
90- containerName := testutil .Identifier (t )
91-
92- defer base .Cmd ("container" , "rm" , "-f" , containerName ).AssertOK ()
93- prepareContainerToAttach (base , containerName )
94-
95- opts := []func (* testutil.Cmd ){
96- testutil .WithStdin (testutil .NewDelayOnceReader (bytes .NewReader (
97- []byte {1 , 2 }, // https://www.physics.udel.edu/~watson/scen103/ascii.html
98- ))),
99- }
100- base .CmdWithHelper ([]string {"unbuffer" , "-p" }, "attach" , "--detach-keys=ctrl-a,ctrl-b" , containerName ).
101- CmdOption (opts ... ).AssertOutContains ("read detach keys" )
102- container := base .InspectContainer (containerName )
103- assert .Equal (base .T , container .State .Running , true )
121+ testCase .Run (t )
104122}
0 commit comments