package system // import "github.com/docker/docker/integration/system" import ( "context" "testing" "github.com/docker/docker/api/types" "github.com/docker/docker/integration/internal/container" "github.com/docker/docker/testutil/daemon" "gotest.tools/v3/assert" "gotest.tools/v3/skip" ) func TestDiskUsage(t *testing.T) { skip.If(t, testEnv.OSType == "windows") // d.Start fails on Windows with `protocol not available` t.Parallel() d := daemon.New(t) defer d.Cleanup(t) d.Start(t, "--iptables=false") defer d.Stop(t) client := d.NewClientT(t) ctx := context.Background() var stepDU types.DiskUsage for _, step := range []struct { doc string next func(t *testing.T, prev types.DiskUsage) types.DiskUsage }{ { doc: "empty", next: func(t *testing.T, _ types.DiskUsage) types.DiskUsage { du, err := client.DiskUsage(ctx, types.DiskUsageOptions{}) assert.NilError(t, err) assert.DeepEqual(t, du, types.DiskUsage{ Images: []*types.ImageSummary{}, Containers: []*types.Container{}, Volumes: []*types.Volume{}, BuildCache: []*types.BuildCache{}, }) return du }, }, { doc: "after LoadBusybox", next: func(t *testing.T, _ types.DiskUsage) types.DiskUsage { d.LoadBusybox(t) du, err := client.DiskUsage(ctx, types.DiskUsageOptions{}) assert.NilError(t, err) assert.Assert(t, du.LayersSize > 0) assert.Equal(t, len(du.Images), 1) assert.DeepEqual(t, du, types.DiskUsage{ LayersSize: du.LayersSize, Images: []*types.ImageSummary{ { Created: du.Images[0].Created, ID: du.Images[0].ID, RepoTags: []string{"busybox:latest"}, Size: du.LayersSize, VirtualSize: du.LayersSize, }, }, Containers: []*types.Container{}, Volumes: []*types.Volume{}, BuildCache: []*types.BuildCache{}, }) return du }, }, { doc: "after container.Run", next: func(t *testing.T, prev types.DiskUsage) types.DiskUsage { cID := container.Run(ctx, t, client) du, err := client.DiskUsage(ctx, types.DiskUsageOptions{}) assert.NilError(t, err) assert.Equal(t, len(du.Containers), 1) assert.Equal(t, len(du.Containers[0].Names), 1) assert.Assert(t, du.Containers[0].Created >= prev.Images[0].Created) assert.DeepEqual(t, du, types.DiskUsage{ LayersSize: prev.LayersSize, Images: []*types.ImageSummary{ func() *types.ImageSummary { sum := *prev.Images[0] sum.Containers++ return &sum }(), }, Containers: []*types.Container{ { ID: cID, Names: du.Containers[0].Names, Image: "busybox", ImageID: prev.Images[0].ID, Command: du.Containers[0].Command, // not relevant for the test Created: du.Containers[0].Created, Ports: du.Containers[0].Ports, // not relevant for the test SizeRootFs: prev.Images[0].Size, Labels: du.Containers[0].Labels, // not relevant for the test State: du.Containers[0].State, // not relevant for the test Status: du.Containers[0].Status, // not relevant for the test HostConfig: du.Containers[0].HostConfig, // not relevant for the test NetworkSettings: du.Containers[0].NetworkSettings, // not relevant for the test Mounts: du.Containers[0].Mounts, // not relevant for the test }, }, Volumes: []*types.Volume{}, BuildCache: []*types.BuildCache{}, }) return du }, }, } { t.Run(step.doc, func(t *testing.T) { stepDU = step.next(t, stepDU) for _, tc := range []struct { doc string options types.DiskUsageOptions expected types.DiskUsage }{ { doc: "container types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.ContainerObject, }, }, expected: types.DiskUsage{ Containers: stepDU.Containers, }, }, { doc: "image types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.ImageObject, }, }, expected: types.DiskUsage{ LayersSize: stepDU.LayersSize, Images: stepDU.Images, }, }, { doc: "volume types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.VolumeObject, }, }, expected: types.DiskUsage{ Volumes: stepDU.Volumes, }, }, { doc: "build-cache types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.BuildCacheObject, }, }, expected: types.DiskUsage{ BuildCache: stepDU.BuildCache, }, }, { doc: "container, volume types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.ContainerObject, types.VolumeObject, }, }, expected: types.DiskUsage{ Containers: stepDU.Containers, Volumes: stepDU.Volumes, }, }, { doc: "image, build-cache types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.ImageObject, types.BuildCacheObject, }, }, expected: types.DiskUsage{ LayersSize: stepDU.LayersSize, Images: stepDU.Images, BuildCache: stepDU.BuildCache, }, }, { doc: "container, volume, build-cache types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.ContainerObject, types.VolumeObject, types.BuildCacheObject, }, }, expected: types.DiskUsage{ Containers: stepDU.Containers, Volumes: stepDU.Volumes, BuildCache: stepDU.BuildCache, }, }, { doc: "image, volume, build-cache types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.ImageObject, types.VolumeObject, types.BuildCacheObject, }, }, expected: types.DiskUsage{ LayersSize: stepDU.LayersSize, Images: stepDU.Images, Volumes: stepDU.Volumes, BuildCache: stepDU.BuildCache, }, }, { doc: "container, image, volume types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.ContainerObject, types.ImageObject, types.VolumeObject, }, }, expected: types.DiskUsage{ LayersSize: stepDU.LayersSize, Containers: stepDU.Containers, Images: stepDU.Images, Volumes: stepDU.Volumes, }, }, { doc: "container, image, volume, build-cache types", options: types.DiskUsageOptions{ Types: []types.DiskUsageObject{ types.ContainerObject, types.ImageObject, types.VolumeObject, types.BuildCacheObject, }, }, expected: types.DiskUsage{ LayersSize: stepDU.LayersSize, Containers: stepDU.Containers, Images: stepDU.Images, Volumes: stepDU.Volumes, BuildCache: stepDU.BuildCache, }, }, } { tc := tc t.Run(tc.doc, func(t *testing.T) { // TODO: Run in parallel once https://github.com/moby/moby/pull/42560 is merged. du, err := client.DiskUsage(ctx, tc.options) assert.NilError(t, err) assert.DeepEqual(t, du, tc.expected) }) } }) } }