fix compile error
[platform/upstream/docker-engine.git] / reference / store_test.go
1 package reference
2
3 import (
4         "bytes"
5         "io/ioutil"
6         "os"
7         "path/filepath"
8         "runtime"
9         "strings"
10         "testing"
11
12         "github.com/docker/distribution/reference"
13         "github.com/opencontainers/go-digest"
14 )
15
16 var (
17         saveLoadTestCases = map[string]digest.Digest{
18                 "registry:5000/foobar:HEAD":                                                        "sha256:470022b8af682154f57a2163d030eb369549549cba00edc69e1b99b46bb924d6",
19                 "registry:5000/foobar:alternate":                                                   "sha256:ae300ebc4a4f00693702cfb0a5e0b7bc527b353828dc86ad09fb95c8a681b793",
20                 "registry:5000/foobar:latest":                                                      "sha256:6153498b9ac00968d71b66cca4eac37e990b5f9eb50c26877eb8799c8847451b",
21                 "registry:5000/foobar:master":                                                      "sha256:6c9917af4c4e05001b346421959d7ea81b6dc9d25718466a37a6add865dfd7fc",
22                 "jess/hollywood:latest":                                                            "sha256:ae7a5519a0a55a2d4ef20ddcbd5d0ca0888a1f7ab806acc8e2a27baf46f529fe",
23                 "registry@sha256:367eb40fd0330a7e464777121e39d2f5b3e8e23a1e159342e53ab05c9e4d94e6": "sha256:24126a56805beb9711be5f4590cc2eb55ab8d4a85ebd618eed72bb19fc50631c",
24                 "busybox:latest": "sha256:91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c",
25         }
26
27         marshalledSaveLoadTestCases = []byte(`{"Repositories":{"busybox":{"busybox:latest":"sha256:91e54dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c"},"jess/hollywood":{"jess/hollywood:latest":"sha256:ae7a5519a0a55a2d4ef20ddcbd5d0ca0888a1f7ab806acc8e2a27baf46f529fe"},"registry":{"registry@sha256:367eb40fd0330a7e464777121e39d2f5b3e8e23a1e159342e53ab05c9e4d94e6":"sha256:24126a56805beb9711be5f4590cc2eb55ab8d4a85ebd618eed72bb19fc50631c"},"registry:5000/foobar":{"registry:5000/foobar:HEAD":"sha256:470022b8af682154f57a2163d030eb369549549cba00edc69e1b99b46bb924d6","registry:5000/foobar:alternate":"sha256:ae300ebc4a4f00693702cfb0a5e0b7bc527b353828dc86ad09fb95c8a681b793","registry:5000/foobar:latest":"sha256:6153498b9ac00968d71b66cca4eac37e990b5f9eb50c26877eb8799c8847451b","registry:5000/foobar:master":"sha256:6c9917af4c4e05001b346421959d7ea81b6dc9d25718466a37a6add865dfd7fc"}}}`)
28 )
29
30 func TestLoad(t *testing.T) {
31         jsonFile, err := ioutil.TempFile("", "tag-store-test")
32         if err != nil {
33                 t.Fatalf("error creating temp file: %v", err)
34         }
35         defer os.RemoveAll(jsonFile.Name())
36
37         // Write canned json to the temp file
38         _, err = jsonFile.Write(marshalledSaveLoadTestCases)
39         if err != nil {
40                 t.Fatalf("error writing to temp file: %v", err)
41         }
42         jsonFile.Close()
43
44         store, err := NewReferenceStore(jsonFile.Name(), runtime.GOOS)
45         if err != nil {
46                 t.Fatalf("error creating tag store: %v", err)
47         }
48
49         for refStr, expectedID := range saveLoadTestCases {
50                 ref, err := reference.ParseNormalizedNamed(refStr)
51                 if err != nil {
52                         t.Fatalf("failed to parse reference: %v", err)
53                 }
54                 id, err := store.Get(ref)
55                 if err != nil {
56                         t.Fatalf("could not find reference %s: %v", refStr, err)
57                 }
58                 if id != expectedID {
59                         t.Fatalf("expected %s - got %s", expectedID, id)
60                 }
61         }
62 }
63
64 func TestSave(t *testing.T) {
65         jsonFile, err := ioutil.TempFile("", "tag-store-test")
66         if err != nil {
67                 t.Fatalf("error creating temp file: %v", err)
68         }
69         _, err = jsonFile.Write([]byte(`{}`))
70         jsonFile.Close()
71         defer os.RemoveAll(jsonFile.Name())
72
73         store, err := NewReferenceStore(jsonFile.Name(), runtime.GOOS)
74         if err != nil {
75                 t.Fatalf("error creating tag store: %v", err)
76         }
77
78         for refStr, id := range saveLoadTestCases {
79                 ref, err := reference.ParseNormalizedNamed(refStr)
80                 if err != nil {
81                         t.Fatalf("failed to parse reference: %v", err)
82                 }
83                 if canonical, ok := ref.(reference.Canonical); ok {
84                         err = store.AddDigest(canonical, id, false)
85                         if err != nil {
86                                 t.Fatalf("could not add digest reference %s: %v", refStr, err)
87                         }
88                 } else {
89                         err = store.AddTag(ref, id, false)
90                         if err != nil {
91                                 t.Fatalf("could not add reference %s: %v", refStr, err)
92                         }
93                 }
94         }
95
96         jsonBytes, err := ioutil.ReadFile(jsonFile.Name())
97         if err != nil {
98                 t.Fatalf("could not read json file: %v", err)
99         }
100
101         if !bytes.Equal(jsonBytes, marshalledSaveLoadTestCases) {
102                 t.Fatalf("save output did not match expectations\nexpected:\n%s\ngot:\n%s", marshalledSaveLoadTestCases, jsonBytes)
103         }
104 }
105
106 func TestAddDeleteGet(t *testing.T) {
107         jsonFile, err := ioutil.TempFile("", "tag-store-test")
108         if err != nil {
109                 t.Fatalf("error creating temp file: %v", err)
110         }
111         _, err = jsonFile.Write([]byte(`{}`))
112         jsonFile.Close()
113         defer os.RemoveAll(jsonFile.Name())
114
115         store, err := NewReferenceStore(jsonFile.Name(), runtime.GOOS)
116         if err != nil {
117                 t.Fatalf("error creating tag store: %v", err)
118         }
119
120         testImageID1 := digest.Digest("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9c")
121         testImageID2 := digest.Digest("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9d")
122         testImageID3 := digest.Digest("sha256:9655aef5fd742a1b4e1b7b163aa9f1c76c186304bf39102283d80927c916ca9e")
123
124         // Try adding a reference with no tag or digest
125         nameOnly, err := reference.ParseNormalizedNamed("username/repo")
126         if err != nil {
127                 t.Fatalf("could not parse reference: %v", err)
128         }
129         if err = store.AddTag(nameOnly, testImageID1, false); err != nil {
130                 t.Fatalf("error adding to store: %v", err)
131         }
132
133         // Add a few references
134         ref1, err := reference.ParseNormalizedNamed("username/repo1:latest")
135         if err != nil {
136                 t.Fatalf("could not parse reference: %v", err)
137         }
138         if err = store.AddTag(ref1, testImageID1, false); err != nil {
139                 t.Fatalf("error adding to store: %v", err)
140         }
141
142         ref2, err := reference.ParseNormalizedNamed("username/repo1:old")
143         if err != nil {
144                 t.Fatalf("could not parse reference: %v", err)
145         }
146         if err = store.AddTag(ref2, testImageID2, false); err != nil {
147                 t.Fatalf("error adding to store: %v", err)
148         }
149
150         ref3, err := reference.ParseNormalizedNamed("username/repo1:alias")
151         if err != nil {
152                 t.Fatalf("could not parse reference: %v", err)
153         }
154         if err = store.AddTag(ref3, testImageID1, false); err != nil {
155                 t.Fatalf("error adding to store: %v", err)
156         }
157
158         ref4, err := reference.ParseNormalizedNamed("username/repo2:latest")
159         if err != nil {
160                 t.Fatalf("could not parse reference: %v", err)
161         }
162         if err = store.AddTag(ref4, testImageID2, false); err != nil {
163                 t.Fatalf("error adding to store: %v", err)
164         }
165
166         ref5, err := reference.ParseNormalizedNamed("username/repo3@sha256:58153dfb11794fad694460162bf0cb0a4fa710cfa3f60979c177d920813e267c")
167         if err != nil {
168                 t.Fatalf("could not parse reference: %v", err)
169         }
170         if err = store.AddDigest(ref5.(reference.Canonical), testImageID2, false); err != nil {
171                 t.Fatalf("error adding to store: %v", err)
172         }
173
174         // Attempt to overwrite with force == false
175         if err = store.AddTag(ref4, testImageID3, false); err == nil || !strings.HasPrefix(err.Error(), "Conflict:") {
176                 t.Fatalf("did not get expected error on overwrite attempt - got %v", err)
177         }
178         // Repeat to overwrite with force == true
179         if err = store.AddTag(ref4, testImageID3, true); err != nil {
180                 t.Fatalf("failed to force tag overwrite: %v", err)
181         }
182
183         // Check references so far
184         id, err := store.Get(nameOnly)
185         if err != nil {
186                 t.Fatalf("Get returned error: %v", err)
187         }
188         if id != testImageID1 {
189                 t.Fatalf("id mismatch: got %s instead of %s", id.String(), testImageID1.String())
190         }
191
192         id, err = store.Get(ref1)
193         if err != nil {
194                 t.Fatalf("Get returned error: %v", err)
195         }
196         if id != testImageID1 {
197                 t.Fatalf("id mismatch: got %s instead of %s", id.String(), testImageID1.String())
198         }
199
200         id, err = store.Get(ref2)
201         if err != nil {
202                 t.Fatalf("Get returned error: %v", err)
203         }
204         if id != testImageID2 {
205                 t.Fatalf("id mismatch: got %s instead of %s", id.String(), testImageID2.String())
206         }
207
208         id, err = store.Get(ref3)
209         if err != nil {
210                 t.Fatalf("Get returned error: %v", err)
211         }
212         if id != testImageID1 {
213                 t.Fatalf("id mismatch: got %s instead of %s", id.String(), testImageID1.String())
214         }
215
216         id, err = store.Get(ref4)
217         if err != nil {
218                 t.Fatalf("Get returned error: %v", err)
219         }
220         if id != testImageID3 {
221                 t.Fatalf("id mismatch: got %s instead of %s", id.String(), testImageID3.String())
222         }
223
224         id, err = store.Get(ref5)
225         if err != nil {
226                 t.Fatalf("Get returned error: %v", err)
227         }
228         if id != testImageID2 {
229                 t.Fatalf("id mismatch: got %s instead of %s", id.String(), testImageID3.String())
230         }
231
232         // Get should return ErrDoesNotExist for a nonexistent repo
233         nonExistRepo, err := reference.ParseNormalizedNamed("username/nonexistrepo:latest")
234         if err != nil {
235                 t.Fatalf("could not parse reference: %v", err)
236         }
237         if _, err = store.Get(nonExistRepo); err != ErrDoesNotExist {
238                 t.Fatal("Expected ErrDoesNotExist from Get")
239         }
240
241         // Get should return ErrDoesNotExist for a nonexistent tag
242         nonExistTag, err := reference.ParseNormalizedNamed("username/repo1:nonexist")
243         if err != nil {
244                 t.Fatalf("could not parse reference: %v", err)
245         }
246         if _, err = store.Get(nonExistTag); err != ErrDoesNotExist {
247                 t.Fatal("Expected ErrDoesNotExist from Get")
248         }
249
250         // Check References
251         refs := store.References(testImageID1)
252         if len(refs) != 3 {
253                 t.Fatal("unexpected number of references")
254         }
255         // Looking for the references in this order verifies that they are
256         // returned lexically sorted.
257         if refs[0].String() != ref3.String() {
258                 t.Fatalf("unexpected reference: %v", refs[0].String())
259         }
260         if refs[1].String() != ref1.String() {
261                 t.Fatalf("unexpected reference: %v", refs[1].String())
262         }
263         if refs[2].String() != nameOnly.String()+":latest" {
264                 t.Fatalf("unexpected reference: %v", refs[2].String())
265         }
266
267         // Check ReferencesByName
268         repoName, err := reference.ParseNormalizedNamed("username/repo1")
269         if err != nil {
270                 t.Fatalf("could not parse reference: %v", err)
271         }
272         associations := store.ReferencesByName(repoName)
273         if len(associations) != 3 {
274                 t.Fatal("unexpected number of associations")
275         }
276         // Looking for the associations in this order verifies that they are
277         // returned lexically sorted.
278         if associations[0].Ref.String() != ref3.String() {
279                 t.Fatalf("unexpected reference: %v", associations[0].Ref.String())
280         }
281         if associations[0].ID != testImageID1 {
282                 t.Fatalf("unexpected reference: %v", associations[0].Ref.String())
283         }
284         if associations[1].Ref.String() != ref1.String() {
285                 t.Fatalf("unexpected reference: %v", associations[1].Ref.String())
286         }
287         if associations[1].ID != testImageID1 {
288                 t.Fatalf("unexpected reference: %v", associations[1].Ref.String())
289         }
290         if associations[2].Ref.String() != ref2.String() {
291                 t.Fatalf("unexpected reference: %v", associations[2].Ref.String())
292         }
293         if associations[2].ID != testImageID2 {
294                 t.Fatalf("unexpected reference: %v", associations[2].Ref.String())
295         }
296
297         // Delete should return ErrDoesNotExist for a nonexistent repo
298         if _, err = store.Delete(nonExistRepo); err != ErrDoesNotExist {
299                 t.Fatal("Expected ErrDoesNotExist from Delete")
300         }
301
302         // Delete should return ErrDoesNotExist for a nonexistent tag
303         if _, err = store.Delete(nonExistTag); err != ErrDoesNotExist {
304                 t.Fatal("Expected ErrDoesNotExist from Delete")
305         }
306
307         // Delete a few references
308         if deleted, err := store.Delete(ref1); err != nil || deleted != true {
309                 t.Fatal("Delete failed")
310         }
311         if _, err := store.Get(ref1); err != ErrDoesNotExist {
312                 t.Fatal("Expected ErrDoesNotExist from Get")
313         }
314         if deleted, err := store.Delete(ref5); err != nil || deleted != true {
315                 t.Fatal("Delete failed")
316         }
317         if _, err := store.Get(ref5); err != ErrDoesNotExist {
318                 t.Fatal("Expected ErrDoesNotExist from Get")
319         }
320         if deleted, err := store.Delete(nameOnly); err != nil || deleted != true {
321                 t.Fatal("Delete failed")
322         }
323         if _, err := store.Get(nameOnly); err != ErrDoesNotExist {
324                 t.Fatal("Expected ErrDoesNotExist from Get")
325         }
326 }
327
328 func TestInvalidTags(t *testing.T) {
329         tmpDir, err := ioutil.TempDir("", "tag-store-test")
330         defer os.RemoveAll(tmpDir)
331
332         store, err := NewReferenceStore(filepath.Join(tmpDir, "repositories.json"), runtime.GOOS)
333         if err != nil {
334                 t.Fatalf("error creating tag store: %v", err)
335         }
336         id := digest.Digest("sha256:470022b8af682154f57a2163d030eb369549549cba00edc69e1b99b46bb924d6")
337
338         // sha256 as repo name
339         ref, err := reference.ParseNormalizedNamed("sha256:abc")
340         if err != nil {
341                 t.Fatal(err)
342         }
343         err = store.AddTag(ref, id, true)
344         if err == nil {
345                 t.Fatalf("expected setting tag %q to fail", ref)
346         }
347
348         // setting digest as a tag
349         ref, err = reference.ParseNormalizedNamed("registry@sha256:367eb40fd0330a7e464777121e39d2f5b3e8e23a1e159342e53ab05c9e4d94e6")
350         if err != nil {
351                 t.Fatal(err)
352         }
353         err = store.AddTag(ref, id, true)
354         if err == nil {
355                 t.Fatalf("expected setting tag %q to fail", ref)
356         }
357
358 }