Browse code

c8d/list: Add test for total and content size

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>

Paweł Gronowski authored on 2024/08/14 20:49:50
Showing 4 changed files
... ...
@@ -89,6 +89,76 @@ func BenchmarkImageList(b *testing.B) {
89 89
 	}
90 90
 }
91 91
 
92
+func TestImageListCheckTotalSize(t *testing.T) {
93
+	ctx := namespaces.WithNamespace(context.TODO(), "testing")
94
+
95
+	blobsDir := t.TempDir()
96
+	cs := &blobsDirContentStore{blobs: filepath.Join(blobsDir, "blobs/sha256")}
97
+
98
+	twoplatform, mfstsDescs, err := specialimage.MultiPlatform(blobsDir, "test:latest", []ocispec.Platform{
99
+		{OS: "linux", Architecture: "arm64"},
100
+		{OS: "linux", Architecture: "amd64"},
101
+	})
102
+	assert.NilError(t, err)
103
+
104
+	ctx = logtest.WithT(ctx, t)
105
+	service := fakeImageService(t, ctx, cs)
106
+
107
+	_, err = service.images.Create(ctx, imagesFromIndex(twoplatform)[0])
108
+	assert.NilError(t, err)
109
+
110
+	all, err := service.Images(ctx, imagetypes.ListOptions{Manifests: true})
111
+	assert.NilError(t, err)
112
+
113
+	assert.Check(t, is.Len(all, 1))
114
+	assert.Check(t, is.Len(all[0].Manifests, 2))
115
+
116
+	// TODO: The test snapshotter doesn't do anything, so the size is always 0.
117
+	assert.Check(t, is.Equal(all[0].Manifests[0].ImageData.Size.Unpacked, int64(0)))
118
+	assert.Check(t, is.Equal(all[0].Manifests[1].ImageData.Size.Unpacked, int64(0)))
119
+
120
+	mfstArm64 := mfstsDescs[0]
121
+	mfstAmd64 := mfstsDescs[1]
122
+
123
+	indexSize := blobSize(t, ctx, cs, twoplatform.Manifests[0].Digest)
124
+	arm64ManifestSize := blobSize(t, ctx, cs, mfstArm64.Digest)
125
+	amd64ManifestSize := blobSize(t, ctx, cs, mfstAmd64.Digest)
126
+
127
+	var arm64Mfst, amd64Mfst ocispec.Manifest
128
+	assert.NilError(t, readConfig(ctx, cs, mfstArm64, &arm64Mfst))
129
+	assert.NilError(t, readConfig(ctx, cs, mfstAmd64, &amd64Mfst))
130
+
131
+	// MultiPlatform should produce a single layer. If these fail, the test needs to be adjusted.
132
+	assert.Assert(t, is.Len(arm64Mfst.Layers, 1))
133
+	assert.Assert(t, is.Len(amd64Mfst.Layers, 1))
134
+
135
+	arm64ConfigSize := blobSize(t, ctx, cs, arm64Mfst.Config.Digest)
136
+	amd64ConfigSize := blobSize(t, ctx, cs, amd64Mfst.Config.Digest)
137
+
138
+	arm64LayerSize := blobSize(t, ctx, cs, arm64Mfst.Layers[0].Digest)
139
+	amd64LayerSize := blobSize(t, ctx, cs, amd64Mfst.Layers[0].Digest)
140
+
141
+	allTotalSize := indexSize +
142
+		arm64ManifestSize + amd64ManifestSize +
143
+		arm64ConfigSize + amd64ConfigSize +
144
+		arm64LayerSize + amd64LayerSize
145
+
146
+	assert.Check(t, is.Equal(all[0].Size, allTotalSize-indexSize))
147
+
148
+	assert.Check(t, is.Equal(all[0].Manifests[0].Size.Content, arm64ManifestSize+arm64ConfigSize+arm64LayerSize))
149
+	assert.Check(t, is.Equal(all[0].Manifests[1].Size.Content, amd64ManifestSize+amd64ConfigSize+amd64LayerSize))
150
+
151
+	// TODO: This should also include the Size.Unpacked, but the test snapshotter doesn't do anything yet
152
+	assert.Check(t, is.Equal(all[0].Manifests[0].Size.Total, amd64ManifestSize+amd64ConfigSize+amd64LayerSize))
153
+	assert.Check(t, is.Equal(all[0].Manifests[1].Size.Total, amd64ManifestSize+amd64ConfigSize+amd64LayerSize))
154
+}
155
+
156
+func blobSize(t *testing.T, ctx context.Context, cs content.Store, dgst digest.Digest) int64 {
157
+	info, err := cs.Info(ctx, dgst)
158
+	assert.NilError(t, err)
159
+	return info.Size
160
+}
161
+
92 162
 func TestImageList(t *testing.T) {
93 163
 	ctx := namespaces.WithNamespace(context.TODO(), "testing")
94 164
 
... ...
@@ -204,7 +204,7 @@ func TestImagePushIndex(t *testing.T) {
204 204
 				imgSvc.defaultPlatformOverride = platforms.Only(defaultDaemonPlatform)
205 205
 			}
206 206
 
207
-			idx, err := specialimage.MultiPlatform(csDir, "multiplatform:latest", tc.indexPlatforms)
207
+			idx, _, err := specialimage.MultiPlatform(csDir, "multiplatform:latest", tc.indexPlatforms)
208 208
 			assert.NilError(t, err)
209 209
 
210 210
 			imgs := imagesFromIndex(idx)
... ...
@@ -251,7 +251,8 @@ func TestAPIImagesListManifests(t *testing.T) {
251 251
 		{OS: "darwin", Architecture: "arm64"},
252 252
 	}
253 253
 	specialimage.Load(ctx, t, apiClient, func(dir string) (*ocispec.Index, error) {
254
-		return specialimage.MultiPlatform(dir, "multiplatform:latest", testPlatforms)
254
+		idx, _, err := specialimage.MultiPlatform(dir, "multiplatform:latest", testPlatforms)
255
+		return idx, err
255 256
 	})
256 257
 
257 258
 	t.Run("unsupported before 1.47", func(t *testing.T) {
... ...
@@ -7,10 +7,10 @@ import (
7 7
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
8 8
 )
9 9
 
10
-func MultiPlatform(dir string, imageRef string, imagePlatforms []ocispec.Platform) (*ocispec.Index, error) {
10
+func MultiPlatform(dir string, imageRef string, imagePlatforms []ocispec.Platform) (*ocispec.Index, []ocispec.Descriptor, error) {
11 11
 	ref, err := reference.ParseNormalizedNamed(imageRef)
12 12
 	if err != nil {
13
-		return nil, err
13
+		return nil, nil, err
14 14
 	}
15 15
 
16 16
 	var descs []ocispec.Descriptor
... ...
@@ -19,14 +19,15 @@ func MultiPlatform(dir string, imageRef string, imagePlatforms []ocispec.Platfor
19 19
 		ps := platforms.Format(platform)
20 20
 		manifestDesc, err := oneLayerPlatformManifest(dir, platform, FileInLayer{Path: "bash", Content: []byte("layer-" + ps)})
21 21
 		if err != nil {
22
-			return nil, err
22
+			return nil, nil, err
23 23
 		}
24 24
 		descs = append(descs, manifestDesc)
25 25
 	}
26 26
 
27
-	return multiPlatformImage(dir, ref, ocispec.Index{
27
+	idx, err := multiPlatformImage(dir, ref, ocispec.Index{
28 28
 		Versioned: specs.Versioned{SchemaVersion: 2},
29 29
 		MediaType: ocispec.MediaTypeImageIndex,
30 30
 		Manifests: descs,
31 31
 	})
32
+	return idx, descs, err
32 33
 }