1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package mutate
17
18 import (
19 "context"
20 "errors"
21 "testing"
22
23 "github.com/google/go-containerregistry/pkg/v1/mutate"
24 "github.com/google/go-containerregistry/pkg/v1/random"
25 "github.com/google/go-containerregistry/pkg/v1/types"
26 "github.com/sigstore/cosign/v2/pkg/oci"
27 "github.com/sigstore/cosign/v2/pkg/oci/signed"
28 )
29
30 func TestMapImage(t *testing.T) {
31 i, err := random.Image(300 , 3 )
32 if err != nil {
33 t.Fatalf("random.Image() = %v", err)
34 }
35 si := signed.Image(i)
36
37 t.Run("one call to identity mutator", func(t *testing.T) {
38 calls := 0
39 rsi, err := Map(context.Background(), si, func(_ context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
40 calls++
41 return se, nil
42 })
43 if err != nil {
44 t.Fatalf("Map() = %v", err)
45 }
46 if rsi != si {
47 t.Fatalf("Map() = %#v, wanted %#v", rsi, si)
48 }
49 if calls != 1 {
50 t.Fatalf("Map called %d times, wanted 1", calls)
51 }
52 })
53
54 t.Run("error propagates", func(t *testing.T) {
55 want := errors.New("this is the error I expect")
56 _, got := Map(context.Background(), si, func(_ context.Context, _ oci.SignedEntity) (oci.SignedEntity, error) {
57 return nil, want
58 })
59 if !errors.Is(got, want) {
60 t.Fatalf("Map() = %v, wanted %v", got, want)
61 }
62 })
63
64 t.Run("new result image", func(t *testing.T) {
65 i, err := random.Image(300 , 3 )
66 if err != nil {
67 t.Fatalf("random.Image() = %v", err)
68 }
69 want := signed.Image(i)
70
71 got, err := Map(context.Background(), si, func(_ context.Context, _ oci.SignedEntity) (oci.SignedEntity, error) {
72 return want, nil
73 })
74 if err != nil {
75 t.Fatalf("Map() = %v", err)
76 }
77 if got != want {
78 t.Fatalf("Map() = %#v, wanted %#v", got, want)
79 }
80 })
81
82 t.Run("filtered image", func(t *testing.T) {
83 got, err := Map(context.Background(), si, func(_ context.Context, _ oci.SignedEntity) (oci.SignedEntity, error) {
84 return nil, nil
85 })
86 if err != nil {
87 t.Fatalf("Map() = %v", err)
88 }
89 if got != nil {
90 t.Fatalf("Map() = %#v, wanted nil", got)
91 }
92 })
93 }
94
95 func TestMapImageIndex(t *testing.T) {
96 ii, err := random.Index(300 , 3 , 2 )
97 if err != nil {
98 t.Fatalf("random.Image() = %v", err)
99 }
100 ii2, err := random.Index(300 , 3 , 2 )
101 if err != nil {
102 t.Fatalf("random.Image() = %v", err)
103 }
104 sii := signed.ImageIndex(mutate.AppendManifests(ii, mutate.IndexAddendum{
105 Add: ii2,
106 }))
107
108 t.Run("six calls to identity mutator", func(t *testing.T) {
109 calls := 0
110 after := 0
111 rsi, err := Map(context.Background(), sii, func(ctx context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
112 calls++
113 if IsAfterChildren(ctx) {
114 after++
115 }
116 return se, nil
117 })
118 if err != nil {
119 t.Fatalf("Map() = %v", err)
120 }
121 if rsi != sii {
122 t.Fatalf("Map() = %#v, wanted %#v", rsi, sii)
123 }
124 if calls != 6 {
125 t.Fatalf("Map called %d times, wanted 6", calls)
126 }
127 if after != 0 {
128 t.Fatalf("Map called %d times (w/ after), wanted 0", after)
129 }
130 })
131
132 t.Run("just one call to root index w/ ErrSkipChildren", func(t *testing.T) {
133 calls := 0
134 _, err := Map(context.Background(), sii, func(_ context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
135 calls++
136 if se != sii {
137 t.Errorf("Wanted mutator called on %#v, got call on %#v", sii, se)
138 }
139 return se, ErrSkipChildren
140 })
141 if err != nil {
142 t.Fatalf("Map() = %v", err)
143 }
144 if calls != 1 {
145 t.Fatalf("Map called %d times, wanted 1", calls)
146 }
147 })
148
149 t.Run("two calls to mutator with IsAfterChildren", func(t *testing.T) {
150 before := 0
151 after := 0
152 rsi, err := Map(context.Background(), sii, func(ctx context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
153 if IsBeforeChildren(ctx) {
154 before++
155 }
156 if IsAfterChildren(ctx) {
157 after++
158 }
159 if sii, ok := se.(oci.SignedImageIndex); ok {
160 return sii, nil
161 }
162 i, err := random.Image(300 , 3 )
163 if err != nil {
164 t.Fatalf("random.Image() = %v", err)
165 }
166 return signed.Image(i), nil
167 })
168 if err != nil {
169 t.Fatalf("Map() = %v", err)
170 }
171 if rsi == sii {
172 t.Fatalf("Map() = %#v, wanted something new!", rsi)
173 }
174 if before != 2 {
175 t.Fatalf("Map called %d times (w/ before), wanted 2", before)
176 }
177 if after != 2 {
178 t.Fatalf("Map called %d times (w/ after), wanted 2", after)
179 }
180 })
181
182 t.Run("test filtering images", func(t *testing.T) {
183 rsi, err := Map(context.Background(), sii, func(_ context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
184 if _, ok := se.(oci.SignedImage); ok {
185 return nil, nil
186 }
187 return se, nil
188 })
189 if err != nil {
190 t.Fatalf("Map() = %v", err)
191 }
192 if rsi == sii {
193 t.Fatalf("Map() = %#v, wanted something new!", rsi)
194 }
195
196 im, err := rsi.(oci.SignedImageIndex).IndexManifest()
197 if err != nil {
198 t.Fatalf("IndexManifest() = %v", err)
199 }
200 for _, desc := range im.Manifests {
201 if desc.MediaType == types.DockerManifestSchema2 {
202 t.Error("Found an image media type!")
203 }
204 }
205 })
206
207 t.Run("test filtering indices", func(t *testing.T) {
208 rsi, err := Map(context.Background(), sii, func(ctx context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
209 if IsBeforeChildren(ctx) && se != sii {
210 return nil, nil
211 }
212 return se, nil
213 })
214 if err != nil {
215 t.Fatalf("Map() = %v", err)
216 }
217 if rsi == sii {
218 t.Fatalf("Map() = %#v, wanted something new!", rsi)
219 }
220
221 im, err := rsi.(oci.SignedImageIndex).IndexManifest()
222 if err != nil {
223 t.Fatalf("IndexManifest() = %v", err)
224 }
225 for _, desc := range im.Manifests {
226 if desc.MediaType != types.DockerManifestSchema2 {
227 t.Errorf("MediaType = %s, wanted %s", desc.MediaType, types.DockerManifestSchema2)
228 }
229 }
230 })
231
232 t.Run("error propagates from child image", func(t *testing.T) {
233 want := errors.New("this is the error I expect")
234 _, got := Map(context.Background(), sii, func(_ context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
235 if _, ok := se.(oci.SignedImage); !ok {
236 return se, nil
237 }
238 return nil, want
239 })
240 if !errors.Is(got, want) {
241 t.Fatalf("Map() = %v, wanted %v", got, want)
242 }
243 })
244
245 t.Run("error propagates from child index", func(t *testing.T) {
246 want := errors.New("this is the error I expect")
247 _, got := Map(context.Background(), sii, func(ctx context.Context, se oci.SignedEntity) (oci.SignedEntity, error) {
248 if IsBeforeChildren(ctx) && se != sii {
249 return nil, want
250 }
251 return se, nil
252 })
253 if !errors.Is(got, want) {
254 t.Fatalf("Map() = %v, wanted %v", got, want)
255 }
256 })
257 }
258
View as plain text