Skip to content

Commit 1c652af

Browse files
TatianaSeleznevaTatiana Selezneva
authored andcommitted
Add tests for obs/archive file
1 parent 840fa4a commit 1c652af

File tree

1 file changed

+371
-0
lines changed

1 file changed

+371
-0
lines changed

pkg/obs/specs/archive_test.go

Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
/*
2+
Copyright 2026 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package specs_test
18+
19+
import (
20+
"net/http"
21+
"path/filepath"
22+
"testing"
23+
24+
"github.com/stretchr/testify/require"
25+
26+
"k8s.io/release/pkg/obs/specs"
27+
"k8s.io/release/pkg/obs/specs/specsfakes"
28+
)
29+
30+
func TestBuildArtifactsArchive(t *testing.T) {
31+
testcases := []struct {
32+
name string
33+
pkgDef *specs.PackageDefinition
34+
shouldErr bool
35+
destinationPaths []string
36+
archiveFile string
37+
prepare func(mock *specsfakes.FakeImpl)
38+
}{
39+
{
40+
name: "happy path, empty package",
41+
shouldErr: false,
42+
archiveFile: "_.orig.tar.gz",
43+
pkgDef: &specs.PackageDefinition{},
44+
prepare: func(*specsfakes.FakeImpl) {},
45+
},
46+
{
47+
name: "happy path with multiple variations (multiple architectures)",
48+
shouldErr: false,
49+
destinationPaths: []string{
50+
"kubernetes-cni/x86_64/kubernetes-cni.tar.gz",
51+
"kubernetes-cni/aarch64/kubernetes-cni.tar.gz",
52+
},
53+
archiveFile: "kubernetes-cni_1.2.3.orig.tar.gz",
54+
pkgDef: &specs.PackageDefinition{
55+
Name: "kubernetes-cni",
56+
Version: "1.2.3",
57+
SpecOutputPath: t.TempDir(),
58+
Variations: []specs.PackageVariation{
59+
{
60+
Architecture: "amd64",
61+
Source: "gs://",
62+
},
63+
{
64+
Architecture: "arm64",
65+
Source: "gs://",
66+
},
67+
},
68+
},
69+
prepare: func(*specsfakes.FakeImpl) {},
70+
},
71+
{
72+
name: "error if pkgDef is nil",
73+
shouldErr: true,
74+
pkgDef: nil,
75+
prepare: func(*specsfakes.FakeImpl) {},
76+
},
77+
{
78+
name: "check download path for kubernetes-cni",
79+
shouldErr: false,
80+
destinationPaths: []string{"kubernetes-cni/kubernetes-cni.tar.gz"},
81+
archiveFile: "kubernetes-cni_0.0.1.orig.tar.gz",
82+
pkgDef: &specs.PackageDefinition{
83+
Name: "kubernetes-cni",
84+
Version: "0.0.1",
85+
SpecOutputPath: t.TempDir(),
86+
Variations: []specs.PackageVariation{
87+
{
88+
Architecture: "",
89+
Source: "gs://",
90+
},
91+
},
92+
},
93+
prepare: func(*specsfakes.FakeImpl) {},
94+
},
95+
{
96+
name: "check download path for cri-tools",
97+
shouldErr: false,
98+
destinationPaths: []string{"cri-tools/cri-tools.tar.gz"},
99+
archiveFile: "cri-tools_0.0.1.orig.tar.gz",
100+
pkgDef: &specs.PackageDefinition{
101+
Name: "cri-tools",
102+
Version: "0.0.1",
103+
SpecOutputPath: t.TempDir(),
104+
Variations: []specs.PackageVariation{
105+
{
106+
Architecture: "",
107+
Source: "gs://",
108+
},
109+
},
110+
},
111+
prepare: func(*specsfakes.FakeImpl) {},
112+
},
113+
{
114+
name: "check download path for cri-o",
115+
shouldErr: false,
116+
destinationPaths: []string{"cri-o/cri-o.tar.gz"},
117+
archiveFile: "cri-o_0.0.1.orig.tar.gz",
118+
pkgDef: &specs.PackageDefinition{
119+
Name: "cri-o",
120+
Version: "0.0.1",
121+
SpecOutputPath: t.TempDir(),
122+
Variations: []specs.PackageVariation{
123+
{
124+
Architecture: "",
125+
Source: "gs://",
126+
},
127+
},
128+
},
129+
prepare: func(*specsfakes.FakeImpl) {},
130+
},
131+
{
132+
name: "check download path for all other packages",
133+
shouldErr: false,
134+
destinationPaths: []string{"some-other-package/some-other-package"},
135+
archiveFile: "some-other-package_0.0.1.orig.tar.gz",
136+
pkgDef: &specs.PackageDefinition{
137+
Name: "some-other-package",
138+
Version: "0.0.1",
139+
SpecOutputPath: t.TempDir(),
140+
Variations: []specs.PackageVariation{
141+
{
142+
Architecture: "",
143+
Source: "gs://",
144+
},
145+
},
146+
},
147+
prepare: func(*specsfakes.FakeImpl) {},
148+
},
149+
{
150+
name: "throw error when can't download from GCS",
151+
shouldErr: true,
152+
pkgDef: &specs.PackageDefinition{
153+
Name: "cri-o",
154+
Version: "0.0.1",
155+
SpecOutputPath: t.TempDir(),
156+
Variations: []specs.PackageVariation{
157+
{
158+
Architecture: "",
159+
Source: "gs://",
160+
},
161+
},
162+
},
163+
prepare: func(mock *specsfakes.FakeImpl) {
164+
mock.GCSCopyToLocalReturns(err)
165+
},
166+
},
167+
{
168+
name: "throw error when can't extract from the archive",
169+
shouldErr: true,
170+
pkgDef: &specs.PackageDefinition{
171+
Name: "cri-o",
172+
Version: "0.0.1",
173+
SpecOutputPath: t.TempDir(),
174+
Variations: []specs.PackageVariation{
175+
{
176+
Architecture: "",
177+
Source: "gs://",
178+
},
179+
},
180+
},
181+
prepare: func(mock *specsfakes.FakeImpl) {
182+
mock.ExtractReturns(err)
183+
},
184+
},
185+
{
186+
name: "throw error when can't remove the archive",
187+
shouldErr: true,
188+
pkgDef: &specs.PackageDefinition{
189+
Name: "cri-o",
190+
Version: "0.0.1",
191+
SpecOutputPath: t.TempDir(),
192+
Variations: []specs.PackageVariation{
193+
{
194+
Architecture: "",
195+
Source: "gs://",
196+
},
197+
},
198+
},
199+
prepare: func(mock *specsfakes.FakeImpl) {
200+
mock.RemoveFileReturns(err)
201+
},
202+
},
203+
{
204+
name: "throw error when can't compress artifacts",
205+
shouldErr: true,
206+
pkgDef: &specs.PackageDefinition{
207+
Name: "cri-o",
208+
Version: "0.0.1",
209+
SpecOutputPath: t.TempDir(),
210+
Variations: []specs.PackageVariation{
211+
{
212+
Architecture: "",
213+
Source: "gs://",
214+
},
215+
},
216+
},
217+
prepare: func(mock *specsfakes.FakeImpl) {
218+
mock.CompressReturns(err)
219+
},
220+
},
221+
222+
{
223+
name: "throw error when MkdirAll fails",
224+
shouldErr: true,
225+
pkgDef: &specs.PackageDefinition{
226+
Name: "cri-o",
227+
Version: "0.0.1",
228+
SpecOutputPath: t.TempDir(),
229+
Variations: []specs.PackageVariation{
230+
{
231+
Architecture: "",
232+
Source: "gs://",
233+
},
234+
},
235+
},
236+
prepare: func(mock *specsfakes.FakeImpl) {
237+
mock.MkdirAllReturns(err)
238+
},
239+
},
240+
{
241+
name: "throw error when can't RemoveAll after compressing",
242+
shouldErr: true,
243+
pkgDef: &specs.PackageDefinition{
244+
Name: "kubernetes-cni",
245+
Version: "0.0.1",
246+
SpecOutputPath: t.TempDir(),
247+
Variations: []specs.PackageVariation{
248+
{
249+
Architecture: "s390x",
250+
Source: "gs://",
251+
},
252+
},
253+
},
254+
prepare: func(mock *specsfakes.FakeImpl) {
255+
mock.RemoveAllReturns(err)
256+
},
257+
},
258+
{
259+
name: "URL download with GetRequest error",
260+
shouldErr: true,
261+
pkgDef: &specs.PackageDefinition{
262+
Name: "something-else",
263+
Version: "0.0.1",
264+
SpecOutputPath: t.TempDir(),
265+
Variations: []specs.PackageVariation{
266+
{
267+
Architecture: "ppc64le",
268+
Source: "https://example.com/artifact.tar",
269+
},
270+
},
271+
},
272+
prepare: func(mock *specsfakes.FakeImpl) {
273+
mock.GetRequestReturns(nil, err)
274+
},
275+
},
276+
{
277+
name: "URL download with non-200 status code",
278+
shouldErr: true,
279+
pkgDef: &specs.PackageDefinition{
280+
Name: "something-else",
281+
Version: "0.0.1",
282+
SpecOutputPath: t.TempDir(),
283+
Variations: []specs.PackageVariation{
284+
{
285+
Architecture: "arm64",
286+
Source: "https://example.com/artifact.tar",
287+
},
288+
},
289+
},
290+
prepare: func(mock *specsfakes.FakeImpl) {
291+
resp := &http.Response{StatusCode: http.StatusNotFound}
292+
mock.GetRequestReturns(resp, nil)
293+
},
294+
},
295+
{
296+
name: "URL download with CreateFile error",
297+
shouldErr: true,
298+
pkgDef: &specs.PackageDefinition{
299+
Name: "something-else",
300+
Version: "0.0.1",
301+
SpecOutputPath: t.TempDir(),
302+
Variations: []specs.PackageVariation{
303+
{
304+
Architecture: "ppc64le",
305+
Source: "https://example.com/artifact.tar",
306+
},
307+
},
308+
},
309+
prepare: func(mock *specsfakes.FakeImpl) {
310+
mock.CreateFileReturns(nil, err)
311+
},
312+
},
313+
{
314+
name: "don't throw an error when download directory exists",
315+
shouldErr: false,
316+
destinationPaths: []string{"kubernetes-cni\\x86_64\\kubernetes-cni.tar.gz"},
317+
archiveFile: "kubernetes-cni_0.0.2.orig.tar.gz",
318+
pkgDef: &specs.PackageDefinition{
319+
Name: "kubernetes-cni",
320+
Version: "0.0.2",
321+
SpecOutputPath: t.TempDir(),
322+
Variations: []specs.PackageVariation{
323+
{
324+
Architecture: "amd64",
325+
Source: "gs://",
326+
},
327+
},
328+
},
329+
prepare: func(mock *specsfakes.FakeImpl) {
330+
mock.MkdirAllReturns(err)
331+
mock.IsExistReturns(true)
332+
},
333+
},
334+
}
335+
for _, tc := range testcases {
336+
t.Run(tc.name, func(t *testing.T) {
337+
options := &specs.Options{}
338+
sut := specs.New(options)
339+
340+
mock := &specsfakes.FakeImpl{}
341+
342+
tc.prepare(mock)
343+
344+
sut.SetImpl(mock)
345+
346+
err := sut.BuildArtifactsArchive(tc.pkgDef)
347+
348+
if tc.shouldErr {
349+
require.Error(t, err)
350+
} else {
351+
if mock.GCSCopyToLocalCallCount() > 0 {
352+
// check destination paths for all variations
353+
for i, expectedPath := range tc.destinationPaths {
354+
_, actualDestinationPath := mock.GCSCopyToLocalArgsForCall(i)
355+
expectedDestinationPath := filepath.Join(tc.pkgDef.SpecOutputPath, expectedPath)
356+
require.Equal(t, expectedDestinationPath, actualDestinationPath)
357+
}
358+
}
359+
360+
// check archive destination
361+
if mock.CompressCallCount() > 0 {
362+
actualArchiveFile, _, _ := mock.CompressArgsForCall(0)
363+
expectedArchiveFile := filepath.Join(tc.pkgDef.SpecOutputPath, tc.archiveFile)
364+
require.Equal(t, expectedArchiveFile, actualArchiveFile)
365+
}
366+
367+
require.NoError(t, err)
368+
}
369+
})
370+
}
371+
}

0 commit comments

Comments
 (0)