github.com/resin-io/docker@v1.13.1/image/store_test.go (about) 1 package image 2 3 import ( 4 "io/ioutil" 5 "os" 6 "testing" 7 8 "github.com/docker/distribution/digest" 9 "github.com/docker/docker/layer" 10 ) 11 12 func TestRestore(t *testing.T) { 13 tmpdir, err := ioutil.TempDir("", "images-fs-store") 14 if err != nil { 15 t.Fatal(err) 16 } 17 defer os.RemoveAll(tmpdir) 18 fs, err := NewFSStoreBackend(tmpdir) 19 if err != nil { 20 t.Fatal(err) 21 } 22 23 id1, err := fs.Set([]byte(`{"comment": "abc", "rootfs": {"type": "layers"}}`)) 24 if err != nil { 25 t.Fatal(err) 26 } 27 _, err = fs.Set([]byte(`invalid`)) 28 if err != nil { 29 t.Fatal(err) 30 } 31 id2, err := fs.Set([]byte(`{"comment": "def", "rootfs": {"type": "layers", "diff_ids": ["2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"]}}`)) 32 if err != nil { 33 t.Fatal(err) 34 } 35 err = fs.SetMetadata(id2, "parent", []byte(id1)) 36 if err != nil { 37 t.Fatal(err) 38 } 39 40 is, err := NewImageStore(fs, &mockLayerGetReleaser{}) 41 if err != nil { 42 t.Fatal(err) 43 } 44 45 imgs := is.Map() 46 if actual, expected := len(imgs), 2; actual != expected { 47 t.Fatalf("invalid images length, expected 2, got %q", len(imgs)) 48 } 49 50 img1, err := is.Get(ID(id1)) 51 if err != nil { 52 t.Fatal(err) 53 } 54 55 if actual, expected := img1.computedID, ID(id1); actual != expected { 56 t.Fatalf("invalid image ID: expected %q, got %q", expected, actual) 57 } 58 59 if actual, expected := img1.computedID.String(), string(id1); actual != expected { 60 t.Fatalf("invalid image ID string: expected %q, got %q", expected, actual) 61 } 62 63 img2, err := is.Get(ID(id2)) 64 if err != nil { 65 t.Fatal(err) 66 } 67 68 if actual, expected := img1.Comment, "abc"; actual != expected { 69 t.Fatalf("invalid comment for image1: expected %q, got %q", expected, actual) 70 } 71 72 if actual, expected := img2.Comment, "def"; actual != expected { 73 t.Fatalf("invalid comment for image2: expected %q, got %q", expected, actual) 74 } 75 76 p, err := is.GetParent(ID(id1)) 77 if err == nil { 78 t.Fatal("expected error for getting parent") 79 } 80 81 p, err = is.GetParent(ID(id2)) 82 if err != nil { 83 t.Fatal(err) 84 } 85 if actual, expected := p, ID(id1); actual != expected { 86 t.Fatalf("invalid parent: expected %q, got %q", expected, actual) 87 } 88 89 children := is.Children(ID(id1)) 90 if len(children) != 1 { 91 t.Fatalf("invalid children length: %q", len(children)) 92 } 93 if actual, expected := children[0], ID(id2); actual != expected { 94 t.Fatalf("invalid child for id1: expected %q, got %q", expected, actual) 95 } 96 97 heads := is.Heads() 98 if actual, expected := len(heads), 1; actual != expected { 99 t.Fatalf("invalid images length: expected %q, got %q", expected, actual) 100 } 101 102 sid1, err := is.Search(string(id1)[:10]) 103 if err != nil { 104 t.Fatal(err) 105 } 106 if actual, expected := sid1, ID(id1); actual != expected { 107 t.Fatalf("searched ID mismatch: expected %q, got %q", expected, actual) 108 } 109 110 sid1, err = is.Search(digest.Digest(id1).Hex()[:6]) 111 if err != nil { 112 t.Fatal(err) 113 } 114 if actual, expected := sid1, ID(id1); actual != expected { 115 t.Fatalf("searched ID mismatch: expected %q, got %q", expected, actual) 116 } 117 118 invalidPattern := digest.Digest(id1).Hex()[1:6] 119 _, err = is.Search(invalidPattern) 120 if err == nil { 121 t.Fatalf("expected search for %q to fail", invalidPattern) 122 } 123 124 } 125 126 func TestAddDelete(t *testing.T) { 127 tmpdir, err := ioutil.TempDir("", "images-fs-store") 128 if err != nil { 129 t.Fatal(err) 130 } 131 defer os.RemoveAll(tmpdir) 132 fs, err := NewFSStoreBackend(tmpdir) 133 if err != nil { 134 t.Fatal(err) 135 } 136 137 is, err := NewImageStore(fs, &mockLayerGetReleaser{}) 138 if err != nil { 139 t.Fatal(err) 140 } 141 142 id1, err := is.Create([]byte(`{"comment": "abc", "rootfs": {"type": "layers", "diff_ids": ["2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"]}}`)) 143 if err != nil { 144 t.Fatal(err) 145 } 146 147 if actual, expected := id1, ID("sha256:8d25a9c45df515f9d0fe8e4a6b1c64dd3b965a84790ddbcc7954bb9bc89eb993"); actual != expected { 148 t.Fatalf("create ID mismatch: expected %q, got %q", expected, actual) 149 } 150 151 img, err := is.Get(id1) 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 if actual, expected := img.Comment, "abc"; actual != expected { 157 t.Fatalf("invalid comment in image: expected %q, got %q", expected, actual) 158 } 159 160 id2, err := is.Create([]byte(`{"comment": "def", "rootfs": {"type": "layers", "diff_ids": ["2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"]}}`)) 161 if err != nil { 162 t.Fatal(err) 163 } 164 165 err = is.SetParent(id2, id1) 166 if err != nil { 167 t.Fatal(err) 168 } 169 170 pid1, err := is.GetParent(id2) 171 if err != nil { 172 t.Fatal(err) 173 } 174 if actual, expected := pid1, id1; actual != expected { 175 t.Fatalf("invalid parent for image: expected %q, got %q", expected, actual) 176 } 177 178 _, err = is.Delete(id1) 179 if err != nil { 180 t.Fatal(err) 181 } 182 _, err = is.Get(id1) 183 if err == nil { 184 t.Fatalf("expected get for deleted image %q to fail", id1) 185 } 186 _, err = is.Get(id2) 187 if err != nil { 188 t.Fatal(err) 189 } 190 pid1, err = is.GetParent(id2) 191 if err == nil { 192 t.Fatalf("expected parent check for image %q to fail, got %q", id2, pid1) 193 } 194 195 } 196 197 func TestSearchAfterDelete(t *testing.T) { 198 tmpdir, err := ioutil.TempDir("", "images-fs-store") 199 if err != nil { 200 t.Fatal(err) 201 } 202 defer os.RemoveAll(tmpdir) 203 fs, err := NewFSStoreBackend(tmpdir) 204 if err != nil { 205 t.Fatal(err) 206 } 207 208 is, err := NewImageStore(fs, &mockLayerGetReleaser{}) 209 if err != nil { 210 t.Fatal(err) 211 } 212 213 id, err := is.Create([]byte(`{"comment": "abc", "rootfs": {"type": "layers"}}`)) 214 if err != nil { 215 t.Fatal(err) 216 } 217 218 id1, err := is.Search(string(id)[:15]) 219 if err != nil { 220 t.Fatal(err) 221 } 222 223 if actual, expected := id1, id; expected != actual { 224 t.Fatalf("wrong id returned from search: expected %q, got %q", expected, actual) 225 } 226 227 if _, err := is.Delete(id); err != nil { 228 t.Fatal(err) 229 } 230 231 if _, err := is.Search(string(id)[:15]); err == nil { 232 t.Fatal("expected search after deletion to fail") 233 } 234 } 235 236 func TestParentReset(t *testing.T) { 237 tmpdir, err := ioutil.TempDir("", "images-fs-store") 238 if err != nil { 239 t.Fatal(err) 240 } 241 defer os.RemoveAll(tmpdir) 242 fs, err := NewFSStoreBackend(tmpdir) 243 if err != nil { 244 t.Fatal(err) 245 } 246 247 is, err := NewImageStore(fs, &mockLayerGetReleaser{}) 248 if err != nil { 249 t.Fatal(err) 250 } 251 252 id, err := is.Create([]byte(`{"comment": "abc1", "rootfs": {"type": "layers"}}`)) 253 if err != nil { 254 t.Fatal(err) 255 } 256 257 id2, err := is.Create([]byte(`{"comment": "abc2", "rootfs": {"type": "layers"}}`)) 258 if err != nil { 259 t.Fatal(err) 260 } 261 262 id3, err := is.Create([]byte(`{"comment": "abc3", "rootfs": {"type": "layers"}}`)) 263 if err != nil { 264 t.Fatal(err) 265 } 266 267 if err := is.SetParent(id, id2); err != nil { 268 t.Fatal(err) 269 } 270 271 ids := is.Children(id2) 272 if actual, expected := len(ids), 1; expected != actual { 273 t.Fatalf("wrong number of children: %d, got %d", expected, actual) 274 } 275 276 if err := is.SetParent(id, id3); err != nil { 277 t.Fatal(err) 278 } 279 280 ids = is.Children(id2) 281 if actual, expected := len(ids), 0; expected != actual { 282 t.Fatalf("wrong number of children after parent reset: %d, got %d", expected, actual) 283 } 284 285 ids = is.Children(id3) 286 if actual, expected := len(ids), 1; expected != actual { 287 t.Fatalf("wrong number of children after parent reset: %d, got %d", expected, actual) 288 } 289 290 } 291 292 type mockLayerGetReleaser struct{} 293 294 func (ls *mockLayerGetReleaser) Get(layer.ChainID) (layer.Layer, error) { 295 return nil, nil 296 } 297 298 func (ls *mockLayerGetReleaser) Release(layer.Layer) ([]layer.Metadata, error) { 299 return nil, nil 300 }