Files
moby/daemon/libnetwork/datastore/datastore_test.go
Sebastiaan van Stijn 975e46f726 libnetwork/datastore: small cleanups
- 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>
2025-10-20 11:49:03 +02:00

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",
},
}
}