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