github.com/pwn-term/docker@v0.0.0-20210616085119-6e977cce2565/libnetwork/datastore/datastore_test.go (about)

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