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