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 }