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