github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/image/fs_test.go (about) 1 package image 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "crypto/sha256" 7 "encoding/hex" 8 "errors" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "testing" 13 14 "github.com/docker/distribution/digest" 15 ) 16 17 func TestFSGetSet(t *testing.T) { 18 tmpdir, err := ioutil.TempDir("", "images-fs-store") 19 if err != nil { 20 t.Fatal(err) 21 } 22 defer os.RemoveAll(tmpdir) 23 fs, err := NewFSStoreBackend(tmpdir) 24 if err != nil { 25 t.Fatal(err) 26 } 27 28 testGetSet(t, fs) 29 } 30 31 func TestFSGetInvalidData(t *testing.T) { 32 tmpdir, err := ioutil.TempDir("", "images-fs-store") 33 if err != nil { 34 t.Fatal(err) 35 } 36 defer os.RemoveAll(tmpdir) 37 fs, err := NewFSStoreBackend(tmpdir) 38 if err != nil { 39 t.Fatal(err) 40 } 41 42 id, err := fs.Set([]byte("foobar")) 43 if err != nil { 44 t.Fatal(err) 45 } 46 47 dgst := digest.Digest(id) 48 49 if err := ioutil.WriteFile(filepath.Join(tmpdir, contentDirName, string(dgst.Algorithm()), dgst.Hex()), []byte("foobar2"), 0600); err != nil { 50 t.Fatal(err) 51 } 52 53 _, err = fs.Get(id) 54 if err == nil { 55 t.Fatal("Expected get to fail after data modification.") 56 } 57 } 58 59 func TestFSInvalidSet(t *testing.T) { 60 tmpdir, err := ioutil.TempDir("", "images-fs-store") 61 if err != nil { 62 t.Fatal(err) 63 } 64 defer os.RemoveAll(tmpdir) 65 fs, err := NewFSStoreBackend(tmpdir) 66 if err != nil { 67 t.Fatal(err) 68 } 69 70 id, err := digest.FromBytes([]byte("foobar")) 71 if err != nil { 72 t.Fatal(err) 73 } 74 err = os.Mkdir(filepath.Join(tmpdir, contentDirName, string(id.Algorithm()), id.Hex()), 0700) 75 if err != nil { 76 t.Fatal(err) 77 } 78 79 _, err = fs.Set([]byte("foobar")) 80 if err == nil { 81 t.Fatal("Expecting error from invalid filesystem data.") 82 } 83 } 84 85 func TestFSInvalidRoot(t *testing.T) { 86 tmpdir, err := ioutil.TempDir("", "images-fs-store") 87 if err != nil { 88 t.Fatal(err) 89 } 90 defer os.RemoveAll(tmpdir) 91 92 tcases := []struct { 93 root, invalidFile string 94 }{ 95 {"root", "root"}, 96 {"root", "root/content"}, 97 {"root", "root/metadata"}, 98 } 99 100 for _, tc := range tcases { 101 root := filepath.Join(tmpdir, tc.root) 102 filePath := filepath.Join(tmpdir, tc.invalidFile) 103 err := os.MkdirAll(filepath.Dir(filePath), 0700) 104 if err != nil { 105 t.Fatal(err) 106 } 107 f, err := os.Create(filePath) 108 if err != nil { 109 t.Fatal(err) 110 } 111 f.Close() 112 113 _, err = NewFSStoreBackend(root) 114 if err == nil { 115 t.Fatalf("Expected error from root %q and invlid file %q", tc.root, tc.invalidFile) 116 } 117 118 os.RemoveAll(root) 119 } 120 121 } 122 123 func testMetadataGetSet(t *testing.T, store StoreBackend) { 124 id, err := store.Set([]byte("foo")) 125 if err != nil { 126 t.Fatal(err) 127 } 128 id2, err := store.Set([]byte("bar")) 129 if err != nil { 130 t.Fatal(err) 131 } 132 133 tcases := []struct { 134 id ID 135 key string 136 value []byte 137 }{ 138 {id, "tkey", []byte("tval1")}, 139 {id, "tkey2", []byte("tval2")}, 140 {id2, "tkey", []byte("tval3")}, 141 } 142 143 for _, tc := range tcases { 144 err = store.SetMetadata(tc.id, tc.key, tc.value) 145 if err != nil { 146 t.Fatal(err) 147 } 148 149 actual, err := store.GetMetadata(tc.id, tc.key) 150 if err != nil { 151 t.Fatal(err) 152 } 153 if bytes.Compare(actual, tc.value) != 0 { 154 t.Fatalf("Metadata expected %q, got %q", tc.value, actual) 155 } 156 } 157 158 _, err = store.GetMetadata(id2, "tkey2") 159 if err == nil { 160 t.Fatal("Expected error for getting metadata for unknown key") 161 } 162 163 id3, err := digest.FromBytes([]byte("baz")) 164 if err != nil { 165 t.Fatal(err) 166 } 167 168 err = store.SetMetadata(ID(id3), "tkey", []byte("tval")) 169 if err == nil { 170 t.Fatal("Expected error for setting metadata for unknown ID.") 171 } 172 173 _, err = store.GetMetadata(ID(id3), "tkey") 174 if err == nil { 175 t.Fatal("Expected error for getting metadata for unknown ID.") 176 } 177 } 178 179 func TestFSMetadataGetSet(t *testing.T) { 180 tmpdir, err := ioutil.TempDir("", "images-fs-store") 181 if err != nil { 182 t.Fatal(err) 183 } 184 defer os.RemoveAll(tmpdir) 185 fs, err := NewFSStoreBackend(tmpdir) 186 if err != nil { 187 t.Fatal(err) 188 } 189 190 testMetadataGetSet(t, fs) 191 } 192 193 func TestFSDelete(t *testing.T) { 194 tmpdir, err := ioutil.TempDir("", "images-fs-store") 195 if err != nil { 196 t.Fatal(err) 197 } 198 defer os.RemoveAll(tmpdir) 199 fs, err := NewFSStoreBackend(tmpdir) 200 if err != nil { 201 t.Fatal(err) 202 } 203 204 testDelete(t, fs) 205 } 206 207 func TestFSWalker(t *testing.T) { 208 tmpdir, err := ioutil.TempDir("", "images-fs-store") 209 if err != nil { 210 t.Fatal(err) 211 } 212 defer os.RemoveAll(tmpdir) 213 fs, err := NewFSStoreBackend(tmpdir) 214 if err != nil { 215 t.Fatal(err) 216 } 217 218 testWalker(t, fs) 219 } 220 221 func TestFSInvalidWalker(t *testing.T) { 222 tmpdir, err := ioutil.TempDir("", "images-fs-store") 223 if err != nil { 224 t.Fatal(err) 225 } 226 defer os.RemoveAll(tmpdir) 227 fs, err := NewFSStoreBackend(tmpdir) 228 if err != nil { 229 t.Fatal(err) 230 } 231 232 fooID, err := fs.Set([]byte("foo")) 233 if err != nil { 234 t.Fatal(err) 235 } 236 237 if err := ioutil.WriteFile(filepath.Join(tmpdir, contentDirName, "sha256/foobar"), []byte("foobar"), 0600); err != nil { 238 t.Fatal(err) 239 } 240 241 n := 0 242 err = fs.Walk(func(id ID) error { 243 if id != fooID { 244 t.Fatalf("Invalid walker ID %q, expected %q", id, fooID) 245 } 246 n++ 247 return nil 248 }) 249 if err != nil { 250 t.Fatalf("Invalid data should not have caused walker error, got %v", err) 251 } 252 if n != 1 { 253 t.Fatalf("Expected 1 walk initialization, got %d", n) 254 } 255 } 256 257 func testGetSet(t *testing.T, store StoreBackend) { 258 type tcase struct { 259 input []byte 260 expected ID 261 } 262 tcases := []tcase{ 263 {[]byte("foobar"), ID("sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2")}, 264 } 265 266 randomInput := make([]byte, 8*1024) 267 _, err := rand.Read(randomInput) 268 if err != nil { 269 t.Fatal(err) 270 } 271 // skipping use of digest pkg because its used by the implementation 272 h := sha256.New() 273 _, err = h.Write(randomInput) 274 if err != nil { 275 t.Fatal(err) 276 } 277 tcases = append(tcases, tcase{ 278 input: randomInput, 279 expected: ID("sha256:" + hex.EncodeToString(h.Sum(nil))), 280 }) 281 282 for _, tc := range tcases { 283 id, err := store.Set([]byte(tc.input)) 284 if err != nil { 285 t.Fatal(err) 286 } 287 if id != tc.expected { 288 t.Fatalf("Expected ID %q, got %q", tc.expected, id) 289 } 290 } 291 292 for _, emptyData := range [][]byte{nil, {}} { 293 _, err := store.Set(emptyData) 294 if err == nil { 295 t.Fatal("Expected error for nil input.") 296 } 297 } 298 299 for _, tc := range tcases { 300 data, err := store.Get(tc.expected) 301 if err != nil { 302 t.Fatal(err) 303 } 304 if bytes.Compare(data, tc.input) != 0 { 305 t.Fatalf("Expected data %q, got %q", tc.input, data) 306 } 307 } 308 309 for _, key := range []ID{"foobar:abc", "sha256:abc", "sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2a"} { 310 _, err := store.Get(key) 311 if err == nil { 312 t.Fatalf("Expected error for ID %q.", key) 313 } 314 } 315 316 } 317 318 func testDelete(t *testing.T, store StoreBackend) { 319 id, err := store.Set([]byte("foo")) 320 if err != nil { 321 t.Fatal(err) 322 } 323 id2, err := store.Set([]byte("bar")) 324 if err != nil { 325 t.Fatal(err) 326 } 327 328 err = store.Delete(id) 329 if err != nil { 330 t.Fatal(err) 331 } 332 333 _, err = store.Get(id) 334 if err == nil { 335 t.Fatalf("Expected getting deleted item %q to fail", id) 336 } 337 _, err = store.Get(id2) 338 if err != nil { 339 t.Fatal(err) 340 } 341 342 err = store.Delete(id2) 343 if err != nil { 344 t.Fatal(err) 345 } 346 _, err = store.Get(id2) 347 if err == nil { 348 t.Fatalf("Expected getting deleted item %q to fail", id2) 349 } 350 } 351 352 func testWalker(t *testing.T, store StoreBackend) { 353 id, err := store.Set([]byte("foo")) 354 if err != nil { 355 t.Fatal(err) 356 } 357 id2, err := store.Set([]byte("bar")) 358 if err != nil { 359 t.Fatal(err) 360 } 361 362 tcases := make(map[ID]struct{}) 363 tcases[id] = struct{}{} 364 tcases[id2] = struct{}{} 365 n := 0 366 err = store.Walk(func(id ID) error { 367 delete(tcases, id) 368 n++ 369 return nil 370 }) 371 if err != nil { 372 t.Fatal(err) 373 } 374 375 if n != 2 { 376 t.Fatalf("Expected 2 walk initializations, got %d", n) 377 } 378 if len(tcases) != 0 { 379 t.Fatalf("Expected empty unwalked set, got %+v", tcases) 380 } 381 382 // stop on error 383 tcases = make(map[ID]struct{}) 384 tcases[id] = struct{}{} 385 err = store.Walk(func(id ID) error { 386 return errors.New("") 387 }) 388 if err == nil { 389 t.Fatalf("Exected error from walker.") 390 } 391 }