@@ -19,9 +19,9 @@ package compose
1919import (
2020 "fmt"
2121 "io"
22+ "strconv"
2223 "strings"
2324 "testing"
24- "time"
2525
2626 "gotest.tools/v3/assert"
2727
@@ -33,6 +33,7 @@ import (
3333 "github.com/containerd/nerdctl/v2/pkg/testutil"
3434 "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
3535 "github.com/containerd/nerdctl/v2/pkg/testutil/nettestutil"
36+ "github.com/containerd/nerdctl/v2/pkg/testutil/portlock"
3637 "github.com/containerd/nerdctl/v2/pkg/testutil/testregistry"
3738)
3839
@@ -113,123 +114,117 @@ services:
113114}
114115
115116func TestComposeRunWithServicePorts (t * testing.T ) {
116- base := testutil .NewBase (t )
117- // specify the name of container in order to remove
118- // TODO: when `compose rm` is implemented, replace it.
119- containerName := testutil .Identifier (t )
117+ testCase := nerdtest .Setup ()
120118
121- dockerComposeYAML := fmt .Sprintf (`
119+ testCase .Setup = func (data test.Data , helpers test.Helpers ) {
120+ hostPort , err := portlock .Acquire (0 )
121+ assert .NilError (helpers .T (), err )
122+ data .Labels ().Set ("hostPort" , strconv .Itoa (hostPort ))
123+
124+ dockerComposeYAML := fmt .Sprintf (`
122125services:
123126 web:
124127 image: %s
125128 ports:
126- - 8080 :80
127- ` , testutil .NginxAlpineImage )
129+ - %d :80
130+ ` , testutil .NginxAlpineImage , hostPort )
128131
129- comp := testutil .NewComposeDir (t , dockerComposeYAML )
130- defer comp .CleanUp ()
131- projectName := comp .ProjectName ()
132- t .Logf ("projectName=%q" , projectName )
133- defer base .ComposeCmd ("-f" , comp .YAMLFullPath (), "down" , "-v" ).Run ()
132+ data .Temp ().Save (dockerComposeYAML , "compose.yaml" )
133+ cmd := helpers .Command (
134+ "compose" ,
135+ "-f" ,
136+ data .Temp ().Path ("compose.yaml" ),
137+ "run" ,
138+ "--service-ports" ,
139+ "--name" ,
140+ data .Identifier (),
141+ "web" ,
142+ )
143+ cmd .WithPseudoTTY ()
144+ cmd .Background ()
145+ nerdtest .EnsureContainerStarted (helpers , data .Identifier ())
146+ }
134147
135- defer base .Cmd ("rm" , "-f" , "-v" , containerName ).Run ()
136- go func () {
137- // unbuffer(1) emulates tty, which is required by `nerdctl run -t`.
138- // unbuffer(1) can be installed with `apt-get install expect`.
139- unbuffer := []string {"unbuffer" }
140- base .ComposeCmdWithHelper (unbuffer , "-f" , comp .YAMLFullPath (),
141- "run" , "--service-ports" , "--name" , containerName , "web" ).Run ()
142- }()
143-
144- checkNginx := func () error {
145- resp , err := nettestutil .HTTPGet ("http://127.0.0.1:8080" , 5 , false )
146- if err != nil {
147- return err
148- }
149- respBody , err := io .ReadAll (resp .Body )
150- if err != nil {
151- return err
152- }
153- if ! strings .Contains (string (respBody ), testutil .NginxAlpineIndexHTMLSnippet ) {
154- t .Logf ("respBody=%q" , respBody )
155- return fmt .Errorf ("respBody does not contain %q" , testutil .NginxAlpineIndexHTMLSnippet )
148+ testCase .Cleanup = func (data test.Data , helpers test.Helpers ) {
149+ helpers .Anyhow ("compose" , "-f" , data .Temp ().Path ("compose.yaml" ), "rm" , "-f" , "-v" )
150+ helpers .Anyhow ("compose" , "-f" , data .Temp ().Path ("compose.yaml" ), "down" , "-v" )
151+ if p := data .Labels ().Get ("hostPort" ); p != "" {
152+ if port , err := strconv .Atoi (p ); err == nil {
153+ _ = portlock .Release (port )
154+ }
156155 }
157- return nil
158156 }
159- var nginxWorking bool
160- for i := 0 ; i < 30 ; i ++ {
161- t .Logf ("(retry %d)" , i )
162- err := checkNginx ()
163- if err == nil {
164- nginxWorking = true
165- break
157+
158+ testCase .Expected = func (data test.Data , helpers test.Helpers ) * test.Expected {
159+ return & test.Expected {
160+ Output : func (stdout string , t tig.T ) {
161+ host := fmt .Sprintf ("http://127.0.0.1:%s" , data .Labels ().Get ("hostPort" ))
162+ resp , err := nettestutil .HTTPGet (host , 30 , false )
163+ assert .NilError (t , err )
164+ respBody , err := io .ReadAll (resp .Body )
165+ assert .NilError (t , err )
166+ assert .Assert (t , strings .Contains (string (respBody ), testutil .NginxAlpineIndexHTMLSnippet ))
167+ },
166168 }
167- t .Log (err )
168- time .Sleep (3 * time .Second )
169- }
170- if ! nginxWorking {
171- t .Fatal ("nginx is not working" )
172169 }
173- t .Log ("nginx seems functional" )
170+
171+ testCase .Run (t )
174172}
175173
176174func TestComposeRunWithPublish (t * testing.T ) {
177- base := testutil .NewBase (t )
178- // specify the name of container in order to remove
179- // TODO: when `compose rm` is implemented, replace it.
180- containerName := testutil .Identifier (t )
175+ testCase := nerdtest .Setup ()
181176
182- dockerComposeYAML := fmt .Sprintf (`
177+ testCase .Setup = func (data test.Data , helpers test.Helpers ) {
178+ hostPort , err := portlock .Acquire (0 )
179+ assert .NilError (helpers .T (), err )
180+ data .Labels ().Set ("hostPort" , strconv .Itoa (hostPort ))
181+
182+ dockerComposeYAML := fmt .Sprintf (`
183183services:
184184 web:
185185 image: %s
186186` , testutil .NginxAlpineImage )
187187
188- comp := testutil .NewComposeDir (t , dockerComposeYAML )
189- defer comp .CleanUp ()
190- projectName := comp .ProjectName ()
191- t .Logf ("projectName=%q" , projectName )
192- defer base .ComposeCmd ("-f" , comp .YAMLFullPath (), "down" , "-v" ).Run ()
188+ data .Temp ().Save (dockerComposeYAML , "compose.yaml" )
189+ cmd := helpers .Command (
190+ "compose" ,
191+ "-f" ,
192+ data .Temp ().Path ("compose.yaml" ),
193+ "run" ,
194+ "--publish" , fmt .Sprintf ("%d:80" , hostPort ),
195+ "--name" ,
196+ data .Identifier (),
197+ "web" ,
198+ )
199+ cmd .WithPseudoTTY ()
200+ cmd .Background ()
201+ nerdtest .EnsureContainerStarted (helpers , data .Identifier ())
202+ }
193203
194- defer base .Cmd ("rm" , "-f" , "-v" , containerName ).Run ()
195- go func () {
196- // unbuffer(1) emulates tty, which is required by `nerdctl run -t`.
197- // unbuffer(1) can be installed with `apt-get install expect`.
198- unbuffer := []string {"unbuffer" }
199- base .ComposeCmdWithHelper (unbuffer , "-f" , comp .YAMLFullPath (),
200- "run" , "--publish" , "8080:80" , "--name" , containerName , "web" ).Run ()
201- }()
202-
203- checkNginx := func () error {
204- resp , err := nettestutil .HTTPGet ("http://127.0.0.1:8080" , 5 , false )
205- if err != nil {
206- return err
207- }
208- respBody , err := io .ReadAll (resp .Body )
209- if err != nil {
210- return err
211- }
212- if ! strings .Contains (string (respBody ), testutil .NginxAlpineIndexHTMLSnippet ) {
213- t .Logf ("respBody=%q" , respBody )
214- return fmt .Errorf ("respBody does not contain %q" , testutil .NginxAlpineIndexHTMLSnippet )
204+ testCase .Cleanup = func (data test.Data , helpers test.Helpers ) {
205+ helpers .Anyhow ("compose" , "-f" , data .Temp ().Path ("compose.yaml" ), "rm" , "-f" , "-v" )
206+ helpers .Anyhow ("compose" , "-f" , data .Temp ().Path ("compose.yaml" ), "down" , "-v" )
207+ if p := data .Labels ().Get ("hostPort" ); p != "" {
208+ if port , err := strconv .Atoi (p ); err == nil {
209+ _ = portlock .Release (port )
210+ }
215211 }
216- return nil
217212 }
218- var nginxWorking bool
219- for i := 0 ; i < 30 ; i ++ {
220- t .Logf ("(retry %d)" , i )
221- err := checkNginx ()
222- if err == nil {
223- nginxWorking = true
224- break
213+
214+ testCase .Expected = func (data test.Data , helpers test.Helpers ) * test.Expected {
215+ return & test.Expected {
216+ Output : func (stdout string , t tig.T ) {
217+ host := fmt .Sprintf ("http://127.0.0.1:%s" , data .Labels ().Get ("hostPort" ))
218+ resp , err := nettestutil .HTTPGet (host , 30 , false )
219+ assert .NilError (t , err )
220+ respBody , err := io .ReadAll (resp .Body )
221+ assert .NilError (t , err )
222+ assert .Assert (t , strings .Contains (string (respBody ), testutil .NginxAlpineIndexHTMLSnippet ))
223+ },
225224 }
226- t .Log (err )
227- time .Sleep (3 * time .Second )
228- }
229- if ! nginxWorking {
230- t .Fatal ("nginx is not working" )
231225 }
232- t .Log ("nginx seems functional" )
226+
227+ testCase .Run (t )
233228}
234229
235230func TestComposeRunWithEnv (t * testing.T ) {
0 commit comments