github.com/adityamillind98/moby@v23.0.0-rc.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 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 // dummy data used to test the datastore 114 type dummyObject struct { 115 Name string `kv:"leaf"` 116 NetworkType string `kv:"leaf"` 117 EnableIPv6 bool `kv:"leaf"` 118 Rec *recStruct `kv:"recursive"` 119 Dict map[string]*recStruct `kv:"iterative"` 120 Generic options.Generic `kv:"iterative"` 121 ID string 122 DBIndex uint64 123 DBExists bool 124 SkipSave bool 125 ReturnValue bool 126 } 127 128 func (n *dummyObject) Key() []string { 129 return []string{dummyKey, n.ID} 130 } 131 132 func (n *dummyObject) KeyPrefix() []string { 133 return []string{dummyKey} 134 } 135 136 func (n *dummyObject) Value() []byte { 137 if !n.ReturnValue { 138 return nil 139 } 140 141 b, err := json.Marshal(n) 142 if err != nil { 143 return nil 144 } 145 return b 146 } 147 148 func (n *dummyObject) SetValue(value []byte) error { 149 return json.Unmarshal(value, n) 150 } 151 152 func (n *dummyObject) Index() uint64 { 153 return n.DBIndex 154 } 155 156 func (n *dummyObject) SetIndex(index uint64) { 157 n.DBIndex = index 158 n.DBExists = true 159 } 160 161 func (n *dummyObject) Exists() bool { 162 return n.DBExists 163 } 164 165 func (n *dummyObject) Skip() bool { 166 return n.SkipSave 167 } 168 169 func (n *dummyObject) DataScope() string { 170 return LocalScope 171 } 172 173 func (n *dummyObject) MarshalJSON() ([]byte, error) { 174 netMap := make(map[string]interface{}) 175 netMap["name"] = n.Name 176 netMap["networkType"] = n.NetworkType 177 netMap["enableIPv6"] = n.EnableIPv6 178 netMap["generic"] = n.Generic 179 return json.Marshal(netMap) 180 } 181 182 func (n *dummyObject) UnmarshalJSON(b []byte) (err error) { 183 var netMap map[string]interface{} 184 if err := json.Unmarshal(b, &netMap); err != nil { 185 return err 186 } 187 n.Name = netMap["name"].(string) 188 n.NetworkType = netMap["networkType"].(string) 189 n.EnableIPv6 = netMap["enableIPv6"].(bool) 190 n.Generic = netMap["generic"].(map[string]interface{}) 191 return nil 192 } 193 194 // dummy structure to test "recursive" cases 195 type recStruct struct { 196 Name string `kv:"leaf"` 197 Field1 int `kv:"leaf"` 198 Dict map[string]string `kv:"iterative"` 199 DBIndex uint64 200 DBExists bool 201 SkipSave bool 202 } 203 204 func (r *recStruct) Key() []string { 205 return []string{"recStruct"} 206 } 207 func (r *recStruct) Value() []byte { 208 b, err := json.Marshal(r) 209 if err != nil { 210 return nil 211 } 212 return b 213 } 214 215 func (r *recStruct) SetValue(value []byte) error { 216 return json.Unmarshal(value, r) 217 } 218 219 func (r *recStruct) Index() uint64 { 220 return r.DBIndex 221 } 222 223 func (r *recStruct) SetIndex(index uint64) { 224 r.DBIndex = index 225 r.DBExists = true 226 } 227 228 func (r *recStruct) Exists() bool { 229 return r.DBExists 230 } 231 232 func (r *recStruct) Skip() bool { 233 return r.SkipSave 234 } 235 236 func dummyKVObject(id string, retValue bool) *dummyObject { 237 cDict := make(map[string]string) 238 cDict["foo"] = "bar" 239 cDict["hello"] = "world" 240 n := dummyObject{ 241 Name: "testNw", 242 NetworkType: "bridge", 243 EnableIPv6: true, 244 Rec: &recStruct{"gen", 5, cDict, 0, false, false}, 245 ID: id, 246 DBIndex: 0, 247 ReturnValue: retValue, 248 DBExists: false, 249 SkipSave: false} 250 generic := make(map[string]interface{}) 251 generic["label1"] = &recStruct{"value1", 1, cDict, 0, false, false} 252 generic["label2"] = "subnet=10.1.1.0/16" 253 n.Generic = generic 254 return &n 255 }