github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/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/docker/pkg/testutil" 15 "github.com/opencontainers/go-digest" 16 "github.com/stretchr/testify/assert" 17 ) 18 19 func defaultFSStoreBackend(t *testing.T) (StoreBackend, func()) { 20 tmpdir, err := ioutil.TempDir("", "images-fs-store") 21 assert.NoError(t, err) 22 23 fsBackend, err := NewFSStoreBackend(tmpdir) 24 assert.NoError(t, err) 25 26 return fsBackend, func() { os.RemoveAll(tmpdir) } 27 } 28 29 func TestFSGetInvalidData(t *testing.T) { 30 store, cleanup := defaultFSStoreBackend(t) 31 defer cleanup() 32 33 id, err := store.Set([]byte("foobar")) 34 assert.NoError(t, err) 35 36 dgst := digest.Digest(id) 37 38 err = ioutil.WriteFile(filepath.Join(store.(*fs).root, contentDirName, string(dgst.Algorithm()), dgst.Hex()), []byte("foobar2"), 0600) 39 assert.NoError(t, err) 40 41 _, err = store.Get(id) 42 testutil.ErrorContains(t, err, "failed to verify") 43 } 44 45 func TestFSInvalidSet(t *testing.T) { 46 store, cleanup := defaultFSStoreBackend(t) 47 defer cleanup() 48 49 id := digest.FromBytes([]byte("foobar")) 50 err := os.Mkdir(filepath.Join(store.(*fs).root, contentDirName, string(id.Algorithm()), id.Hex()), 0700) 51 assert.NoError(t, err) 52 53 _, err = store.Set([]byte("foobar")) 54 testutil.ErrorContains(t, err, "failed to write digest data") 55 } 56 57 func TestFSInvalidRoot(t *testing.T) { 58 tmpdir, err := ioutil.TempDir("", "images-fs-store") 59 assert.NoError(t, err) 60 defer os.RemoveAll(tmpdir) 61 62 tcases := []struct { 63 root, invalidFile string 64 }{ 65 {"root", "root"}, 66 {"root", "root/content"}, 67 {"root", "root/metadata"}, 68 } 69 70 for _, tc := range tcases { 71 root := filepath.Join(tmpdir, tc.root) 72 filePath := filepath.Join(tmpdir, tc.invalidFile) 73 err := os.MkdirAll(filepath.Dir(filePath), 0700) 74 assert.NoError(t, err) 75 76 f, err := os.Create(filePath) 77 assert.NoError(t, err) 78 f.Close() 79 80 _, err = NewFSStoreBackend(root) 81 testutil.ErrorContains(t, err, "failed to create storage backend") 82 83 os.RemoveAll(root) 84 } 85 86 } 87 88 func TestFSMetadataGetSet(t *testing.T) { 89 store, cleanup := defaultFSStoreBackend(t) 90 defer cleanup() 91 92 id, err := store.Set([]byte("foo")) 93 assert.NoError(t, err) 94 95 id2, err := store.Set([]byte("bar")) 96 assert.NoError(t, err) 97 98 tcases := []struct { 99 id digest.Digest 100 key string 101 value []byte 102 }{ 103 {id, "tkey", []byte("tval1")}, 104 {id, "tkey2", []byte("tval2")}, 105 {id2, "tkey", []byte("tval3")}, 106 } 107 108 for _, tc := range tcases { 109 err = store.SetMetadata(tc.id, tc.key, tc.value) 110 assert.NoError(t, err) 111 112 actual, err := store.GetMetadata(tc.id, tc.key) 113 assert.NoError(t, err) 114 115 if bytes.Compare(actual, tc.value) != 0 { 116 t.Fatalf("Metadata expected %q, got %q", tc.value, actual) 117 } 118 } 119 120 _, err = store.GetMetadata(id2, "tkey2") 121 testutil.ErrorContains(t, err, "failed to read metadata") 122 123 id3 := digest.FromBytes([]byte("baz")) 124 err = store.SetMetadata(id3, "tkey", []byte("tval")) 125 testutil.ErrorContains(t, err, "failed to get digest") 126 127 _, err = store.GetMetadata(id3, "tkey") 128 testutil.ErrorContains(t, err, "failed to get digest") 129 } 130 131 func TestFSInvalidWalker(t *testing.T) { 132 store, cleanup := defaultFSStoreBackend(t) 133 defer cleanup() 134 135 fooID, err := store.Set([]byte("foo")) 136 assert.NoError(t, err) 137 138 err = ioutil.WriteFile(filepath.Join(store.(*fs).root, contentDirName, "sha256/foobar"), []byte("foobar"), 0600) 139 assert.NoError(t, err) 140 141 n := 0 142 err = store.Walk(func(id digest.Digest) error { 143 assert.Equal(t, fooID, id) 144 n++ 145 return nil 146 }) 147 assert.NoError(t, err) 148 assert.Equal(t, 1, n) 149 } 150 151 func TestFSGetSet(t *testing.T) { 152 store, cleanup := defaultFSStoreBackend(t) 153 defer cleanup() 154 155 type tcase struct { 156 input []byte 157 expected digest.Digest 158 } 159 tcases := []tcase{ 160 {[]byte("foobar"), digest.Digest("sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2")}, 161 } 162 163 randomInput := make([]byte, 8*1024) 164 _, err := rand.Read(randomInput) 165 assert.NoError(t, err) 166 167 // skipping use of digest pkg because it is used by the implementation 168 h := sha256.New() 169 _, err = h.Write(randomInput) 170 assert.NoError(t, err) 171 172 tcases = append(tcases, tcase{ 173 input: randomInput, 174 expected: digest.Digest("sha256:" + hex.EncodeToString(h.Sum(nil))), 175 }) 176 177 for _, tc := range tcases { 178 id, err := store.Set([]byte(tc.input)) 179 assert.NoError(t, err) 180 assert.Equal(t, tc.expected, id) 181 } 182 183 for _, tc := range tcases { 184 data, err := store.Get(tc.expected) 185 assert.NoError(t, err) 186 if bytes.Compare(data, tc.input) != 0 { 187 t.Fatalf("expected data %q, got %q", tc.input, data) 188 } 189 } 190 } 191 192 func TestFSGetUnsetKey(t *testing.T) { 193 store, cleanup := defaultFSStoreBackend(t) 194 defer cleanup() 195 196 for _, key := range []digest.Digest{"foobar:abc", "sha256:abc", "sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2a"} { 197 _, err := store.Get(key) 198 testutil.ErrorContains(t, err, "failed to get digest") 199 } 200 } 201 202 func TestFSGetEmptyData(t *testing.T) { 203 store, cleanup := defaultFSStoreBackend(t) 204 defer cleanup() 205 206 for _, emptyData := range [][]byte{nil, {}} { 207 _, err := store.Set(emptyData) 208 testutil.ErrorContains(t, err, "invalid empty data") 209 } 210 } 211 212 func TestFSDelete(t *testing.T) { 213 store, cleanup := defaultFSStoreBackend(t) 214 defer cleanup() 215 216 id, err := store.Set([]byte("foo")) 217 assert.NoError(t, err) 218 219 id2, err := store.Set([]byte("bar")) 220 assert.NoError(t, err) 221 222 err = store.Delete(id) 223 assert.NoError(t, err) 224 225 _, err = store.Get(id) 226 testutil.ErrorContains(t, err, "failed to get digest") 227 228 _, err = store.Get(id2) 229 assert.NoError(t, err) 230 231 err = store.Delete(id2) 232 assert.NoError(t, err) 233 234 _, err = store.Get(id2) 235 testutil.ErrorContains(t, err, "failed to get digest") 236 } 237 238 func TestFSWalker(t *testing.T) { 239 store, cleanup := defaultFSStoreBackend(t) 240 defer cleanup() 241 242 id, err := store.Set([]byte("foo")) 243 assert.NoError(t, err) 244 245 id2, err := store.Set([]byte("bar")) 246 assert.NoError(t, err) 247 248 tcases := make(map[digest.Digest]struct{}) 249 tcases[id] = struct{}{} 250 tcases[id2] = struct{}{} 251 n := 0 252 err = store.Walk(func(id digest.Digest) error { 253 delete(tcases, id) 254 n++ 255 return nil 256 }) 257 assert.NoError(t, err) 258 assert.Equal(t, 2, n) 259 assert.Len(t, tcases, 0) 260 } 261 262 func TestFSWalkerStopOnError(t *testing.T) { 263 store, cleanup := defaultFSStoreBackend(t) 264 defer cleanup() 265 266 id, err := store.Set([]byte("foo")) 267 assert.NoError(t, err) 268 269 tcases := make(map[digest.Digest]struct{}) 270 tcases[id] = struct{}{} 271 err = store.Walk(func(id digest.Digest) error { 272 return errors.New("what") 273 }) 274 testutil.ErrorContains(t, err, "what") 275 }