01ba0a93 |
package image
import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"errors"
"io/ioutil"
"os"
"path/filepath"
"testing"
|
e62b2d41 |
"github.com/docker/docker/internal/testutil" |
f7f101d5 |
digest "github.com/opencontainers/go-digest" |
6052f2b3 |
"github.com/stretchr/testify/assert" |
01ba0a93 |
)
|
69d73620 |
func defaultFSStoreBackend(t *testing.T) (StoreBackend, func()) { |
01ba0a93 |
tmpdir, err := ioutil.TempDir("", "images-fs-store") |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
|
69d73620 |
fsBackend, err := NewFSStoreBackend(tmpdir) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
return fsBackend, func() { os.RemoveAll(tmpdir) } |
01ba0a93 |
}
func TestFSGetInvalidData(t *testing.T) { |
69d73620 |
store, cleanup := defaultFSStoreBackend(t)
defer cleanup() |
01ba0a93 |
|
69d73620 |
id, err := store.Set([]byte("foobar")) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
dgst := digest.Digest(id)
|
69d73620 |
err = ioutil.WriteFile(filepath.Join(store.(*fs).root, contentDirName, string(dgst.Algorithm()), dgst.Hex()), []byte("foobar2"), 0600) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
|
69d73620 |
_, err = store.Get(id) |
6052f2b3 |
testutil.ErrorContains(t, err, "failed to verify") |
01ba0a93 |
}
func TestFSInvalidSet(t *testing.T) { |
69d73620 |
store, cleanup := defaultFSStoreBackend(t)
defer cleanup() |
01ba0a93 |
|
c168a005 |
id := digest.FromBytes([]byte("foobar")) |
69d73620 |
err := os.Mkdir(filepath.Join(store.(*fs).root, contentDirName, string(id.Algorithm()), id.Hex()), 0700) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
|
69d73620 |
_, err = store.Set([]byte("foobar")) |
6052f2b3 |
testutil.ErrorContains(t, err, "failed to write digest data") |
01ba0a93 |
}
func TestFSInvalidRoot(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "images-fs-store") |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
defer os.RemoveAll(tmpdir)
tcases := []struct {
root, invalidFile string
}{
{"root", "root"},
{"root", "root/content"},
{"root", "root/metadata"},
}
for _, tc := range tcases {
root := filepath.Join(tmpdir, tc.root)
filePath := filepath.Join(tmpdir, tc.invalidFile)
err := os.MkdirAll(filepath.Dir(filePath), 0700) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
|
01ba0a93 |
f, err := os.Create(filePath) |
6052f2b3 |
assert.NoError(t, err) |
7abeb08a |
f.Close() |
01ba0a93 |
_, err = NewFSStoreBackend(root) |
6052f2b3 |
testutil.ErrorContains(t, err, "failed to create storage backend") |
01ba0a93 |
os.RemoveAll(root)
}
}
|
69d73620 |
func TestFSMetadataGetSet(t *testing.T) {
store, cleanup := defaultFSStoreBackend(t)
defer cleanup()
|
01ba0a93 |
id, err := store.Set([]byte("foo")) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
|
01ba0a93 |
id2, err := store.Set([]byte("bar")) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
tcases := []struct { |
80522398 |
id digest.Digest |
01ba0a93 |
key string
value []byte
}{
{id, "tkey", []byte("tval1")},
{id, "tkey2", []byte("tval2")},
{id2, "tkey", []byte("tval3")},
}
for _, tc := range tcases {
err = store.SetMetadata(tc.id, tc.key, tc.value) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
actual, err := store.GetMetadata(tc.id, tc.key) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
|
f7f101d5 |
assert.Equal(t, tc.value, actual) |
01ba0a93 |
}
_, err = store.GetMetadata(id2, "tkey2") |
6052f2b3 |
testutil.ErrorContains(t, err, "failed to read metadata") |
01ba0a93 |
|
c168a005 |
id3 := digest.FromBytes([]byte("baz")) |
80522398 |
err = store.SetMetadata(id3, "tkey", []byte("tval")) |
6052f2b3 |
testutil.ErrorContains(t, err, "failed to get digest") |
01ba0a93 |
|
80522398 |
_, err = store.GetMetadata(id3, "tkey") |
6052f2b3 |
testutil.ErrorContains(t, err, "failed to get digest") |
01ba0a93 |
}
func TestFSInvalidWalker(t *testing.T) { |
69d73620 |
store, cleanup := defaultFSStoreBackend(t)
defer cleanup() |
01ba0a93 |
|
69d73620 |
fooID, err := store.Set([]byte("foo")) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
|
69d73620 |
err = ioutil.WriteFile(filepath.Join(store.(*fs).root, contentDirName, "sha256/foobar"), []byte("foobar"), 0600) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
n := 0 |
69d73620 |
err = store.Walk(func(id digest.Digest) error { |
6052f2b3 |
assert.Equal(t, fooID, id) |
01ba0a93 |
n++
return nil
}) |
6052f2b3 |
assert.NoError(t, err)
assert.Equal(t, 1, n) |
01ba0a93 |
}
|
69d73620 |
func TestFSGetSet(t *testing.T) {
store, cleanup := defaultFSStoreBackend(t)
defer cleanup()
|
01ba0a93 |
type tcase struct {
input []byte |
80522398 |
expected digest.Digest |
01ba0a93 |
}
tcases := []tcase{ |
80522398 |
{[]byte("foobar"), digest.Digest("sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2")}, |
01ba0a93 |
}
randomInput := make([]byte, 8*1024)
_, err := rand.Read(randomInput) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
|
b2ec509a |
// skipping use of digest pkg because it is used by the implementation |
01ba0a93 |
h := sha256.New()
_, err = h.Write(randomInput) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
|
01ba0a93 |
tcases = append(tcases, tcase{
input: randomInput, |
80522398 |
expected: digest.Digest("sha256:" + hex.EncodeToString(h.Sum(nil))), |
01ba0a93 |
})
for _, tc := range tcases {
id, err := store.Set([]byte(tc.input)) |
6052f2b3 |
assert.NoError(t, err)
assert.Equal(t, tc.expected, id) |
01ba0a93 |
}
for _, tc := range tcases {
data, err := store.Get(tc.expected) |
6052f2b3 |
assert.NoError(t, err) |
f7f101d5 |
assert.Equal(t, tc.input, data) |
01ba0a93 |
} |
69d73620 |
}
func TestFSGetUnsetKey(t *testing.T) {
store, cleanup := defaultFSStoreBackend(t)
defer cleanup() |
01ba0a93 |
|
80522398 |
for _, key := range []digest.Digest{"foobar:abc", "sha256:abc", "sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2a"} { |
01ba0a93 |
_, err := store.Get(key) |
6052f2b3 |
testutil.ErrorContains(t, err, "failed to get digest") |
01ba0a93 |
} |
69d73620 |
} |
01ba0a93 |
|
69d73620 |
func TestFSGetEmptyData(t *testing.T) {
store, cleanup := defaultFSStoreBackend(t)
defer cleanup()
for _, emptyData := range [][]byte{nil, {}} {
_, err := store.Set(emptyData) |
6052f2b3 |
testutil.ErrorContains(t, err, "invalid empty data") |
69d73620 |
} |
01ba0a93 |
}
|
69d73620 |
func TestFSDelete(t *testing.T) {
store, cleanup := defaultFSStoreBackend(t)
defer cleanup()
|
01ba0a93 |
id, err := store.Set([]byte("foo")) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
|
01ba0a93 |
id2, err := store.Set([]byte("bar")) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
err = store.Delete(id) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
_, err = store.Get(id) |
6052f2b3 |
testutil.ErrorContains(t, err, "failed to get digest") |
69d73620 |
|
01ba0a93 |
_, err = store.Get(id2) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
err = store.Delete(id2) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
|
01ba0a93 |
_, err = store.Get(id2) |
6052f2b3 |
testutil.ErrorContains(t, err, "failed to get digest") |
01ba0a93 |
}
|
69d73620 |
func TestFSWalker(t *testing.T) {
store, cleanup := defaultFSStoreBackend(t)
defer cleanup()
|
01ba0a93 |
id, err := store.Set([]byte("foo")) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
|
01ba0a93 |
id2, err := store.Set([]byte("bar")) |
6052f2b3 |
assert.NoError(t, err) |
01ba0a93 |
|
80522398 |
tcases := make(map[digest.Digest]struct{}) |
01ba0a93 |
tcases[id] = struct{}{}
tcases[id2] = struct{}{}
n := 0 |
80522398 |
err = store.Walk(func(id digest.Digest) error { |
01ba0a93 |
delete(tcases, id)
n++
return nil
}) |
6052f2b3 |
assert.NoError(t, err)
assert.Equal(t, 2, n)
assert.Len(t, tcases, 0) |
69d73620 |
} |
01ba0a93 |
|
69d73620 |
func TestFSWalkerStopOnError(t *testing.T) {
store, cleanup := defaultFSStoreBackend(t)
defer cleanup() |
01ba0a93 |
|
69d73620 |
id, err := store.Set([]byte("foo")) |
6052f2b3 |
assert.NoError(t, err) |
69d73620 |
tcases := make(map[digest.Digest]struct{}) |
01ba0a93 |
tcases[id] = struct{}{} |
80522398 |
err = store.Walk(func(id digest.Digest) error { |
69d73620 |
return errors.New("what") |
01ba0a93 |
}) |
6052f2b3 |
testutil.ErrorContains(t, err, "what") |
01ba0a93 |
} |