github.com/zly-app/zapp@v1.3.3/config/watch_test.go (about) 1 package config 2 3 import ( 4 "fmt" 5 "sync" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/require" 10 11 "github.com/zly-app/zapp/core" 12 ) 13 14 func init() { 15 watchWaitWG.Done() 16 } 17 18 // 测试提供者 19 type TestWatchProvider struct { 20 data map[string]map[string][]byte // 表示组下的key的数据 21 changeDataHandler func(oldData []byte) []byte 22 mx sync.Mutex 23 } 24 25 // 创建测试提供者 26 func NewTestWatchProvider(data map[string]map[string][]byte) *TestWatchProvider { 27 p := &TestWatchProvider{ 28 data: data, 29 } 30 return p 31 } 32 func (t *TestWatchProvider) Get(groupName, keyName string) ([]byte, error) { 33 t.mx.Lock() 34 defer t.mx.Unlock() 35 36 g, ok := t.data[groupName] 37 if !ok { 38 return nil, fmt.Errorf("not found group: %s", groupName) 39 } 40 41 data, ok := g[keyName] 42 if !ok { 43 return nil, fmt.Errorf("not found key: %s.%s", groupName, keyName) 44 } 45 46 return data, nil 47 } 48 func (t *TestWatchProvider) Set(groupName, keyName string, data []byte) error { 49 t.mx.Lock() 50 defer t.mx.Unlock() 51 52 g, ok := t.data[groupName] 53 if !ok { 54 g = make(map[string][]byte) 55 t.data[groupName] = g 56 } 57 58 g[keyName] = data 59 return nil 60 } 61 func (t *TestWatchProvider) Watch(groupName, keyName string, callback core.ConfigWatchProviderCallback) error { 62 go func(groupName, keyName string, callback core.ConfigWatchProviderCallback) { 63 time.Sleep(time.Millisecond * 200) 64 t.mx.Lock() 65 oldData := t.getData(groupName, keyName) 66 newData := t.changeDataHandler(oldData) 67 t.data[groupName][keyName] = newData 68 t.mx.Unlock() 69 callback(groupName, keyName, oldData, newData) 70 }(groupName, keyName, callback) 71 return nil 72 } 73 func (t *TestWatchProvider) getData(groupName, keyName string) []byte { 74 g, ok := t.data[groupName] 75 if !ok { 76 return nil 77 } 78 return g[keyName] 79 } 80 81 var testProvider *TestWatchProvider 82 83 func init() { 84 p := NewTestWatchProvider(map[string]map[string][]byte{}) 85 p.changeDataHandler = func(oldData []byte) []byte { 86 newData := make([]byte, len(oldData)*2) 87 copy(newData, oldData) 88 copy(newData[len(oldData):], oldData) 89 return newData 90 } 91 testProvider = p 92 RegistryConfigWatchProvider("test", p) 93 SetDefaultConfigWatchProvider(p) 94 } 95 96 func TestSDK(t *testing.T) { 97 testGroupName := "g1" 98 testKeyName := "k1" 99 100 err := testProvider.Set(testGroupName, testKeyName, []byte("1")) 101 require.Nil(t, err) 102 103 keyObj := newWatchKeyObject(testGroupName, testKeyName) 104 105 // 获取原始数据 106 y1 := keyObj.GetString() 107 require.Equal(t, "1", y1) 108 109 // 转为 int 值 110 y2 := keyObj.GetInt() 111 require.Equal(t, 1, y2) 112 113 // 转为 boolean 值 114 y3 := keyObj.GetBool() 115 require.Equal(t, true, y3) 116 117 // 检查复合预期 118 b1 := keyObj.Expect("1") 119 require.Equal(t, true, b1) 120 b2 := keyObj.Expect(1) 121 require.Equal(t, true, b2) 122 b3 := keyObj.Expect(true) 123 require.Equal(t, true, b3) 124 } 125 126 func TestWatch(t *testing.T) { 127 testGroupName := "g2" 128 testKeyName := "k2" 129 130 err := testProvider.Set(testGroupName, testKeyName, []byte("2")) 131 require.Nil(t, err) 132 133 keyObj := newWatchKeyObject(testGroupName, testKeyName) 134 135 var isCallback bool 136 expectFirst := true 137 expectOldData := "2" 138 expectNewData := "2" 139 keyObj.AddCallback(func(first bool, oldData, newData []byte) { 140 isCallback = true 141 require.Equal(t, expectFirst, first) 142 require.Equal(t, expectOldData, string(oldData)) 143 require.Equal(t, expectNewData, string(newData)) 144 }) 145 require.Nil(t, err) 146 147 require.True(t, isCallback) 148 require.Equal(t, expectNewData, keyObj.GetString()) 149 150 isCallback = false 151 expectFirst = false 152 expectOldData = "2" 153 expectNewData = "22" 154 time.Sleep(time.Millisecond * 300) 155 require.True(t, isCallback) 156 require.Equal(t, expectNewData, keyObj.GetString()) 157 } 158 159 func TestExpect(t *testing.T) { 160 testGroupName := "g3" 161 testKeyName := "k3" 162 163 err := testProvider.Set(testGroupName, testKeyName, []byte("1")) 164 require.Nil(t, err) 165 166 keyObj := newWatchKeyObject(testGroupName, testKeyName) 167 168 var tests = []struct { 169 expect interface{} 170 result bool 171 }{ 172 {[]byte("1"), true}, 173 {"1", true}, 174 {[]rune("1"), true}, 175 {true, true}, 176 {1, true}, 177 {int8(1), true}, 178 {int16(1), true}, 179 {int32(1), true}, 180 {int64(1), true}, 181 {uint(1), true}, 182 {uint8(1), true}, 183 {uint16(1), true}, 184 {uint32(1), true}, 185 {uint64(1), true}, 186 {float32(1), true}, 187 {float64(1), true}, 188 189 {[]byte("2"), false}, 190 {"2", false}, 191 {[]rune("2"), false}, 192 {false, false}, 193 {2, false}, 194 {int8(2), false}, 195 {int16(2), false}, 196 {int32(2), false}, 197 {int64(2), false}, 198 {uint(2), false}, 199 {uint8(2), false}, 200 {uint16(2), false}, 201 {uint32(2), false}, 202 {uint64(2), false}, 203 {float32(2), false}, 204 {float64(2), false}, 205 } 206 207 for _, test := range tests { 208 result := keyObj.Expect(test.expect) 209 require.Equal(t, result, test.result) 210 } 211 } 212 213 func TestConvert(t *testing.T) { 214 testGroupName := "g4" 215 testKeyName := "k4" 216 217 err := testProvider.Set(testGroupName, testKeyName, []byte("4")) 218 require.Nil(t, err) 219 220 keyObj := newWatchKeyObject(testGroupName, testKeyName) 221 222 require.Equal(t, []byte("4"), keyObj.GetData()) 223 require.Equal(t, "4", keyObj.GetString()) 224 require.Equal(t, false, keyObj.GetBool()) 225 require.Equal(t, true, keyObj.GetBool(true)) 226 require.Equal(t, 4, keyObj.GetInt()) 227 require.Equal(t, int8(4), keyObj.GetInt8()) 228 require.Equal(t, int16(4), keyObj.GetInt16()) 229 require.Equal(t, int32(4), keyObj.GetInt32()) 230 require.Equal(t, int64(4), keyObj.GetInt64()) 231 require.Equal(t, uint(4), keyObj.GetUint()) 232 require.Equal(t, uint8(4), keyObj.GetUint8()) 233 require.Equal(t, uint16(4), keyObj.GetUint16()) 234 require.Equal(t, uint32(4), keyObj.GetUint32()) 235 require.Equal(t, uint64(4), keyObj.GetUint64()) 236 require.Equal(t, float32(4), keyObj.GetFloat32()) 237 require.Equal(t, float64(4), keyObj.GetFloat64()) 238 } 239 240 func TestParseJSON(t *testing.T) { 241 testGroupName := "g5" 242 testKeyName := "k5" 243 244 value := `{"a": 1, "b": {"c": ["x", "y", "z"]}}` 245 err := testProvider.Set(testGroupName, testKeyName, []byte(value)) 246 require.Nil(t, err) 247 248 keyObj := newWatchKeyObject(testGroupName, testKeyName) 249 250 require.Equal(t, keyObj.GetString(), value) 251 252 var a struct { 253 A int `json:"a"` 254 B struct { 255 C []string `json:"c"` 256 } `json:"b"` 257 } 258 err = keyObj.ParseJSON(&a) 259 require.Nil(t, err) 260 require.Equal(t, 1, a.A) 261 require.Equal(t, []string{"x", "y", "z"}, a.B.C) 262 } 263 264 func TestParseYaml(t *testing.T) { 265 testGroupName := "g6" 266 testKeyName := "k6" 267 268 value := ` 269 a: 1 270 b: 271 c: 272 - x 273 - y 274 - z` 275 err := testProvider.Set(testGroupName, testKeyName, []byte(value)) 276 require.Nil(t, err) 277 278 keyObj := newWatchKeyObject(testGroupName, testKeyName) 279 280 require.Equal(t, keyObj.GetString(), value) 281 282 var a struct { 283 A int `json:"a"` 284 B struct { 285 C []string `json:"c"` 286 } `json:"b"` 287 } 288 err = keyObj.ParseYaml(&a) 289 require.Nil(t, err) 290 require.Equal(t, 1, a.A) 291 require.Equal(t, []string{"x", "y", "z"}, a.B.C) 292 } 293 294 func TestGenericSDKJson(t *testing.T) { 295 testGroupName := "g1" 296 testKeyName := "k1" 297 298 rawData := []byte(`{"a":1}`) 299 err := testProvider.Set(testGroupName, testKeyName, rawData) 300 require.Nil(t, err) 301 302 type AA struct { 303 A int `json:"a"` 304 } 305 306 keyObj := WatchJson[*AA](testGroupName, testKeyName) 307 require.NotNil(t, keyObj) 308 require.Equal(t, 1, keyObj.Get().A) 309 require.Equal(t, rawData, keyObj.GetData()) 310 } 311 312 func TestGenericSDKYaml(t *testing.T) { 313 testGroupName := "g1" 314 testKeyName := "k1" 315 316 rawData := []byte(`a: 1`) 317 err := testProvider.Set(testGroupName, testKeyName, rawData) 318 require.Nil(t, err) 319 320 type AA struct { 321 A int `yaml:"a"` 322 } 323 324 keyObj := WatchYaml[*AA](testGroupName, testKeyName) 325 require.NotNil(t, keyObj) 326 require.Equal(t, 1, keyObj.Get().A) 327 require.Equal(t, rawData, keyObj.GetData()) 328 } 329 330 func TestGenericWatchJson(t *testing.T) { 331 testGroupName := "g1" 332 testKeyName := "k1" 333 334 rawData := []byte(`{"a":1}`) 335 err := testProvider.Set(testGroupName, testKeyName, rawData) 336 require.Nil(t, err) 337 338 type AA struct { 339 A int `json:"a"` 340 } 341 342 keyObj := WatchJson[*AA](testGroupName, testKeyName) 343 require.NotNil(t, keyObj) 344 require.Equal(t, 1, keyObj.Get().A) 345 require.Equal(t, rawData, keyObj.GetData()) 346 347 var isCallback bool 348 expectFirst := true 349 expectOldData := 1 350 expectNewData := 1 351 keyObj.AddCallback(func(first bool, oldData, newData *AA) { 352 isCallback = true 353 require.Equal(t, expectFirst, first) 354 require.Equal(t, expectOldData, oldData.A) 355 require.Equal(t, expectNewData, newData.A) 356 }) 357 require.Nil(t, err) 358 359 require.True(t, isCallback) 360 require.Equal(t, expectNewData, keyObj.Get().A) 361 require.Equal(t, rawData, keyObj.GetData()) 362 363 rawData = []byte(`{"a":2}`) 364 testProvider.changeDataHandler = func(oldData []byte) []byte { 365 return rawData 366 } 367 368 isCallback = false 369 expectFirst = false 370 expectOldData = 1 371 expectNewData = 2 372 time.Sleep(time.Millisecond * 300) 373 require.True(t, isCallback) 374 require.Equal(t, expectNewData, keyObj.Get().A) 375 require.Equal(t, rawData, keyObj.GetData()) 376 } 377 378 func TestGenericWatchYaml(t *testing.T) { 379 testGroupName := "g1" 380 testKeyName := "k1" 381 382 rawData := []byte(`a: 1`) 383 err := testProvider.Set(testGroupName, testKeyName, rawData) 384 require.Nil(t, err) 385 386 type AA struct { 387 A int `yaml:"a"` 388 } 389 390 keyObj := WatchYaml[*AA](testGroupName, testKeyName) 391 require.NotNil(t, keyObj) 392 require.Equal(t, 1, keyObj.Get().A) 393 require.Equal(t, rawData, keyObj.GetData()) 394 395 var isCallback bool 396 expectFirst := true 397 expectOldData := 1 398 expectNewData := 1 399 keyObj.AddCallback(func(first bool, oldData, newData *AA) { 400 isCallback = true 401 require.Equal(t, expectFirst, first) 402 require.Equal(t, expectOldData, oldData.A) 403 require.Equal(t, expectNewData, newData.A) 404 }) 405 require.Nil(t, err) 406 407 require.True(t, isCallback) 408 require.Equal(t, expectNewData, keyObj.Get().A) 409 require.Equal(t, rawData, keyObj.GetData()) 410 411 rawData = []byte(`a: 2`) 412 testProvider.changeDataHandler = func(oldData []byte) []byte { 413 return rawData 414 } 415 416 isCallback = false 417 expectFirst = false 418 expectOldData = 1 419 expectNewData = 2 420 time.Sleep(time.Millisecond * 300) 421 require.True(t, isCallback) 422 require.Equal(t, expectNewData, keyObj.Get().A) 423 require.Equal(t, rawData, keyObj.GetData()) 424 }