1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package crane_test
16
17 import (
18 "archive/tar"
19 "errors"
20 "io"
21 "testing"
22
23 "github.com/google/go-containerregistry/pkg/crane"
24 )
25
26 func TestLayer(t *testing.T) {
27 tcs := []struct {
28 Name string
29 FileMap map[string][]byte
30 Digest string
31 }{{
32 Name: "Empty contents",
33 Digest: "sha256:89732bc7504122601f40269fc9ddfb70982e633ea9caf641ae45736f2846b004",
34 }, {
35 Name: "One file",
36 FileMap: map[string][]byte{
37 "/test": []byte("testy"),
38 },
39 Digest: "sha256:ec3ff19f471b99a76fb1c339c1dfdaa944a4fba25be6bcdc99fe7e772103079e",
40 }, {
41 Name: "Two files",
42 FileMap: map[string][]byte{
43 "/test": []byte("testy"),
44 "/testalt": []byte("footesty"),
45 },
46 Digest: "sha256:a48bcb7be3ab3ec608ee56eb80901224e19e31dc096cc06a8fd3a8dae1aa8947",
47 }, {
48 Name: "Many files",
49 FileMap: map[string][]byte{
50 "/1": []byte("1"),
51 "/2": []byte("2"),
52 "/3": []byte("3"),
53 "/4": []byte("4"),
54 "/5": []byte("5"),
55 "/6": []byte("6"),
56 "/7": []byte("7"),
57 "/8": []byte("8"),
58 "/9": []byte("9"),
59 },
60 Digest: "sha256:1e637602abbcab2dcedcc24e0b7c19763454a47261f1658b57569530b369ccb9",
61 }}
62
63 for _, tc := range tcs {
64 t.Run(tc.Name, func(t *testing.T) {
65 l, err := crane.Layer(tc.FileMap)
66 if err != nil {
67 t.Fatalf("Error calling layer: %v", err)
68 }
69
70 d, err := l.Digest()
71 if err != nil {
72 t.Fatalf("Error calling digest: %v", err)
73 }
74 if d.String() != tc.Digest {
75 t.Errorf("Incorrect digest, want %q, got %q", tc.Digest, d.String())
76 }
77
78
79 rc, err := l.Uncompressed()
80 if err != nil {
81 t.Fatalf("Uncompressed: %v", err)
82 }
83 defer rc.Close()
84 tr := tar.NewReader(rc)
85 saw := map[string]struct{}{}
86 for {
87 th, err := tr.Next()
88 if errors.Is(err, io.EOF) {
89 break
90 }
91 if err != nil {
92 t.Fatalf("Next: %v", err)
93 }
94 saw[th.Name] = struct{}{}
95 want, found := tc.FileMap[th.Name]
96 if !found {
97 t.Errorf("found %q, not in original map", th.Name)
98 continue
99 }
100 got, err := io.ReadAll(tr)
101 if err != nil {
102 t.Fatalf("ReadAll(%q): %v", th.Name, err)
103 }
104 if string(want) != string(got) {
105 t.Errorf("File %q: got %v, want %v", th.Name, string(got), string(want))
106 }
107 }
108 for k := range saw {
109 delete(tc.FileMap, k)
110 }
111 for k := range tc.FileMap {
112 t.Errorf("Layer did not contain %q", k)
113 }
114 })
115 t.Run(tc.Name+" is reproducible", func(t *testing.T) {
116 l1, _ := crane.Layer(tc.FileMap)
117 l2, _ := crane.Layer(tc.FileMap)
118 d1, _ := l1.Digest()
119 d2, _ := l2.Digest()
120 if d1 != d2 {
121 t.Fatalf("Non matching digests, want %q, got %q", d1, d2)
122 }
123 })
124 }
125 }
126
127 func TestImage(t *testing.T) {
128 tcs := []struct {
129 Name string
130 FileMap map[string][]byte
131 Digest string
132 }{{
133 Name: "Empty contents",
134 Digest: "sha256:98132f58b523c391a5788997327cac95e114e3a6609d01163189774510705399",
135 }, {
136 Name: "One file",
137 FileMap: map[string][]byte{
138 "/test": []byte("testy"),
139 },
140 Digest: "sha256:d905c03ac635172a96c12b8af6c90cfd028e3edaa3114b31a9e196ab38c16963",
141 }, {
142 Name: "Two files",
143 FileMap: map[string][]byte{
144 "/test": []byte("testy"),
145 "/bar": []byte("not useful"),
146 },
147 Digest: "sha256:20e7e4800e5eb167f170970936c08d9e1bcbe91372420eeb6ab8d1a07752c3a3",
148 }, {
149 Name: "Many files",
150 FileMap: map[string][]byte{
151 "/1": []byte("1"),
152 "/2": []byte("2"),
153 "/3": []byte("3"),
154 "/4": []byte("4"),
155 "/5": []byte("5"),
156 "/6": []byte("6"),
157 "/7": []byte("7"),
158 "/8": []byte("8"),
159 "/9": []byte("9"),
160 },
161 Digest: "sha256:dfca2803510c8e3b83a3151f7c035c60cfa2a8a52465b802e18b85014de361f1",
162 }}
163 for _, tc := range tcs {
164 t.Run(tc.Name, func(t *testing.T) {
165 i, err := crane.Image(tc.FileMap)
166 if err != nil {
167 t.Fatalf("Error calling image: %v", err)
168 }
169 d, err := i.Digest()
170 if err != nil {
171 t.Fatalf("Error calling digest: %v", err)
172 }
173 if d.String() != tc.Digest {
174 t.Fatalf("Incorrect digest, want %q, got %q", tc.Digest, d.String())
175 }
176 })
177 t.Run(tc.Name+" is reproducible", func(t *testing.T) {
178 i1, _ := crane.Image(tc.FileMap)
179 i2, _ := crane.Image(tc.FileMap)
180 d1, _ := i1.Digest()
181 d2, _ := i2.Digest()
182 if d1 != d2 {
183 t.Fatalf("Non matching digests, want %q, got %q", d1, d2)
184 }
185 })
186 }
187 }
188
View as plain text