pkg/cri/sbserver: sub-test uses array and capture range var

Using array to build sub-tests is to avoid random pick. The shuffle
thing should be handled by go-test framework. And we should capture
range var before runing sub-test.

Signed-off-by: Wei Fu <fuweid89@gmail.com>
This commit is contained in:
Wei Fu
2023-04-15 21:53:01 +08:00
parent ffc70c45c4
commit 8bcfdda39b
27 changed files with 973 additions and 493 deletions

View File

@@ -29,32 +29,39 @@ import (
func TestGetCgroupsPath(t *testing.T) {
testID := "test-id"
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
cgroupsParent string
expected string
}{
"should support regular cgroup path": {
{
desc: "should support regular cgroup path",
cgroupsParent: "/a/b",
expected: "/a/b/test-id",
},
"should support systemd cgroup path": {
{
desc: "should support systemd cgroup path",
cgroupsParent: "/a.slice/b.slice",
expected: "b.slice:cri-containerd:test-id",
},
"should support tailing slash for regular cgroup path": {
{
desc: "should support tailing slash for regular cgroup path",
cgroupsParent: "/a/b/",
expected: "/a/b/test-id",
},
"should support tailing slash for systemd cgroup path": {
{
desc: "should support tailing slash for systemd cgroup path",
cgroupsParent: "/a.slice/b.slice/",
expected: "b.slice:cri-containerd:test-id",
},
"should treat root cgroup as regular cgroup path": {
{
desc: "should treat root cgroup as regular cgroup path",
cgroupsParent: "/",
expected: "/test-id",
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
got := getCgroupsPath(test.cgroupsParent, testID)
assert.Equal(t, test.expected, got)
})

View File

@@ -29,18 +29,21 @@ func TestInitSelinuxOpts(t *testing.T) {
t.Skip("selinux is not enabled")
}
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
selinuxOpt *runtime.SELinuxOption
processLabel string
mountLabel string
expectErr bool
}{
"Should return empty strings for processLabel and mountLabel when selinuxOpt is nil": {
{
desc: "Should return empty strings for processLabel and mountLabel when selinuxOpt is nil",
selinuxOpt: nil,
processLabel: ".*:c[0-9]{1,3},c[0-9]{1,3}",
mountLabel: ".*:c[0-9]{1,3},c[0-9]{1,3}",
},
"Should overlay fields on processLabel when selinuxOpt has been initialized partially": {
{
desc: "Should overlay fields on processLabel when selinuxOpt has been initialized partially",
selinuxOpt: &runtime.SELinuxOption{
User: "",
Role: "user_r",
@@ -50,7 +53,8 @@ func TestInitSelinuxOpts(t *testing.T) {
processLabel: "system_u:user_r:(container_file_t|svirt_lxc_net_t):s0:c1,c2",
mountLabel: "system_u:object_r:(container_file_t|svirt_sandbox_file_t):s0:c1,c2",
},
"Should be resolved correctly when selinuxOpt has been initialized completely": {
{
desc: "Should be resolved correctly when selinuxOpt has been initialized completely",
selinuxOpt: &runtime.SELinuxOption{
User: "user_u",
Role: "user_r",
@@ -60,7 +64,8 @@ func TestInitSelinuxOpts(t *testing.T) {
processLabel: "user_u:user_r:user_t:s0:c1,c2",
mountLabel: "user_u:object_r:(container_file_t|svirt_sandbox_file_t):s0:c1,c2",
},
"Should be resolved correctly when selinuxOpt has been initialized with level=''": {
{
desc: "Should be resolved correctly when selinuxOpt has been initialized with level=''",
selinuxOpt: &runtime.SELinuxOption{
User: "user_u",
Role: "user_r",
@@ -70,7 +75,8 @@ func TestInitSelinuxOpts(t *testing.T) {
processLabel: "user_u:user_r:user_t:s0:c[0-9]{1,3},c[0-9]{1,3}",
mountLabel: "user_u:object_r:(container_file_t|svirt_sandbox_file_t):s0",
},
"Should return error when the format of 'level' is not correct": {
{
desc: "Should return error when the format of 'level' is not correct",
selinuxOpt: &runtime.SELinuxOption{
User: "user_u",
Role: "user_r",
@@ -80,7 +86,8 @@ func TestInitSelinuxOpts(t *testing.T) {
expectErr: true,
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
processLabel, mountLabel, err := initLabelsFromOpt(test.selinuxOpt)
if test.expectErr {
assert.Error(t, err)
@@ -93,59 +100,75 @@ func TestInitSelinuxOpts(t *testing.T) {
}
func TestCheckSelinuxLevel(t *testing.T) {
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
level string
expectNoMatch bool
}{
"s0": {
{
desc: "s0",
level: "s0",
},
"s0-s0": {
{
desc: "s0-s0",
level: "s0-s0",
},
"s0:c0": {
{
desc: "s0:c0",
level: "s0:c0",
},
"s0:c0.c3": {
{
desc: "s0:c0.c3",
level: "s0:c0.c3",
},
"s0:c0,c3": {
{
desc: "s0:c0,c3",
level: "s0:c0,c3",
},
"s0-s0:c0,c3": {
{
desc: "s0-s0:c0,c3",
level: "s0-s0:c0,c3",
},
"s0-s0:c0,c3.c6": {
{
desc: "s0-s0:c0,c3.c6",
level: "s0-s0:c0,c3.c6",
},
"s0-s0:c0,c3.c6,c8.c10": {
{
desc: "s0-s0:c0,c3.c6,c8.c10",
level: "s0-s0:c0,c3.c6,c8.c10",
},
"s0-s0:c0,c3.c6,c8,c10": {
{
desc: "s0-s0:c0,c3.c6,c8,c10",
level: "s0-s0:c0,c3.c6",
},
"s0,c0,c3": {
{
desc: "s0,c0,c3",
level: "s0,c0,c3",
expectNoMatch: true,
},
"s0:c0.c3.c6": {
{
desc: "s0:c0.c3.c6",
level: "s0:c0.c3.c6",
expectNoMatch: true,
},
"s0-s0,c0,c3": {
{
desc: "s0-s0,c0,c3",
level: "s0-s0,c0,c3",
expectNoMatch: true,
},
"s0-s0:c0.c3.c6": {
{
desc: "s0-s0:c0.c3.c6",
level: "s0-s0:c0.c3.c6",
expectNoMatch: true,
},
"s0-s0:c0,c3.c6.c8": {
{
desc: "s0-s0:c0,c3.c6.c8",
level: "s0-s0:c0,c3.c6.c8",
expectNoMatch: true,
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
err := checkSelinuxLevel(test.level)
if test.expectNoMatch {
assert.Error(t, err)

View File

@@ -31,35 +31,41 @@ import (
func TestGetRepoDigestAndTag(t *testing.T) {
digest := imagedigest.Digest("sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582")
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
ref string
schema1 bool
expectedRepoDigest string
expectedRepoTag string
}{
"repo tag should be empty if original ref has no tag": {
{
desc: "repo tag should be empty if original ref has no tag",
ref: "gcr.io/library/busybox@" + digest.String(),
expectedRepoDigest: "gcr.io/library/busybox@" + digest.String(),
},
"repo tag should not be empty if original ref has tag": {
{
desc: "repo tag should not be empty if original ref has tag",
ref: "gcr.io/library/busybox:latest",
expectedRepoDigest: "gcr.io/library/busybox@" + digest.String(),
expectedRepoTag: "gcr.io/library/busybox:latest",
},
"repo digest should be empty if original ref is schema1 and has no digest": {
{
desc: "repo digest should be empty if original ref is schema1 and has no digest",
ref: "gcr.io/library/busybox:latest",
schema1: true,
expectedRepoDigest: "",
expectedRepoTag: "gcr.io/library/busybox:latest",
},
"repo digest should not be empty if original ref is schema1 but has digest": {
{
desc: "repo digest should not be empty if original ref is schema1 but has digest",
ref: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594",
schema1: true,
expectedRepoDigest: "gcr.io/library/busybox@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59594",
expectedRepoTag: "",
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
named, err := docker.ParseDockerRef(test.ref)
assert.NoError(t, err)
repoDigest, repoTag := getRepoDigestAndTag(named, digest, test.schema1)
@@ -109,18 +115,21 @@ func TestParseImageReferences(t *testing.T) {
}
func TestEnvDeduplication(t *testing.T) {
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
existing []string
kv [][2]string
expected []string
}{
"single env": {
{
desc: "single env",
kv: [][2]string{
{"a", "b"},
},
expected: []string{"a=b"},
},
"multiple envs": {
{
desc: "multiple envs",
kv: [][2]string{
{"a", "b"},
{"c", "d"},
@@ -132,7 +141,8 @@ func TestEnvDeduplication(t *testing.T) {
"e=f",
},
},
"env override": {
{
desc: "env override",
kv: [][2]string{
{"k1", "v1"},
{"k2", "v2"},
@@ -148,7 +158,8 @@ func TestEnvDeduplication(t *testing.T) {
"k4=v6",
},
},
"existing env": {
{
desc: "existing env",
existing: []string{
"k1=v1",
"k2=v2",
@@ -167,7 +178,8 @@ func TestEnvDeduplication(t *testing.T) {
},
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
var spec runtimespec.Spec
if len(test.existing) > 0 {
spec.Process = &runtimespec.Process{
@@ -183,17 +195,20 @@ func TestEnvDeduplication(t *testing.T) {
}
func TestPassThroughAnnotationsFilter(t *testing.T) {
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
podAnnotations map[string]string
runtimePodAnnotations []string
passthroughAnnotations map[string]string
}{
"should support direct match": {
{
desc: "should support direct match",
podAnnotations: map[string]string{"c": "d", "d": "e"},
runtimePodAnnotations: []string{"c"},
passthroughAnnotations: map[string]string{"c": "d"},
},
"should support wildcard match": {
{
desc: "should support wildcard match",
podAnnotations: map[string]string{
"t.f": "j",
"z.g": "o",
@@ -208,7 +223,8 @@ func TestPassThroughAnnotationsFilter(t *testing.T) {
"y.ca": "b",
},
},
"should support wildcard match all": {
{
desc: "should support wildcard match all",
podAnnotations: map[string]string{
"t.f": "j",
"z.g": "o",
@@ -225,7 +241,8 @@ func TestPassThroughAnnotationsFilter(t *testing.T) {
"y": "b",
},
},
"should support match including path separator": {
{
desc: "should support match including path separator",
podAnnotations: map[string]string{
"matchend.com/end": "1",
"matchend.com/end1": "2",
@@ -284,7 +301,8 @@ func TestPassThroughAnnotationsFilter(t *testing.T) {
},
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
passthroughAnnotations := getPassthroughAnnotations(test.podAnnotations, test.runtimePodAnnotations)
assert.Equal(t, test.passthroughAnnotations, passthroughAnnotations)
})

View File

@@ -106,12 +106,14 @@ func getRunPodSandboxTestData() (*runtime.PodSandboxConfig, *imagespec.ImageConf
func TestLinuxSandboxContainerSpec(t *testing.T) {
testID := "test-id"
nsPath := "test-cni"
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
configChange func(*runtime.PodSandboxConfig)
specCheck func(*testing.T, *runtimespec.Spec)
expectErr bool
}{
"spec should reflect original config": {
{
desc: "spec should reflect original config",
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
// runtime spec should have expected namespaces enabled by default.
require.NotNil(t, spec.Linux)
@@ -132,7 +134,8 @@ func TestLinuxSandboxContainerSpec(t *testing.T) {
assert.Contains(t, spec.Linux.Sysctl["net.ipv4.ping_group_range"], "0 2147483647")
},
},
"host namespace": {
{
desc: "host namespace",
configChange: func(c *runtime.PodSandboxConfig) {
c.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
NamespaceOptions: &runtime.NamespaceOption{
@@ -161,7 +164,8 @@ func TestLinuxSandboxContainerSpec(t *testing.T) {
assert.NotContains(t, spec.Linux.Sysctl["net.ipv4.ping_group_range"], "0 2147483647")
},
},
"should set supplemental groups correctly": {
{
desc: "should set supplemental groups correctly",
configChange: func(c *runtime.PodSandboxConfig) {
c.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
SupplementalGroups: []int64{1111, 2222},
@@ -173,7 +177,8 @@ func TestLinuxSandboxContainerSpec(t *testing.T) {
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(2222))
},
},
"should overwrite default sysctls": {
{
desc: "should overwrite default sysctls",
configChange: func(c *runtime.PodSandboxConfig) {
c.Linux.Sysctls = map[string]string{
"net.ipv4.ip_unprivileged_port_start": "500",
@@ -186,7 +191,8 @@ func TestLinuxSandboxContainerSpec(t *testing.T) {
assert.Contains(t, spec.Linux.Sysctl["net.ipv4.ping_group_range"], "1 1000")
},
},
"sandbox sizing annotations should be set if LinuxContainerResources were provided": {
{
desc: "sandbox sizing annotations should be set if LinuxContainerResources were provided",
configChange: func(c *runtime.PodSandboxConfig) {
c.Linux.Resources = &v1.LinuxContainerResources{
CpuPeriod: 100,
@@ -214,7 +220,8 @@ func TestLinuxSandboxContainerSpec(t *testing.T) {
assert.EqualValues(t, "1024", value)
},
},
"sandbox sizing annotations should not be set if LinuxContainerResources were not provided": {
{
desc: "sandbox sizing annotations should not be set if LinuxContainerResources were not provided",
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
_, ok := spec.Annotations[annotations.SandboxCPUPeriod]
assert.False(t, ok)
@@ -226,7 +233,8 @@ func TestLinuxSandboxContainerSpec(t *testing.T) {
assert.False(t, ok)
},
},
"sandbox sizing annotations are zero if the resources are set to 0": {
{
desc: "sandbox sizing annotations are zero if the resources are set to 0",
configChange: func(c *runtime.PodSandboxConfig) {
c.Linux.Resources = &v1.LinuxContainerResources{}
},
@@ -246,7 +254,8 @@ func TestLinuxSandboxContainerSpec(t *testing.T) {
},
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
c := newControllerService()
c.config.EnableUnprivilegedICMP = true
c.config.EnableUnprivilegedPorts = true
@@ -275,13 +284,15 @@ func TestSetupSandboxFiles(t *testing.T) {
testID = "test-id"
realhostname = "test-real-hostname"
)
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
dnsConfig *runtime.DNSConfig
hostname string
ipcMode runtime.NamespaceMode
expectedCalls []ostesting.CalledDetail
}{
"should check host /dev/shm existence when ipc mode is NODE": {
{
desc: "should check host /dev/shm existence when ipc mode is NODE",
ipcMode: runtime.NamespaceMode_NODE,
expectedCalls: []ostesting.CalledDetail{
{
@@ -317,7 +328,8 @@ func TestSetupSandboxFiles(t *testing.T) {
},
},
},
"should create new /etc/resolv.conf if DNSOptions is set": {
{
desc: "should create new /etc/resolv.conf if DNSOptions is set",
dnsConfig: &runtime.DNSConfig{
Servers: []string{"8.8.8.8"},
Searches: []string{"114.114.114.114"},
@@ -360,7 +372,8 @@ options timeout:1
},
},
},
"should create sandbox shm when ipc namespace mode is not NODE": {
{
desc: "should create sandbox shm when ipc namespace mode is not NODE",
ipcMode: runtime.NamespaceMode_POD,
expectedCalls: []ostesting.CalledDetail{
{
@@ -403,7 +416,8 @@ options timeout:1
},
},
},
"should create /etc/hostname when hostname is set": {
{
desc: "should create /etc/hostname when hostname is set",
hostname: "test-hostname",
ipcMode: runtime.NamespaceMode_NODE,
expectedCalls: []ostesting.CalledDetail{
@@ -438,7 +452,8 @@ options timeout:1
},
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
c := newControllerService()
c.os.(*ostesting.FakeOS).HostnameFn = func() (string, error) {
return realhostname, nil
@@ -469,15 +484,19 @@ options timeout:1
}
func TestParseDNSOption(t *testing.T) {
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
servers []string
searches []string
options []string
expectedContent string
expectErr bool
}{
"empty dns options should return empty content": {},
"non-empty dns options should return correct content": {
{
desc: "empty dns options should return empty content",
},
{
desc: "non-empty dns options should return correct content",
servers: []string{"8.8.8.8", "server.google.com"},
searches: []string{"114.114.114.114"},
options: []string{"timeout:1"},
@@ -487,7 +506,8 @@ nameserver server.google.com
options timeout:1
`,
},
"expanded dns config should return correct content on modern libc (e.g. glibc 2.26 and above)": {
{
desc: "expanded dns config should return correct content on modern libc (e.g. glibc 2.26 and above)",
servers: []string{"8.8.8.8", "server.google.com"},
searches: []string{
"server0.google.com",
@@ -506,7 +526,8 @@ options timeout:1
`,
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
resolvContent, err := parseDNSOptions(test.servers, test.searches, test.options)
if test.expectErr {
assert.Error(t, err)

View File

@@ -38,27 +38,31 @@ func TestSandboxContainerSpec(t *testing.T) {
}
testID := "test-id"
nsPath := "test-cni"
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
configChange func(*runtime.PodSandboxConfig)
podAnnotations []string
imageConfigChange func(*imagespec.ImageConfig)
specCheck func(*testing.T, *runtimespec.Spec)
expectErr bool
}{
"should return error when entrypoint and cmd are empty": {
{
desc: "should return error when entrypoint and cmd are empty",
imageConfigChange: func(c *imagespec.ImageConfig) {
c.Entrypoint = nil
c.Cmd = nil
},
expectErr: true,
},
"a passthrough annotation should be passed as an OCI annotation": {
{
desc: "a passthrough annotation should be passed as an OCI annotation",
podAnnotations: []string{"c"},
specCheck: func(t *testing.T, spec *runtimespec.Spec) {
assert.Equal(t, spec.Annotations["c"], "d")
},
},
"a non-passthrough annotation should not be passed as an OCI annotation": {
{
desc: "a non-passthrough annotation should not be passed as an OCI annotation",
configChange: func(c *runtime.PodSandboxConfig) {
c.Annotations["d"] = "e"
},
@@ -69,7 +73,8 @@ func TestSandboxContainerSpec(t *testing.T) {
assert.False(t, ok)
},
},
"passthrough annotations should support wildcard match": {
{
desc: "passthrough annotations should support wildcard match",
configChange: func(c *runtime.PodSandboxConfig) {
c.Annotations["t.f"] = "j"
c.Annotations["z.g"] = "o"
@@ -89,7 +94,8 @@ func TestSandboxContainerSpec(t *testing.T) {
},
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
c := newControllerService()
config, imageConfig, specCheck := getRunPodSandboxTestData()
if test.configChange != nil {
@@ -117,11 +123,15 @@ func TestSandboxContainerSpec(t *testing.T) {
}
func TestTypeurlMarshalUnmarshalSandboxMeta(t *testing.T) {
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
configChange func(*runtime.PodSandboxConfig)
}{
"should marshal original config": {},
"should marshal Linux": {
{
desc: "should marshal original config",
},
{
desc: "should marshal Linux",
configChange: func(c *runtime.PodSandboxConfig) {
if c.Linux == nil {
c.Linux = &runtime.LinuxPodSandboxConfig{}
@@ -137,7 +147,8 @@ func TestTypeurlMarshalUnmarshalSandboxMeta(t *testing.T) {
},
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
meta := &sandboxstore.Metadata{
ID: "1",
Name: "sandbox_1",
@@ -198,6 +209,7 @@ func TestHostAccessingSandbox(t *testing.T) {
{"Security Context namespace host access", hostNamespace, true},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
if got := hostAccessingSandbox(tt.config); got != tt.want {
t.Errorf("hostAccessingSandbox() = %v, want %v", got, tt.want)