github.com/rawahars/moby@v24.0.4+incompatible/libnetwork/datastore/datastore_test.go (about)

     1  package datastore
     2  
     3  import (
     4  	"encoding/json"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/docker/docker/libnetwork/options"
     9  	"gotest.tools/v3/assert"
    10  )
    11  
    12  var dummyKey = "dummy"
    13  
    14  // NewCustomDataStore can be used by other Tests in order to use custom datastore
    15  func NewTestDataStore() DataStore {
    16  	return &datastore{scope: LocalScope, store: NewMockStore()}
    17  }
    18  
    19  func TestKey(t *testing.T) {
    20  	eKey := []string{"hello", "world"}
    21  	sKey := Key(eKey...)
    22  	if sKey != "docker/network/v1.0/hello/world/" {
    23  		t.Fatalf("unexpected key : %s", sKey)
    24  	}
    25  }
    26  
    27  func TestParseKey(t *testing.T) {
    28  	keySlice, err := ParseKey("/docker/network/v1.0/hello/world/")
    29  	if err != nil {
    30  		t.Fatal(err)
    31  	}
    32  	eKey := []string{"hello", "world"}
    33  	if len(keySlice) < 2 || !reflect.DeepEqual(eKey, keySlice) {
    34  		t.Fatalf("unexpected unkey : %s", keySlice)
    35  	}
    36  }
    37  
    38  func TestInvalidDataStore(t *testing.T) {
    39  	config := ScopeCfg{
    40  		Client: ScopeClientCfg{
    41  			Provider: "invalid",
    42  			Address:  "localhost:8500",
    43  		},
    44  	}
    45  	_, err := NewDataStore(config)
    46  	if err == nil {
    47  		t.Fatal("Invalid Datastore connection configuration must result in a failure")
    48  	}
    49  }
    50  
    51  func TestKVObjectFlatKey(t *testing.T) {
    52  	store := NewTestDataStore()
    53  	expected := dummyKVObject("1000", true)
    54  	err := store.PutObject(expected)
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	keychain := []string{dummyKey, "1000"}
    59  	data, err := store.KVStore().Get(Key(keychain...))
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  	var n dummyObject
    64  	json.Unmarshal(data.Value, &n)
    65  	if n.Name != expected.Name {
    66  		t.Fatal("Dummy object doesn't match the expected object")
    67  	}
    68  }
    69  
    70  func TestAtomicKVObjectFlatKey(t *testing.T) {
    71  	store := NewTestDataStore()
    72  	expected := dummyKVObject("1111", true)
    73  	assert.Check(t, !expected.Exists())
    74  	err := store.PutObjectAtomic(expected)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	assert.Check(t, expected.Exists())
    79  
    80  	// PutObjectAtomic automatically sets the Index again. Hence the following must pass.
    81  
    82  	err = store.PutObjectAtomic(expected)
    83  	if err != nil {
    84  		t.Fatal("Atomic update should succeed.")
    85  	}
    86  
    87  	// Get the latest index and try PutObjectAtomic again for the same Key
    88  	// This must succeed as well
    89  	data, err := store.KVStore().Get(Key(expected.Key()...))
    90  	if err != nil {
    91  		t.Fatal(err)
    92  	}
    93  	n := dummyObject{}
    94  	json.Unmarshal(data.Value, &n)
    95  	n.ID = "1111"
    96  	n.SetIndex(data.LastIndex)
    97  	n.ReturnValue = true
    98  	err = store.PutObjectAtomic(&n)
    99  	if err != nil {
   100  		t.Fatal(err)
   101  	}
   102  
   103  	// Get the Object using GetObject, then set again.
   104  	newObj := dummyObject{}
   105  	err = store.GetObject(Key(expected.Key()...), &newObj)
   106  	if err != nil {
   107  		t.Fatal(err)
   108  	}
   109  	assert.Check(t, newObj.Exists())
   110  	err = store.PutObjectAtomic(&n)
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  }
   115  
   116  // dummy data used to test the datastore
   117  type dummyObject struct {
   118  	Name        string                `kv:"leaf"`
   119  	NetworkType string                `kv:"leaf"`
   120  	EnableIPv6  bool                  `kv:"leaf"`
   121  	Rec         *recStruct            `kv:"recursive"`
   122  	Dict        map[string]*recStruct `kv:"iterative"`
   123  	Generic     options.Generic       `kv:"iterative"`
   124  	ID          string
   125  	DBIndex     uint64
   126  	DBExists    bool
   127  	SkipSave    bool
   128  	ReturnValue bool
   129  }
   130  
   131  func (n *dummyObject) Key() []string {
   132  	return []string{dummyKey, n.ID}
   133  }
   134  
   135  func (n *dummyObject) KeyPrefix() []string {
   136  	return []string{dummyKey}
   137  }
   138  
   139  func (n *dummyObject) Value() []byte {
   140  	if !n.ReturnValue {
   141  		return nil
   142  	}
   143  
   144  	b, err := json.Marshal(n)
   145  	if err != nil {
   146  		return nil
   147  	}
   148  	return b
   149  }
   150  
   151  func (n *dummyObject) SetValue(value []byte) error {
   152  	return json.Unmarshal(value, n)
   153  }
   154  
   155  func (n *dummyObject) Index() uint64 {
   156  	return n.DBIndex
   157  }
   158  
   159  func (n *dummyObject) SetIndex(index uint64) {
   160  	n.DBIndex = index
   161  	n.DBExists = true
   162  }
   163  
   164  func (n *dummyObject) Exists() bool {
   165  	return n.DBExists
   166  }
   167  
   168  func (n *dummyObject) Skip() bool {
   169  	return n.SkipSave
   170  }
   171  
   172  func (n *dummyObject) DataScope() string {
   173  	return LocalScope
   174  }
   175  
   176  func (n *dummyObject) MarshalJSON() ([]byte, error) {
   177  	netMap := make(map[string]interface{})
   178  	netMap["name"] = n.Name
   179  	netMap["networkType"] = n.NetworkType
   180  	netMap["enableIPv6"] = n.EnableIPv6
   181  	netMap["generic"] = n.Generic
   182  	return json.Marshal(netMap)
   183  }
   184  
   185  func (n *dummyObject) UnmarshalJSON(b []byte) (err error) {
   186  	var netMap map[string]interface{}
   187  	if err := json.Unmarshal(b, &netMap); err != nil {
   188  		return err
   189  	}
   190  	n.Name = netMap["name"].(string)
   191  	n.NetworkType = netMap["networkType"].(string)
   192  	n.EnableIPv6 = netMap["enableIPv6"].(bool)
   193  	n.Generic = netMap["generic"].(map[string]interface{})
   194  	return nil
   195  }
   196  
   197  // dummy structure to test "recursive" cases
   198  type recStruct struct {
   199  	Name     string            `kv:"leaf"`
   200  	Field1   int               `kv:"leaf"`
   201  	Dict     map[string]string `kv:"iterative"`
   202  	DBIndex  uint64
   203  	DBExists bool
   204  	SkipSave bool
   205  }
   206  
   207  func (r *recStruct) Key() []string {
   208  	return []string{"recStruct"}
   209  }
   210  func (r *recStruct) Value() []byte {
   211  	b, err := json.Marshal(r)
   212  	if err != nil {
   213  		return nil
   214  	}
   215  	return b
   216  }
   217  
   218  func (r *recStruct) SetValue(value []byte) error {
   219  	return json.Unmarshal(value, r)
   220  }
   221  
   222  func (r *recStruct) Index() uint64 {
   223  	return r.DBIndex
   224  }
   225  
   226  func (r *recStruct) SetIndex(index uint64) {
   227  	r.DBIndex = index
   228  	r.DBExists = true
   229  }
   230  
   231  func (r *recStruct) Exists() bool {
   232  	return r.DBExists
   233  }
   234  
   235  func (r *recStruct) Skip() bool {
   236  	return r.SkipSave
   237  }
   238  
   239  func dummyKVObject(id string, retValue bool) *dummyObject {
   240  	cDict := make(map[string]string)
   241  	cDict["foo"] = "bar"
   242  	cDict["hello"] = "world"
   243  	n := dummyObject{
   244  		Name:        "testNw",
   245  		NetworkType: "bridge",
   246  		EnableIPv6:  true,
   247  		Rec:         &recStruct{"gen", 5, cDict, 0, false, false},
   248  		ID:          id,
   249  		DBIndex:     0,
   250  		ReturnValue: retValue,
   251  		DBExists:    false,
   252  		SkipSave:    false}
   253  	generic := make(map[string]interface{})
   254  	generic["label1"] = &recStruct{"value1", 1, cDict, 0, false, false}
   255  	generic["label2"] = "subnet=10.1.1.0/16"
   256  	n.Generic = generic
   257  	return &n
   258  }