179 lines
3.5 KiB
Go
179 lines
3.5 KiB
Go
package metadata
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"testing"
|
|
|
|
"github.com/boltdb/bolt"
|
|
"github.com/containerd/containerd/errdefs"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func TestInit(t *testing.T) {
|
|
ctx, db, cancel := testEnv(t)
|
|
defer cancel()
|
|
|
|
if err := NewDB(db, nil, nil).Init(ctx); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
version, err := readDBVersion(db, bucketKeyVersion)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if version != dbVersion {
|
|
t.Fatalf("Unexpected version %d, expected %d", version, dbVersion)
|
|
}
|
|
}
|
|
|
|
func TestMigrations(t *testing.T) {
|
|
migrationTests := []struct {
|
|
name string
|
|
init func(*bolt.Tx) error
|
|
check func(*bolt.Tx) error
|
|
}{
|
|
{
|
|
name: "ChildrenKey",
|
|
init: func(tx *bolt.Tx) error {
|
|
bkt, err := createSnapshotterBucket(tx, "testing", "testing")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
snapshots := []struct {
|
|
key string
|
|
parent string
|
|
}{
|
|
{
|
|
key: "k1",
|
|
parent: "",
|
|
},
|
|
{
|
|
key: "k2",
|
|
parent: "k1",
|
|
},
|
|
{
|
|
key: "k2a",
|
|
parent: "k1",
|
|
},
|
|
{
|
|
key: "a1",
|
|
parent: "k2",
|
|
},
|
|
}
|
|
|
|
for _, s := range snapshots {
|
|
sbkt, err := bkt.CreateBucket([]byte(s.key))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := sbkt.Put(bucketKeyParent, []byte(s.parent)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
},
|
|
check: func(tx *bolt.Tx) error {
|
|
bkt := getSnapshotterBucket(tx, "testing", "testing")
|
|
if bkt == nil {
|
|
return errors.Wrap(errdefs.ErrNotFound, "snapshots bucket not found")
|
|
}
|
|
snapshots := []struct {
|
|
key string
|
|
children []string
|
|
}{
|
|
{
|
|
key: "k1",
|
|
children: []string{"k2", "k2a"},
|
|
},
|
|
{
|
|
key: "k2",
|
|
children: []string{"a1"},
|
|
},
|
|
{
|
|
key: "k2a",
|
|
children: []string{},
|
|
},
|
|
{
|
|
key: "a1",
|
|
children: []string{},
|
|
},
|
|
}
|
|
|
|
for _, s := range snapshots {
|
|
sbkt := bkt.Bucket([]byte(s.key))
|
|
if sbkt == nil {
|
|
return errors.Wrap(errdefs.ErrNotFound, "key does not exist")
|
|
}
|
|
|
|
cbkt := sbkt.Bucket(bucketKeyChildren)
|
|
var cn int
|
|
if cbkt != nil {
|
|
cn = cbkt.Stats().KeyN
|
|
}
|
|
|
|
if cn != len(s.children) {
|
|
return errors.Errorf("unexpected number of children %d, expected %d", cn, len(s.children))
|
|
}
|
|
|
|
for _, ch := range s.children {
|
|
if v := cbkt.Get([]byte(ch)); v == nil {
|
|
return errors.Errorf("missing child record for %s", ch)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
},
|
|
},
|
|
}
|
|
|
|
if len(migrationTests) != len(migrations) {
|
|
t.Fatal("Each migration must have a test case")
|
|
}
|
|
|
|
for i, mt := range migrationTests {
|
|
t.Run(mt.name, runMigrationTest(i, mt.init, mt.check))
|
|
}
|
|
}
|
|
|
|
func runMigrationTest(i int, init, check func(*bolt.Tx) error) func(t *testing.T) {
|
|
return func(t *testing.T) {
|
|
_, db, cancel := testEnv(t)
|
|
defer cancel()
|
|
|
|
if err := db.Update(init); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := db.Update(migrations[i].migrate); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := db.View(check); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func readDBVersion(db *bolt.DB, schema []byte) (int, error) {
|
|
var version int
|
|
if err := db.View(func(tx *bolt.Tx) error {
|
|
bkt := tx.Bucket(schema)
|
|
if bkt == nil {
|
|
return errors.Wrap(errdefs.ErrNotFound, "no version bucket")
|
|
}
|
|
vb := bkt.Get(bucketKeyDBVersion)
|
|
if vb == nil {
|
|
return errors.Wrap(errdefs.ErrNotFound, "no version value")
|
|
}
|
|
v, _ := binary.Varint(vb)
|
|
version = int(v)
|
|
return nil
|
|
}); err != nil {
|
|
return 0, err
|
|
}
|
|
return version, nil
|
|
}
|