Browse code

integration-cli: migrate TestPostContainersCreateShmSizeXXX to integration

Some of these tests were making assumptions about the daemon's internals
by using `config.DefaultShmSize` from the daemon config package.

Rewrite them to start a daemon with a custom default, and verify the
tests to use that default.

This migrates the following tests from integration-cli to integration;

- `DockerAPISuite.TestPostContainersCreateShmSizeNegative`
- `DockerAPISuite.TestPostContainersCreateShmSizeHostConfigOmitted`
- `DockerAPISuite.TestPostContainersCreateShmSizeOmitted`
- `DockerAPISuite.TestPostContainersCreateWithShmSize`

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2025/07/25 00:16:12
Showing 3 changed files
... ...
@@ -11,14 +11,12 @@ import (
11 11
 	"net/http"
12 12
 	"os"
13 13
 	"path/filepath"
14
-	"regexp"
15 14
 	"runtime"
16 15
 	"strings"
17 16
 	"testing"
18 17
 	"time"
19 18
 
20 19
 	cerrdefs "github.com/containerd/errdefs"
21
-	dconfig "github.com/docker/docker/daemon/config"
22 20
 	"github.com/docker/docker/daemon/volume"
23 21
 	"github.com/docker/docker/integration-cli/cli"
24 22
 	"github.com/docker/docker/integration-cli/cli/build"
... ...
@@ -1139,110 +1137,6 @@ func (s *DockerAPISuite) TestPostContainersCreateWithWrongCpusetValues(c *testin
1139 1139
 	assert.ErrorContains(c, err, expected)
1140 1140
 }
1141 1141
 
1142
-func (s *DockerAPISuite) TestPostContainersCreateShmSizeNegative(c *testing.T) {
1143
-	// ShmSize is not supported on Windows
1144
-	testRequires(c, DaemonIsLinux)
1145
-	config := container.Config{
1146
-		Image: "busybox",
1147
-	}
1148
-	hostConfig := container.HostConfig{
1149
-		ShmSize: -1,
1150
-	}
1151
-
1152
-	apiClient, err := client.NewClientWithOpts(client.FromEnv)
1153
-	assert.NilError(c, err)
1154
-	defer apiClient.Close()
1155
-
1156
-	_, err = apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
1157
-	assert.ErrorContains(c, err, "SHM size can not be less than 0")
1158
-}
1159
-
1160
-func (s *DockerAPISuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *testing.T) {
1161
-	// ShmSize is not supported on Windows
1162
-	testRequires(c, DaemonIsLinux)
1163
-
1164
-	config := container.Config{
1165
-		Image: "busybox",
1166
-		Cmd:   []string{"mount"},
1167
-	}
1168
-
1169
-	apiClient, err := client.NewClientWithOpts(client.FromEnv)
1170
-	assert.NilError(c, err)
1171
-	defer apiClient.Close()
1172
-
1173
-	ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
1174
-	assert.NilError(c, err)
1175
-
1176
-	containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID)
1177
-	assert.NilError(c, err)
1178
-
1179
-	assert.Equal(c, containerJSON.HostConfig.ShmSize, dconfig.DefaultShmSize)
1180
-
1181
-	out := cli.DockerCmd(c, "start", "-i", containerJSON.ID).Combined()
1182
-	shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`)
1183
-	if !shmRegexp.MatchString(out) {
1184
-		c.Fatalf("Expected shm of 64MB in mount command, got %v", out)
1185
-	}
1186
-}
1187
-
1188
-func (s *DockerAPISuite) TestPostContainersCreateShmSizeOmitted(c *testing.T) {
1189
-	// ShmSize is not supported on Windows
1190
-	testRequires(c, DaemonIsLinux)
1191
-	config := container.Config{
1192
-		Image: "busybox",
1193
-		Cmd:   []string{"mount"},
1194
-	}
1195
-
1196
-	apiClient, err := client.NewClientWithOpts(client.FromEnv)
1197
-	assert.NilError(c, err)
1198
-	defer apiClient.Close()
1199
-
1200
-	ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &container.HostConfig{}, &network.NetworkingConfig{}, nil, "")
1201
-	assert.NilError(c, err)
1202
-
1203
-	containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID)
1204
-	assert.NilError(c, err)
1205
-
1206
-	assert.Equal(c, containerJSON.HostConfig.ShmSize, int64(67108864))
1207
-
1208
-	out := cli.DockerCmd(c, "start", "-i", containerJSON.ID).Combined()
1209
-	shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`)
1210
-	if !shmRegexp.MatchString(out) {
1211
-		c.Fatalf("Expected shm of 64MB in mount command, got %v", out)
1212
-	}
1213
-}
1214
-
1215
-func (s *DockerAPISuite) TestPostContainersCreateWithShmSize(c *testing.T) {
1216
-	// ShmSize is not supported on Windows
1217
-	testRequires(c, DaemonIsLinux)
1218
-	config := container.Config{
1219
-		Image: "busybox",
1220
-		Cmd:   []string{"mount"},
1221
-	}
1222
-
1223
-	hostConfig := container.HostConfig{
1224
-		ShmSize: 1073741824,
1225
-	}
1226
-
1227
-	apiClient, err := client.NewClientWithOpts(client.FromEnv)
1228
-	assert.NilError(c, err)
1229
-	defer apiClient.Close()
1230
-
1231
-	ctr, err := apiClient.ContainerCreate(testutil.GetContext(c), &config, &hostConfig, &network.NetworkingConfig{}, nil, "")
1232
-	assert.NilError(c, err)
1233
-
1234
-	containerJSON, err := apiClient.ContainerInspect(testutil.GetContext(c), ctr.ID)
1235
-	assert.NilError(c, err)
1236
-
1237
-	assert.Equal(c, containerJSON.HostConfig.ShmSize, int64(1073741824))
1238
-
1239
-	out := cli.DockerCmd(c, "start", "-i", containerJSON.ID).Combined()
1240
-	shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=1048576k`)
1241
-	if !shmRegex.MatchString(out) {
1242
-		c.Fatalf("Expected shm of 1GB in mount command, got %v", out)
1243
-	}
1244
-}
1245
-
1246 1142
 func (s *DockerAPISuite) TestPostContainersCreateMemorySwappinessHostConfigOmitted(c *testing.T) {
1247 1143
 	// Swappiness is not supported on Windows
1248 1144
 	testRequires(c, DaemonIsLinux)
... ...
@@ -9,10 +9,12 @@ import (
9 9
 	"strings"
10 10
 	"testing"
11 11
 
12
+	cerrdefs "github.com/containerd/errdefs"
12 13
 	"github.com/docker/docker/integration/internal/container"
13 14
 	net "github.com/docker/docker/integration/internal/network"
14 15
 	"github.com/docker/docker/testutil"
15 16
 	"github.com/docker/docker/testutil/daemon"
17
+	"github.com/docker/go-units"
16 18
 	"github.com/moby/moby/api/stdcopy"
17 19
 	containertypes "github.com/moby/moby/api/types/container"
18 20
 	"github.com/moby/moby/api/types/versions"
... ...
@@ -457,8 +459,8 @@ func TestCgroupRW(t *testing.T) {
457 457
 	}
458 458
 	for _, tc := range testCases {
459 459
 		t.Run(tc.name, func(t *testing.T) {
460
-			config := container.NewTestConfig(tc.ops...)
461
-			resp, err := container.CreateFromConfig(ctx, apiClient, config)
460
+			cfg := container.NewTestConfig(tc.ops...)
461
+			resp, err := container.CreateFromConfig(ctx, apiClient, cfg)
462 462
 			if err != nil {
463 463
 				assert.Equal(t, tc.expectedErrMsg, err.Error())
464 464
 				return
... ...
@@ -488,3 +490,79 @@ func TestCgroupRW(t *testing.T) {
488 488
 		})
489 489
 	}
490 490
 }
491
+
492
+func TestContainerShmSize(t *testing.T) {
493
+	ctx := setupTest(t)
494
+
495
+	const defaultSize = "1000k"
496
+	defaultSizeBytes, err := units.RAMInBytes(defaultSize)
497
+	assert.NilError(t, err)
498
+
499
+	d := daemon.New(t)
500
+	d.StartWithBusybox(ctx, t, "--default-shm-size="+defaultSize)
501
+	defer d.Stop(t)
502
+
503
+	apiClient := d.NewClientT(t)
504
+
505
+	tests := []struct {
506
+		doc     string
507
+		opt     container.ConfigOpt
508
+		expSize string
509
+		expErr  string
510
+	}{
511
+		{
512
+			doc:     "nil hostConfig",
513
+			opt:     container.WithHostConfig(nil),
514
+			expSize: defaultSize,
515
+		},
516
+		{
517
+			doc:     "empty hostConfig",
518
+			opt:     container.WithHostConfig(&containertypes.HostConfig{}),
519
+			expSize: defaultSize,
520
+		},
521
+		{
522
+			doc:     "custom shmSize",
523
+			opt:     container.WithHostConfig(&containertypes.HostConfig{ShmSize: defaultSizeBytes * 2}),
524
+			expSize: "2000k",
525
+		},
526
+		{
527
+			doc:    "negative shmSize",
528
+			opt:    container.WithHostConfig(&containertypes.HostConfig{ShmSize: -1}),
529
+			expErr: "Error response from daemon: SHM size can not be less than 0",
530
+		},
531
+	}
532
+
533
+	for _, tc := range tests {
534
+		t.Run(tc.doc, func(t *testing.T) {
535
+			if tc.expErr != "" {
536
+				cfg := container.NewTestConfig(container.WithCmd("sh", "-c", "grep /dev/shm /proc/self/mountinfo"), tc.opt)
537
+				_, err := container.CreateFromConfig(ctx, apiClient, cfg)
538
+				assert.Check(t, is.ErrorContains(err, tc.expErr))
539
+				assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
540
+				return
541
+			}
542
+
543
+			cID := container.Run(ctx, t, apiClient,
544
+				container.WithCmd("sh", "-c", "grep /dev/shm /proc/self/mountinfo"),
545
+				tc.opt,
546
+			)
547
+
548
+			t.Cleanup(func() {
549
+				container.Remove(ctx, t, apiClient, cID, containertypes.RemoveOptions{})
550
+			})
551
+
552
+			expectedSize, err := units.RAMInBytes(tc.expSize)
553
+			assert.NilError(t, err)
554
+
555
+			ctr := container.Inspect(ctx, t, apiClient, cID)
556
+			assert.Check(t, is.Equal(ctr.HostConfig.ShmSize, expectedSize))
557
+
558
+			out, err := container.Output(ctx, apiClient, cID)
559
+			assert.NilError(t, err)
560
+
561
+			// e.g., "218 213 0:87 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=1000k"
562
+			assert.Assert(t, is.Contains(out.Stdout, "/dev/shm "), "shm mount not found in output: \n%v", out.Stdout)
563
+			assert.Check(t, is.Contains(out.Stdout, "size="+tc.expSize))
564
+		})
565
+	}
566
+}
... ...
@@ -12,6 +12,9 @@ import (
12 12
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
13 13
 )
14 14
 
15
+// ConfigOpt is an option to apply to a container.
16
+type ConfigOpt func(*TestContainerConfig)
17
+
15 18
 // WithName sets the name of the container
16 19
 func WithName(name string) func(*TestContainerConfig) {
17 20
 	return func(c *TestContainerConfig) {
... ...
@@ -361,3 +364,10 @@ func WithContainerWideMacAddress(address string) func(c *TestContainerConfig) {
361 361
 		c.Config.MacAddress = address //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.44.
362 362
 	}
363 363
 }
364
+
365
+// WithHostConfig sets a custom [container.HostConfig] for the container.
366
+func WithHostConfig(hc *container.HostConfig) func(c *TestContainerConfig) {
367
+	return func(c *TestContainerConfig) {
368
+		c.HostConfig = hc
369
+	}
370
+}