-
Notifications
You must be signed in to change notification settings - Fork 781
refactor container_list_windows_test.go to use Tigron #4780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
must108
wants to merge
4
commits into
containerd:main
Choose a base branch
from
must108:containers-list-windows-test
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+160
−181
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,224 +23,203 @@ import ( | |
|
|
||
| "gotest.tools/v3/assert" | ||
|
|
||
| "github.com/containerd/nerdctl/mod/tigron/expect" | ||
| "github.com/containerd/nerdctl/mod/tigron/require" | ||
| "github.com/containerd/nerdctl/mod/tigron/test" | ||
| "github.com/containerd/nerdctl/mod/tigron/tig" | ||
|
|
||
| "github.com/containerd/nerdctl/v2/pkg/formatter" | ||
| "github.com/containerd/nerdctl/v2/pkg/strutil" | ||
| "github.com/containerd/nerdctl/v2/pkg/tabutil" | ||
| "github.com/containerd/nerdctl/v2/pkg/testutil" | ||
| "github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest" | ||
| ) | ||
|
|
||
| type psTestContainer struct { | ||
| name string | ||
| labels map[string]string | ||
| network string | ||
| } | ||
|
|
||
| func preparePsTestContainer(t *testing.T, identity string, restart bool, hyperv bool) (*testutil.Base, psTestContainer) { | ||
| base := testutil.NewBase(t) | ||
| func setupPsTestContainer(identity string, restart bool, hyperv bool) func(data test.Data, helpers test.Helpers) { | ||
| return func(data test.Data, helpers test.Helpers) { | ||
| helpers.Ensure("pull", "--quiet", testutil.NginxAlpineImage) | ||
| containerName := data.Identifier(identity) | ||
| data.Labels().Set("containerName", containerName) | ||
| // A container can have multiple labels. | ||
| testLabels := make(map[string]string) | ||
|
|
||
| for i := 0; i < 2; i++ { | ||
| k := fmt.Sprintf("%s-%d", data.Identifier(identity), i) | ||
| testLabels[k] = k | ||
| data.Labels().Set(fmt.Sprintf("label-key-%d", i), k) | ||
| data.Labels().Set(fmt.Sprintf("label-value-%d", i), k) | ||
| } | ||
|
|
||
| base.Cmd("pull", "--quiet", testutil.NginxAlpineImage).AssertOK() | ||
| args := []string{ | ||
| "run", | ||
| "-d", | ||
| } | ||
|
|
||
| testContainerName := testutil.Identifier(t) + identity | ||
| t.Cleanup(func() { | ||
| base.Cmd("rm", "-f", testContainerName).AssertOK() | ||
| }) | ||
| if hyperv { | ||
| args = append(args, "--isolation", "hyperv") | ||
| } | ||
|
|
||
| // A container can have multiple labels. | ||
| // Therefore, this test container has multiple labels to check it. | ||
| testLabels := make(map[string]string) | ||
| keys := []string{ | ||
| testutil.Identifier(t) + identity, | ||
| testutil.Identifier(t) + identity, | ||
| } | ||
| // fill the value of testLabels | ||
| for _, k := range keys { | ||
| testLabels[k] = k | ||
| } | ||
| args = append(args, | ||
| "--name", containerName, | ||
| "--label", formatter.FormatLabels(testLabels), | ||
| testutil.NginxAlpineImage, | ||
| ) | ||
|
|
||
| args := []string{ | ||
| "run", | ||
| "-d", | ||
| "--name", | ||
| testContainerName, | ||
| "--label", | ||
| formatter.FormatLabels(testLabels), | ||
| testutil.NginxAlpineImage, | ||
| } | ||
| if !restart { | ||
| args = append(args, "--restart=no") | ||
| } | ||
| if hyperv { | ||
| args = append(args[:3], args[1:]...) | ||
| args[1], args[2] = "--isolation", "hyperv" | ||
| } | ||
| if !restart { | ||
| args = append(args, "--restart=no") | ||
| } | ||
|
|
||
| base.Cmd(args...).AssertOK() | ||
| if restart { | ||
| base.EnsureContainerStarted(testContainerName) | ||
| helpers.Ensure(args...) | ||
| if restart { | ||
| nerdtest.EnsureContainerStarted(helpers, containerName) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return base, psTestContainer{ | ||
| name: testContainerName, | ||
| labels: testLabels, | ||
| network: testContainerName, | ||
| func cleanupPsTestContainer() func(data test.Data, helpers test.Helpers) { | ||
| return func(data test.Data, helpers test.Helpers) { | ||
| helpers.Anyhow("rm", "-f", data.Labels().Get("containerName")) | ||
| } | ||
| } | ||
|
|
||
| func TestListProcessContainer(t *testing.T) { | ||
| base, testContainer := preparePsTestContainer(t, "list", true, false) | ||
|
|
||
| // hope there are no tests running parallel | ||
| base.Cmd("ps", "-n", "1", "-s").AssertOutWithFunc(func(stdout string) error { | ||
| // An example of nerdctl/docker ps -n 1 -s | ||
| // CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE | ||
| // be8d386c991e docker.io/library/busybox:latest "top" 1 second ago Up c1 16.0 KiB (virtual 1.3 MiB) | ||
|
|
||
| lines := strings.Split(strings.TrimSpace(stdout), "\n") | ||
| if len(lines) < 2 { | ||
| return fmt.Errorf("expected at least 2 lines, got %d", len(lines)) | ||
| } | ||
|
|
||
| tab := tabutil.NewReader("CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES\tSIZE") | ||
| err := tab.ParseHeader(lines[0]) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to parse header: %v", err) | ||
| } | ||
|
|
||
| container, _ := tab.ReadRow(lines[1], "NAMES") | ||
| assert.Equal(t, container, testContainer.name) | ||
|
|
||
| image, _ := tab.ReadRow(lines[1], "IMAGE") | ||
| assert.Equal(t, image, testutil.NginxAlpineImage) | ||
|
|
||
| size, _ := tab.ReadRow(lines[1], "SIZE") | ||
|
|
||
| // there is some difference between nerdctl and docker in calculating the size of the container | ||
| expectedSize := "36.0 MiB (virtual " | ||
| testCase := nerdtest.Setup() | ||
| testCase.Setup = setupPsTestContainer("list", true, false) | ||
| testCase.Cleanup = cleanupPsTestContainer() | ||
| testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { | ||
| return helpers.Command("ps", "-s", "--filter", fmt.Sprintf("name=%s", data.Labels().Get("containerName"))) | ||
| } | ||
|
|
||
| if !strings.Contains(size, expectedSize) { | ||
| return fmt.Errorf("expect container size %s, but got %s", expectedSize, size) | ||
| testCase.Expected = func(data test.Data, helpers test.Helpers) *test.Expected { | ||
| return &test.Expected{ | ||
| ExitCode: expect.ExitCodeSuccess, | ||
| Output: func(stdout string, t tig.T) { | ||
| lines := strings.Split(strings.TrimSpace(stdout), "\n") | ||
| assert.Assert(t, len(lines) >= 2, fmt.Sprintf("expected at least 2 lines, got %d", len(lines))) | ||
| tab := tabutil.NewReader("CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES\tSIZE") | ||
| err := tab.ParseHeader(lines[0]) | ||
| assert.NilError(t, err, "failed to parse header") | ||
| container, _ := tab.ReadRow(lines[1], "NAMES") | ||
| assert.Equal(t, container, data.Labels().Get("containerName")) | ||
| image, _ := tab.ReadRow(lines[1], "IMAGE") | ||
| assert.Equal(t, image, testutil.NginxAlpineImage) | ||
| size, _ := tab.ReadRow(lines[1], "SIZE") | ||
| assert.Assert( | ||
| t, | ||
| strings.Contains(size, "(virtual"), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Originally, the string was checked to see if it contained |
||
| fmt.Sprintf("expect container size to contain '(virtual', but got %s", size), | ||
| ) | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| }) | ||
| testCase.Run(t) | ||
| } | ||
|
|
||
| func TestListHyperVContainer(t *testing.T) { | ||
| if !testutil.HyperVSupported() { | ||
| t.Skip("HyperV is not enabled, skipping test") | ||
| } | ||
|
|
||
| base, testContainer := preparePsTestContainer(t, "list", true, true) | ||
| inspect := base.InspectContainer(testContainer.name) | ||
| //check with HCS if the container is ineed a VM | ||
| isHypervContainer, err := testutil.HyperVContainer(inspect) | ||
| if err != nil { | ||
| t.Fatalf("unable to list HCS containers: %s", err) | ||
| testCase := nerdtest.Setup() | ||
| testCase.Require = nerdtest.HyperV | ||
|
|
||
| testCase.Setup = func(data test.Data, helpers test.Helpers) { | ||
| setupPsTestContainer("list", true, true)(data, helpers) | ||
| containerName := data.Labels().Get("containerName") | ||
| inspect := nerdtest.InspectContainer(helpers, containerName) | ||
| isHypervContainer, err := testutil.HyperVContainer(inspect) | ||
| assert.NilError(helpers.T(), err, "unable to list HCS containers") | ||
| assert.Assert(helpers.T(), isHypervContainer, "expected HyperV container") | ||
| } | ||
| assert.Assert(t, isHypervContainer, true) | ||
|
|
||
| // hope there are no tests running parallel | ||
| base.Cmd("ps", "-n", "1", "-s").AssertOutWithFunc(func(stdout string) error { | ||
| // An example of nerdctl/docker ps -n 1 -s | ||
| // CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE | ||
| // be8d386c991e docker.io/library/busybox:latest "top" 1 second ago Up c1 16.0 KiB (virtual 1.3 MiB) | ||
|
|
||
| lines := strings.Split(strings.TrimSpace(stdout), "\n") | ||
| if len(lines) < 2 { | ||
| return fmt.Errorf("expected at least 2 lines, got %d", len(lines)) | ||
| } | ||
|
|
||
| tab := tabutil.NewReader("CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES\tSIZE") | ||
| err := tab.ParseHeader(lines[0]) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to parse header: %v", err) | ||
| } | ||
|
|
||
| container, _ := tab.ReadRow(lines[1], "NAMES") | ||
| assert.Equal(t, container, testContainer.name) | ||
|
|
||
| image, _ := tab.ReadRow(lines[1], "IMAGE") | ||
| assert.Equal(t, image, testutil.NginxAlpineImage) | ||
| testCase.Cleanup = cleanupPsTestContainer() | ||
|
|
||
| size, _ := tab.ReadRow(lines[1], "SIZE") | ||
|
|
||
| // there is some difference between nerdctl and docker in calculating the size of the container | ||
| expectedSize := "72.0 MiB (virtual " | ||
| testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { | ||
| return helpers.Command("ps", "-s", "--filter", fmt.Sprintf("name=%s", data.Labels().Get("containerName"))) | ||
| } | ||
|
|
||
| if !strings.Contains(size, expectedSize) { | ||
| return fmt.Errorf("expect container size %s, but got %s", expectedSize, size) | ||
| testCase.Expected = func(data test.Data, helpers test.Helpers) *test.Expected { | ||
| return &test.Expected{ | ||
| ExitCode: expect.ExitCodeSuccess, | ||
| Output: func(stdout string, t tig.T) { | ||
| lines := strings.Split(strings.TrimSpace(stdout), "\n") | ||
| assert.Assert(t, len(lines) >= 2, fmt.Sprintf("expected at least 2 lines, got %d", len(lines))) | ||
| tab := tabutil.NewReader("CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES\tSIZE") | ||
| err := tab.ParseHeader(lines[0]) | ||
| assert.NilError(t, err, "failed to parse header") | ||
| container, _ := tab.ReadRow(lines[1], "NAMES") | ||
| assert.Equal(t, container, data.Labels().Get("containerName")) | ||
| image, _ := tab.ReadRow(lines[1], "IMAGE") | ||
| assert.Equal(t, image, testutil.NginxAlpineImage) | ||
| size, _ := tab.ReadRow(lines[1], "SIZE") | ||
| expectedSize := "72.0 MiB (virtual " | ||
| assert.Assert(t, strings.Contains(size, expectedSize), | ||
| fmt.Sprintf("expect container size %s, but got %s", expectedSize, size)) | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| }) | ||
| testCase.Run(t) | ||
| } | ||
|
|
||
| func TestListProcessContainerWideMode(t *testing.T) { | ||
| testutil.DockerIncompatible(t) | ||
| base, testContainer := preparePsTestContainer(t, "listWithMode", true, false) | ||
| testCase := nerdtest.Setup() | ||
| testCase.Require = require.Not(nerdtest.Docker) | ||
| testCase.Setup = setupPsTestContainer("listWithMode", true, false) | ||
| testCase.Cleanup = cleanupPsTestContainer() | ||
|
|
||
| // hope there are no tests running parallel | ||
| base.Cmd("ps", "-n", "1", "--format", "wide").AssertOutWithFunc(func(stdout string) error { | ||
|
|
||
| // An example of nerdctl ps --format wide | ||
| // CONTAINER ID IMAGE PLATFORM COMMAND CREATED STATUS PORTS NAMES RUNTIME SIZE | ||
| // 17181f208b61 docker.io/library/busybox:latest linux/amd64 "top" About an hour ago Up busybox-17181 io.containerd.runc.v2 16.0 KiB (virtual 1.3 MiB) | ||
|
|
||
| lines := strings.Split(strings.TrimSpace(stdout), "\n") | ||
| if len(lines) < 2 { | ||
| return fmt.Errorf("expected at least 2 lines, got %d", len(lines)) | ||
| } | ||
| testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { | ||
| return helpers.Command("ps", "--format", "wide", "--filter", fmt.Sprintf("name=%s", data.Labels().Get("containerName"))) | ||
| } | ||
|
|
||
| tab := tabutil.NewReader("CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES\tRUNTIME\tPLATFORM\tSIZE") | ||
| err := tab.ParseHeader(lines[0]) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to parse header: %v", err) | ||
| testCase.Expected = func(data test.Data, helpers test.Helpers) *test.Expected { | ||
| return &test.Expected{ | ||
| ExitCode: expect.ExitCodeSuccess, | ||
| Output: func(stdout string, t tig.T) { | ||
| lines := strings.Split(strings.TrimSpace(stdout), "\n") | ||
| assert.Assert(t, len(lines) >= 2, fmt.Sprintf("expected at least 2 lines, got %d", len(lines))) | ||
| tab := tabutil.NewReader("CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES\tRUNTIME\tPLATFORM\tSIZE") | ||
| err := tab.ParseHeader(lines[0]) | ||
| assert.NilError(t, err, "failed to parse header") | ||
| container, _ := tab.ReadRow(lines[1], "NAMES") | ||
| assert.Equal(t, container, data.Labels().Get("containerName")) | ||
| image, _ := tab.ReadRow(lines[1], "IMAGE") | ||
| assert.Equal(t, image, testutil.NginxAlpineImage) | ||
| runtime, _ := tab.ReadRow(lines[1], "RUNTIME") | ||
| assert.Equal(t, runtime, "io.containerd.runhcs.v1") | ||
| size, _ := tab.ReadRow(lines[1], "SIZE") | ||
| expectedSize := "36.0 MiB (virtual " | ||
| assert.Assert(t, strings.Contains(size, expectedSize), | ||
| fmt.Sprintf("expect container size %s, but got %s", expectedSize, size)) | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| container, _ := tab.ReadRow(lines[1], "NAMES") | ||
| assert.Equal(t, container, testContainer.name) | ||
|
|
||
| image, _ := tab.ReadRow(lines[1], "IMAGE") | ||
| assert.Equal(t, image, testutil.NginxAlpineImage) | ||
|
|
||
| runtime, _ := tab.ReadRow(lines[1], "RUNTIME") | ||
| assert.Equal(t, runtime, "io.containerd.runhcs.v1") | ||
|
|
||
| size, _ := tab.ReadRow(lines[1], "SIZE") | ||
| expectedSize := "36.0 MiB (virtual " | ||
| if !strings.Contains(size, expectedSize) { | ||
| return fmt.Errorf("expect container size %s, but got %s", expectedSize, size) | ||
| } | ||
| return nil | ||
| }) | ||
| testCase.Run(t) | ||
| } | ||
|
|
||
| func TestListProcessContainerWithLabels(t *testing.T) { | ||
| base, testContainer := preparePsTestContainer(t, "listWithLabels", true, false) | ||
| testCase := nerdtest.Setup() | ||
| testCase.Setup = setupPsTestContainer("listWithLabels", true, false) | ||
| testCase.Cleanup = cleanupPsTestContainer() | ||
|
|
||
| // hope there are no tests running parallel | ||
| base.Cmd("ps", "-n", "1", "--format", "{{.Labels}}").AssertOutWithFunc(func(stdout string) error { | ||
|
|
||
| // An example of nerdctl ps --format "{{.Labels}}" | ||
| // key1=value1,key2=value2,key3=value3 | ||
| lines := strings.Split(strings.TrimSpace(stdout), "\n") | ||
| if len(lines) != 1 { | ||
| return fmt.Errorf("expected 1 line, got %d", len(lines)) | ||
| } | ||
|
|
||
| // check labels using map | ||
| // 1. the results has no guarantee to show the same order. | ||
| // 2. the results has no guarantee to show only configured labels. | ||
| labelsMap, err := strutil.ParseCSVMap(lines[0]) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to parse labels: %v", err) | ||
| } | ||
| testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { | ||
| return helpers.Command("ps", "--format", "{{.Labels}}", "--filter", fmt.Sprintf("name=%s", data.Labels().Get("containerName"))) | ||
| } | ||
|
|
||
| for i := range testContainer.labels { | ||
| if value, ok := labelsMap[i]; ok { | ||
| assert.Equal(t, value, testContainer.labels[i]) | ||
| } | ||
| testCase.Expected = func(data test.Data, helpers test.Helpers) *test.Expected { | ||
| return &test.Expected{ | ||
| ExitCode: expect.ExitCodeSuccess, | ||
| Output: func(stdout string, t tig.T) { | ||
| lines := strings.Split(strings.TrimSpace(stdout), "\n") | ||
| assert.Assert(t, len(lines) == 1, fmt.Sprintf("expected 1 line, got %d", len(lines))) | ||
| labelsMap, err := strutil.ParseCSVMap(lines[0]) | ||
| assert.NilError(t, err, "failed to parse labels") | ||
|
|
||
| for idx := 0; idx < 2; idx++ { | ||
| labelKey := data.Labels().Get(fmt.Sprintf("label-key-%d", idx)) | ||
| labelValue := data.Labels().Get(fmt.Sprintf("label-value-%d", idx)) | ||
|
|
||
| if value, ok := labelsMap[labelKey]; ok { | ||
| assert.Equal(t, value, labelValue) | ||
| } | ||
| } | ||
| }, | ||
| } | ||
| return nil | ||
| }) | ||
| } | ||
| testCase.Run(t) | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we move the
--restart=noappend above the --name / image block? Otherwise, when restart is false, the container exits immediately instead of running with --restart=no.