Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 129 additions & 37 deletions cmd/nerdctl/compose/compose_port_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,72 +18,166 @@ package compose

import (
"fmt"
"path/filepath"
"strconv"
"testing"

"github.com/containerd/nerdctl/mod/tigron/expect"
"github.com/containerd/nerdctl/mod/tigron/test"

"github.com/containerd/nerdctl/v2/pkg/testutil"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
"github.com/containerd/nerdctl/v2/pkg/testutil/portlock"
)

func TestComposePort(t *testing.T) {
base := testutil.NewBase(t)
const portCount = 2

var dockerComposeYAML = fmt.Sprintf(`
testCase := nerdtest.Setup()

testCase.Setup = func(data test.Data, helpers test.Helpers) {
for i := 0; i < portCount; i++ {
port, err := portlock.Acquire(0)
if err != nil {
helpers.T().Log(fmt.Sprintf("Failed to acquire port: %v", err))
helpers.T().FailNow()
}
data.Labels().Set(fmt.Sprintf("hostPort%d", i), strconv.Itoa(port))
}

dockerComposeYAML := fmt.Sprintf(`
services:
svc0:
image: %s
command: "sleep infinity"
ports:
- "12345:10000"
- "12346:10001/udp"
`, testutil.CommonImage)
- "%s:10000"
- "%s:10001/udp"
`, testutil.CommonImage, data.Labels().Get("hostPort0"), data.Labels().Get("hostPort1"))

compYamlPath := data.Temp().Save(dockerComposeYAML, "compose.yaml")
data.Labels().Set("composeYaml", compYamlPath)
projectName := filepath.Base(filepath.Dir(compYamlPath))
t.Logf("projectName=%q", projectName)

comp := testutil.NewComposeDir(t, dockerComposeYAML)
defer comp.CleanUp()
projectName := comp.ProjectName()
t.Logf("projectName=%q", projectName)
Comment on lines -45 to -46
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you write these in testCase.Setup ?
The same applies to other test functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review.
I've added these in testCase.Setup.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

helpers.Ensure("compose", "-f", compYamlPath, "up", "-d")
}

base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "-d").AssertOK()
defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK()
testCase.Cleanup = func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("compose", "-f", data.Temp().Path("compose.yaml"), "down", "-v")
for i := 0; i < portCount; i++ {
port, _ := strconv.Atoi(data.Labels().Get(fmt.Sprintf("hostPort%d", i)))
_ = portlock.Release(port)
}
}

// `port` should work for given port and protocol
base.ComposeCmd("-f", comp.YAMLFullPath(), "port", "svc0", "10000").AssertOutExactly("0.0.0.0:12345\n")
base.ComposeCmd("-f", comp.YAMLFullPath(), "port", "--protocol", "udp", "svc0", "10001").AssertOutExactly("0.0.0.0:12346\n")
testCase.SubTests = []*test.Case{
{
Description: "port should return host port for TCP",
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("compose", "-f", data.Labels().Get("composeYaml"), "port", "svc0", "10000")
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
ExitCode: expect.ExitCodeSuccess,
Output: expect.Equals(fmt.Sprintf("0.0.0.0:%s\n", data.Labels().Get("hostPort0"))),
}
},
},
{
Description: "port should return host port for UDP",
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("compose", "-f", data.Labels().Get("composeYaml"), "port", "--protocol", "udp", "svc0", "10001")
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
ExitCode: expect.ExitCodeSuccess,
Output: expect.Equals(fmt.Sprintf("0.0.0.0:%s\n", data.Labels().Get("hostPort1"))),
}
},
},
}

testCase.Run(t)
}

func TestComposePortFailure(t *testing.T) {
base := testutil.NewBase(t)
const portCount = 2

testCase := nerdtest.Setup()

var dockerComposeYAML = fmt.Sprintf(`
testCase.Setup = func(data test.Data, helpers test.Helpers) {
for i := 0; i < portCount; i++ {
port, err := portlock.Acquire(0)
if err != nil {
helpers.T().Log(fmt.Sprintf("Failed to acquire port: %v", err))
helpers.T().FailNow()
}
data.Labels().Set(fmt.Sprintf("hostPort%d", i), strconv.Itoa(port))
}

dockerComposeYAML := fmt.Sprintf(`
services:
svc0:
image: %s
command: "sleep infinity"
ports:
- "12345:10000"
- "12346:10001/udp"
`, testutil.CommonImage)

comp := testutil.NewComposeDir(t, dockerComposeYAML)
defer comp.CleanUp()
projectName := comp.ProjectName()
t.Logf("projectName=%q", projectName)

base.ComposeCmd("-f", comp.YAMLFullPath(), "up", "-d").AssertOK()
defer base.ComposeCmd("-f", comp.YAMLFullPath(), "down", "-v").AssertOK()

// `port` should fail if given port and protocol don't exist
base.ComposeCmd("-f", comp.YAMLFullPath(), "port", "svc0", "9999").AssertFail()
base.ComposeCmd("-f", comp.YAMLFullPath(), "port", "--protocol", "udp", "svc0", "10000").AssertFail()
base.ComposeCmd("-f", comp.YAMLFullPath(), "port", "--protocol", "tcp", "svc0", "10001").AssertFail()
- "%s:10000"
- "%s:10001/udp"
`, testutil.CommonImage, data.Labels().Get("hostPort0"), data.Labels().Get("hostPort1"))

compYamlPath := data.Temp().Save(dockerComposeYAML, "compose.yaml")
data.Labels().Set("composeYaml", compYamlPath)
projectName := filepath.Base(filepath.Dir(compYamlPath))
t.Logf("projectName=%q", projectName)

helpers.Ensure("compose", "-f", compYamlPath, "up", "-d")
}

testCase.Cleanup = func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("compose", "-f", data.Temp().Path("compose.yaml"), "down", "-v")
for i := 0; i < portCount; i++ {
port, _ := strconv.Atoi(data.Labels().Get(fmt.Sprintf("hostPort%d", i)))
_ = portlock.Release(port)
}
}

testCase.SubTests = []*test.Case{
{
Description: "port should fail for non-existent port",
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("compose", "-f", data.Labels().Get("composeYaml"), "port", "svc0", "9999")
},
Expected: test.Expects(expect.ExitCodeGenericFail, nil, nil),
},
{
Description: "port should fail for wrong protocol (UDP on TCP port)",
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("compose", "-f", data.Labels().Get("composeYaml"), "port", "--protocol", "udp", "svc0", "10000")
},
Expected: test.Expects(expect.ExitCodeGenericFail, nil, nil),
},
{
Description: "port should fail for wrong protocol (TCP on UDP port)",
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("compose", "-f", data.Labels().Get("composeYaml"), "port", "--protocol", "tcp", "svc0", "10001")
},
Expected: test.Expects(expect.ExitCodeGenericFail, nil, nil),
},
}

testCase.Run(t)
}

// TestComposeMultiplePorts tests whether it is possible to allocate a large
// number of ports. (https://github.com/containerd/nerdctl/issues/4027)
func TestComposeMultiplePorts(t *testing.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for noticing the improvements to the TestComposeMultiplePorts function.
Since this fix (L175 ~ L180 and L191 ~ L192) doesn't involve refactoring the existing tests in Tigron, should we split the commit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. I've split the commit as suggested.

var dockerComposeYAML = fmt.Sprintf(`
testCase := nerdtest.Setup()

testCase.NoParallel = true

testCase.Setup = func(data test.Data, helpers test.Helpers) {
dockerComposeYAML := fmt.Sprintf(`
services:
svc0:
image: %s
Expand All @@ -92,11 +186,10 @@ services:
- '32000-32060:32000-32060'
`, testutil.AlpineImage)

testCase := nerdtest.Setup()

testCase.Setup = func(data test.Data, helpers test.Helpers) {
compYamlPath := data.Temp().Save(dockerComposeYAML, "compose.yaml")
data.Labels().Set("composeYaml", compYamlPath)
projectName := filepath.Base(filepath.Dir(compYamlPath))
t.Logf("projectName=%q", projectName)

helpers.Ensure("compose", "-f", compYamlPath, "up", "-d")
}
Expand All @@ -108,7 +201,6 @@ services:
testCase.SubTests = []*test.Case{
{
Description: "Issue #4027 - Allocate a large number of ports.",
NoParallel: true,
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("compose", "-f", data.Labels().Get("composeYaml"), "port", "svc0", "32000")
},
Expand Down