mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
- Use an intermediate struct for (un)marshaling dummyObject - Remove dummyObject.SkipSave as it would always be set to "false" (i.e., persisted to disk). - Minor cleanups in handling locks and some unused vars Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
229 lines
5.1 KiB
Go
229 lines
5.1 KiB
Go
package datastore
|
|
|
|
import (
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
"github.com/moby/moby/v2/daemon/libnetwork/options"
|
|
"gotest.tools/v3/assert"
|
|
is "gotest.tools/v3/assert/cmp"
|
|
)
|
|
|
|
const dummyKey = "dummy"
|
|
|
|
// NewTestDataStore can be used by other Tests in order to use custom datastore
|
|
func NewTestDataStore() *Store {
|
|
s := NewMockStore()
|
|
return &Store{store: s, cache: newCache(s)}
|
|
}
|
|
|
|
func TestKey(t *testing.T) {
|
|
sKey := Key("hello", "world")
|
|
const expected = "docker/network/v1.0/hello/world/"
|
|
assert.Check(t, is.Equal(sKey, expected))
|
|
}
|
|
|
|
func TestKVObjectFlatKey(t *testing.T) {
|
|
store := NewTestDataStore()
|
|
expected := dummyKVObject("1000", true)
|
|
err := store.PutObjectAtomic(expected)
|
|
assert.Check(t, err)
|
|
|
|
n := dummyObject{ID: "1000"} // GetObject uses KVObject.Key() for cache lookup.
|
|
err = store.GetObject(&n)
|
|
assert.Check(t, err)
|
|
assert.Check(t, is.Equal(n.Name, expected.Name))
|
|
}
|
|
|
|
func TestAtomicKVObjectFlatKey(t *testing.T) {
|
|
store := NewTestDataStore()
|
|
expected := dummyKVObject("1111", true)
|
|
assert.Check(t, !expected.Exists())
|
|
err := store.PutObjectAtomic(expected)
|
|
assert.Check(t, err)
|
|
assert.Check(t, expected.Exists())
|
|
|
|
// PutObjectAtomic automatically sets the Index again. Hence the following must pass.
|
|
|
|
err = store.PutObjectAtomic(expected)
|
|
assert.Check(t, err, "Atomic update should succeed.")
|
|
|
|
// Get the latest index and try PutObjectAtomic again for the same Key
|
|
// This must succeed as well
|
|
n := dummyObject{ID: "1111"} // GetObject uses KVObject.Key() for cache lookup.
|
|
err = store.GetObject(&n)
|
|
assert.Check(t, err)
|
|
n.ReturnValue = true
|
|
err = store.PutObjectAtomic(&n)
|
|
assert.Check(t, err)
|
|
|
|
// Get the Object using GetObject, then set again.
|
|
newObj := dummyObject{ID: "1111"} // GetObject uses KVObject.Key() for cache lookup.
|
|
err = store.GetObject(&newObj)
|
|
assert.Check(t, err)
|
|
assert.Check(t, newObj.Exists())
|
|
err = store.PutObjectAtomic(&n)
|
|
assert.Check(t, err)
|
|
}
|
|
|
|
// dummy data used to test the datastore
|
|
type dummyObject struct {
|
|
Name string `kv:"leaf"`
|
|
NetworkType string `kv:"leaf"`
|
|
EnableIPv6 bool `kv:"leaf"`
|
|
Rec *recStruct `kv:"recursive"`
|
|
Dict map[string]*recStruct `kv:"iterative"`
|
|
Generic options.Generic `kv:"iterative"`
|
|
ID string
|
|
DBIndex uint64
|
|
DBExists bool
|
|
ReturnValue bool
|
|
}
|
|
|
|
func (n *dummyObject) Key() []string {
|
|
return []string{dummyKey, n.ID}
|
|
}
|
|
|
|
func (n *dummyObject) KeyPrefix() []string {
|
|
return []string{dummyKey}
|
|
}
|
|
|
|
func (n *dummyObject) Value() []byte {
|
|
if !n.ReturnValue {
|
|
return nil
|
|
}
|
|
|
|
b, err := json.Marshal(n)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return b
|
|
}
|
|
|
|
func (n *dummyObject) SetValue(value []byte) error {
|
|
return json.Unmarshal(value, n)
|
|
}
|
|
|
|
func (n *dummyObject) Index() uint64 {
|
|
return n.DBIndex
|
|
}
|
|
|
|
func (n *dummyObject) SetIndex(index uint64) {
|
|
n.DBIndex = index
|
|
n.DBExists = true
|
|
}
|
|
|
|
func (n *dummyObject) Exists() bool {
|
|
return n.DBExists
|
|
}
|
|
|
|
func (n *dummyObject) Skip() bool {
|
|
return false
|
|
}
|
|
|
|
type tmpStruct struct {
|
|
Name string `json:"name"`
|
|
NetworkType string `json:"networkType"`
|
|
EnableIPv6 bool `json:"enableIPv6"`
|
|
Generic options.Generic `json:"generic"`
|
|
}
|
|
|
|
func (n *dummyObject) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(tmpStruct{
|
|
Name: n.Name,
|
|
NetworkType: n.NetworkType,
|
|
EnableIPv6: n.EnableIPv6,
|
|
Generic: n.Generic,
|
|
})
|
|
}
|
|
|
|
func (n *dummyObject) UnmarshalJSON(b []byte) error {
|
|
var netMap tmpStruct
|
|
if err := json.Unmarshal(b, &netMap); err != nil {
|
|
return err
|
|
}
|
|
n.Name = netMap.Name
|
|
n.NetworkType = netMap.NetworkType
|
|
n.EnableIPv6 = netMap.EnableIPv6
|
|
n.Generic = netMap.Generic
|
|
return nil
|
|
}
|
|
|
|
func (n *dummyObject) New() KVObject {
|
|
return &dummyObject{}
|
|
}
|
|
|
|
func (n *dummyObject) CopyTo(o KVObject) error {
|
|
if err := o.SetValue(n.Value()); err != nil {
|
|
return err
|
|
}
|
|
o.SetIndex(n.Index())
|
|
return nil
|
|
}
|
|
|
|
// dummy structure to test "recursive" cases
|
|
type recStruct struct {
|
|
Name string `kv:"leaf"`
|
|
Field1 int `kv:"leaf"`
|
|
Dict map[string]string `kv:"iterative"`
|
|
DBIndex uint64
|
|
DBExists bool
|
|
SkipSave bool
|
|
}
|
|
|
|
func (r *recStruct) Key() []string {
|
|
return []string{"recStruct"}
|
|
}
|
|
|
|
func (r *recStruct) Value() []byte {
|
|
b, err := json.Marshal(r)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return b
|
|
}
|
|
|
|
func (r *recStruct) SetValue(value []byte) error {
|
|
return json.Unmarshal(value, r)
|
|
}
|
|
|
|
func (r *recStruct) Index() uint64 {
|
|
return r.DBIndex
|
|
}
|
|
|
|
func (r *recStruct) SetIndex(index uint64) {
|
|
r.DBIndex = index
|
|
r.DBExists = true
|
|
}
|
|
|
|
func (r *recStruct) Exists() bool {
|
|
return r.DBExists
|
|
}
|
|
|
|
func (r *recStruct) Skip() bool {
|
|
return r.SkipSave
|
|
}
|
|
|
|
func dummyKVObject(id string, retValue bool) *dummyObject {
|
|
return &dummyObject{
|
|
Name: "testNw",
|
|
NetworkType: "bridge",
|
|
EnableIPv6: true,
|
|
Rec: &recStruct{Name: "gen", Field1: 5, Dict: map[string]string{
|
|
"foo": "bar",
|
|
"hello": "world",
|
|
}},
|
|
ID: id,
|
|
DBIndex: 0,
|
|
ReturnValue: retValue,
|
|
DBExists: false,
|
|
Generic: options.Generic{
|
|
"label1": &recStruct{Name: "value1", Field1: 1, Dict: map[string]string{
|
|
"foo": "bar",
|
|
"hello": "world",
|
|
}},
|
|
"label2": "subnet=10.1.1.0/16",
|
|
},
|
|
}
|
|
}
|