github.com/GuanceCloud/cliutils@v1.1.21/point/kvs_test.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 package point 7 8 import ( 9 "math" 10 "sort" 11 T "testing" 12 13 "github.com/stretchr/testify/assert" 14 ) 15 16 func TestTrim(t *T.T) { 17 t.Run("trim-field", func(t *T.T) { 18 var kvs KVs 19 kvs = kvs.Add("f0", 1.23, false, false) 20 kvs = kvs.AddTag("t1", "v1") 21 kvs = kvs.Add("f1", -123, false, false) 22 kvs = kvs.Add("f2", uint64(123), false, false) 23 kvs = kvs.Add("f3", "hello", false, false) 24 kvs = kvs.Add("f4", []byte("world"), false, false) 25 kvs = kvs.Add("f5", false, false, false) 26 27 kvs = kvs.TrimFields(1) 28 29 assert.Lenf(t, kvs, 2, "go kvs: %s", kvs.Pretty()) 30 assert.NotNil(t, kvs.Get("f0")) 31 assert.NotNil(t, kvs.Get("t1")) 32 }) 33 34 t.Run("point-pool-kv-reuse", func(t *T.T) { 35 pp := NewReservedCapPointPool(1000) 36 SetPointPool(pp) 37 defer ClearPointPool() 38 39 i := 0 40 var kvs KVs 41 42 kvs = kvs.Add("f0", 1.23, false, false) 43 kvs = kvs.AddTag("t1", "v1") 44 45 for { 46 kvs = kvs.TrimFields(0) 47 48 assert.Lenf(t, kvs, 1, "go kvs: %s", kvs.Pretty()) 49 50 kvs = kvs.Add("f-1", 123, false, false) 51 52 if pp.(*ReservedCapPointPool).chanGet() > 0 { 53 t.Logf("[%d] %s", i, pp) 54 break 55 } 56 i++ 57 } 58 }) 59 60 t.Run("trim-field-under-point-pool", func(t *T.T) { 61 pp := NewReservedCapPointPool(1000) 62 SetPointPool(pp) 63 defer ClearPointPool() 64 65 for loop := 0; loop < 2; loop++ { 66 var kvs KVs 67 kvs = kvs.Add("f0", 1.23, false, false) 68 kvs = kvs.AddTag("t1", "v1") 69 kvs = kvs.Add("f1", -123, false, false) 70 kvs = kvs.Add("f2", uint64(123), false, false) 71 kvs = kvs.Add("f3", "hello", false, false) 72 kvs = kvs.Add("f4", []byte("world"), false, false) 73 kvs = kvs.Add("f5", false, false, false) 74 75 kvs = kvs.TrimFields(2) 76 77 assert.Lenf(t, kvs, 3 /* 2 fields + 1 tag */, "go kvs: %s", kvs.Pretty()) 78 assert.NotNil(t, kvs.Get("f0")) 79 assert.NotNil(t, kvs.Get("f1")) 80 assert.NotNil(t, kvs.Get("t1")) 81 82 kvs = kvs.Add("f-2", 123, false, false) 83 kvs = kvs.Add("f-3", 123, false, false) 84 kvs = kvs.Add("f-4", 123, false, false) 85 _ = kvs.Add("f-5", 123, false, false) 86 } 87 88 // XXX: why set loop to 1, the kvReused == 0? 89 assert.True(t, pp.(*ReservedCapPointPool).chanGet() > 0) 90 91 t.Logf("point-pool: %s", pp) 92 }) 93 94 t.Run("trim-tag", func(t *T.T) { 95 var kvs KVs 96 kvs = kvs.Add("f0", 1.23, false, false) 97 kvs = kvs.AddTag("t1", "v1") 98 kvs = kvs.AddTag("t2", "v1") 99 kvs = kvs.AddTag("t3", "v1") 100 kvs = kvs.Add("f1", -123, false, false) 101 102 kvs = kvs.TrimTags(1) 103 104 assert.Lenf(t, kvs, 3, "go kvs: %s", kvs.Pretty()) 105 assert.NotNil(t, kvs.Get("t1")) 106 }) 107 108 t.Run("trim-tag-under-point-pool", func(t *T.T) { 109 pp := NewReservedCapPointPool(2) 110 SetPointPool(pp) 111 defer ClearPointPool() 112 113 for loop := 0; loop < 2; loop++ { 114 var kvs KVs 115 116 kvs = kvs.Add("f0", 1.23, false, false) 117 kvs = kvs.AddTag("t1", "v1") 118 kvs = kvs.AddTag("t2", "v1") 119 kvs = kvs.Add("f1", -123, false, false) 120 121 kvs = kvs.TrimTags(1) 122 123 assert.Lenf(t, kvs, 3 /* 2 fields + 1 tag */, "go kvs: %s", kvs.Pretty()) 124 125 assert.NotNil(t, kvs.Get("f0")) 126 assert.NotNil(t, kvs.Get("f1")) 127 assert.NotNil(t, kvs.Get("f1")) 128 129 kvs = kvs.Add("f-2", 123, false, false) 130 kvs = kvs.Add("f-3", 123, false, false) 131 kvs = kvs.Add("f-4", 123, false, false) 132 _ = kvs.Add("f-5", 123, false, false) 133 } 134 135 // XXX: why set loop to 1, the kvReused == 0? 136 assert.True(t, pp.(*ReservedCapPointPool).chanGet() > 0) 137 138 t.Logf("point-pool: %s", pp.(*ReservedCapPointPool).String()) 139 }) 140 } 141 142 func BenchmarkKVsTrim(b *T.B) { 143 b.Run("trim", func(b *T.B) { 144 pp := NewReservedCapPointPool(1000) 145 SetPointPool(pp) 146 defer func() { 147 ClearPointPool() 148 b.Logf("point pool: %s", pp) 149 }() 150 151 for i := 0; i < b.N; i++ { 152 var kvs KVs 153 kvs = kvs.Add("f0", 1.23, false, false) 154 kvs = kvs.AddTag("t1", "v1") 155 kvs = kvs.Add("f1", -123, false, false) 156 kvs = kvs.Add("f2", uint64(123), false, false) 157 158 kvs = kvs.TrimFields(1) 159 160 kvs = kvs.Add("f-2", 123, false, false) 161 kvs = kvs.Add("f-3", 123, false, false) 162 kvs = kvs.Add("f-4", 123, false, false) 163 _ = kvs.Add("f-5", 123, false, false) 164 } 165 }) 166 167 b.Run("del", func(b *T.B) { 168 pp := NewReservedCapPointPool(1000) 169 SetPointPool(pp) 170 defer func() { 171 ClearPointPool() 172 b.Logf("point pool: %s", pp) 173 }() 174 175 for i := 0; i < b.N; i++ { 176 var kvs KVs 177 kvs = kvs.Add("f0", 1.23, false, false) 178 kvs = kvs.AddTag("t1", "v1") 179 kvs = kvs.Add("f1", -123, false, false) 180 kvs = kvs.Add("f2", uint64(123), false, false) 181 182 kvs = kvs.Del("f2") 183 184 kvs = kvs.Add("f-2", 123, false, false) 185 kvs = kvs.Add("f-3", 123, false, false) 186 kvs = kvs.Add("f-4", 123, false, false) 187 _ = kvs.Add("f-5", 123, false, false) 188 } 189 }) 190 } 191 192 func TestKVsAdd(t *T.T) { 193 t.Run("basic", func(t *T.T) { 194 var kvs KVs 195 kvs.Add("f1", 123, false, false) 196 197 assert.Len(t, kvs, 0) 198 199 kvs = kvs.Add("f1", 123, false, false) 200 assert.Len(t, kvs, 1) 201 }) 202 203 t.Run("add-v2", func(t *T.T) { 204 var kvs KVs 205 kvs = kvs.AddV2("f1", 123, false, WithKVUnit("dollar"), WithKVType(GAUGE)) 206 kvs = kvs.AddV2("cap", 123, false, WithKVUnit("bytes"), WithKVType(COUNT)) 207 208 t.Logf("kvs: %s", kvs.Pretty()) 209 }) 210 } 211 212 func TestKVsReset(t *T.T) { 213 t.Run("reset", func(t *T.T) { 214 var kvs KVs 215 kvs = kvs.Add("f0", 1.23, false, false) 216 kvs = kvs.Add("f1", -123, false, false) 217 kvs = kvs.Add("f2", uint64(123), false, false) 218 kvs = kvs.Add("f3", "hello", false, false) 219 kvs = kvs.Add("f4", []byte("world"), false, false) 220 kvs = kvs.Add("f5", false, false, false) 221 222 kvs.ResetFull() 223 224 assert.Equal(t, "", kvs[0].Key) 225 assert.Equal(t, 0.0, kvs[0].Raw().(float64)) 226 227 assert.Equal(t, int64(0), kvs[1].Raw().(int64)) 228 assert.Equal(t, uint64(0), kvs[2].Raw().(uint64)) 229 assert.Equal(t, "", kvs[3].Raw().(string)) 230 assert.Len(t, kvs[4].Raw().([]byte), 0) 231 assert.False(t, kvs[5].Raw().(bool)) 232 }) 233 } 234 235 func TestNewKVs(t *T.T) { 236 t.Run("add-tag", func(t *T.T) { 237 kvs := NewKVs(map[string]any{"f1": 123}) 238 239 kvs = kvs.AddTag(`t1`, `v1`) 240 assert.Equal(t, `v1`, kvs.Get(`t1`).GetS()) 241 assert.Equal(t, 1, kvs.TagCount()) 242 243 // add new tag t2 244 kvs = kvs.Add(`t2`, `v2`, true, true) 245 assert.Equal(t, `v2`, kvs.Get(`t2`).GetS()) 246 assert.Equal(t, 2, kvs.TagCount()) 247 248 // replace t2's value v3 249 kvs = kvs.Add(`t2`, `v3`, true, true) 250 assert.Equal(t, `v3`, kvs.Get(`t2`).GetS()) 251 assert.Equal(t, 2, kvs.TagCount()) 252 253 // invalid tag value(must be []byte/string), switch to field 254 kvs = kvs.Add(`tag-as-field`, 123, true, true) 255 assert.Equal(t, int64(123), kvs.Get(`tag-as-field`).GetI()) 256 assert.Equal(t, 2, kvs.TagCount()) 257 258 // invalid tag override exist 259 kvs = kvs.Add(`t2`, false, true, true) 260 assert.Equal(t, false, kvs.Get(`t2`).GetB()) 261 assert.Equal(t, 1, kvs.TagCount()) 262 }) 263 264 t.Run(`new-empty`, func(t *T.T) { 265 kvs := NewKVs(nil) 266 assert.Equal(t, 0, len(kvs)) 267 }) 268 269 t.Run(`new-invalid-float`, func(t *T.T) { 270 kvs := NewKVs(map[string]any{ 271 "f1": math.NaN(), 272 "f2": math.Inf(1), 273 }) 274 275 assert.Equal(t, 2, len(kvs)) 276 }) 277 278 t.Run(`new-all-types`, func(t *T.T) { 279 kvs := NewKVs(map[string]any{ 280 "f1": 123, 281 "f2": uint64(123), 282 "f3": 3.14, 283 "f4": "hello", 284 "f5": []byte(`world`), 285 "f6": false, 286 "f7": true, 287 }) 288 assert.Equal(t, 7, len(kvs)) 289 290 assert.Equal(t, int64(123), kvs.Get(`f1`).GetI()) 291 assert.Equal(t, uint64(123), kvs.Get(`f2`).GetU()) 292 assert.Equal(t, 3.14, kvs.Get(`f3`).GetF()) 293 assert.Equal(t, `hello`, kvs.Get(`f4`).GetS()) 294 assert.Equal(t, []byte(`world`), kvs.Get(`f5`).GetD()) 295 assert.Equal(t, false, kvs.Get(`f6`).GetB()) 296 assert.Equal(t, true, kvs.Get(`f7`).GetB()) 297 298 t.Logf("kvs:\n%s", kvs.Pretty()) 299 }) 300 301 t.Run(`add-kv`, func(t *T.T) { 302 kvs := NewKVs(nil) 303 304 kvs = kvs.MustAddKV(NewKV(`t1`, false, WithKVTagSet(true))) // set tag failed on bool value 305 kvs = kvs.MustAddKV(NewKV(`t2`, "v1", WithKVTagSet(true))) 306 kvs = kvs.MustAddKV(NewKV(`t3`, []byte("v2"), WithKVTagSet(true))) 307 308 kvs = kvs.MustAddKV(NewKV(`f1`, "foo")) 309 kvs = kvs.MustAddKV(NewKV(`f2`, 123, WithKVUnit("MB"), WithKVType(COUNT))) 310 kvs = kvs.MustAddKV(NewKV(`f3`, 3.14, WithKVUnit("some"), WithKVType(GAUGE))) 311 312 assert.Equal(t, 6, len(kvs)) 313 314 t.Logf("kvs:\n%s", kvs.Pretty()) 315 }) 316 317 // any update to kvs should keep them sorted 318 t.Run(`test-not-sorted`, func(t *T.T) { 319 kvs := NewKVs(nil) 320 321 assert.True(t, sort.IsSorted(kvs)) // empty kvs sorted 322 323 kvs = kvs.Add(`f2`, false, false, false) 324 kvs = kvs.Add(`f1`, 123, false, false) 325 kvs = kvs.Add(`f0`, 123, false, false) 326 kvs = kvs.MustAddTag(`t1`, "v1") 327 328 assert.False(t, sort.IsSorted(kvs)) 329 330 kvs = kvs.Del(`f1`) 331 assert.False(t, sort.IsSorted(kvs)) 332 333 kvs = kvs.MustAddKV(NewKV(`f3`, 3.14)) 334 assert.False(t, sort.IsSorted(kvs)) 335 336 t.Logf("kvs:\n%s", kvs.Pretty()) 337 338 sort.Sort(kvs) 339 assert.True(t, sort.IsSorted(kvs)) 340 assert.Len(t, kvs, 4) 341 }) 342 343 t.Run(`test-del3`, func(t *T.T) { 344 pp := NewReservedCapPointPool(1000) 345 346 SetPointPool(pp) 347 defer ClearPointPool() 348 349 var kvs KVs 350 351 defer func() { 352 for _, kv := range kvs { 353 pp.PutKV(kv) 354 } 355 }() 356 357 kvs = kvs.Add(`f1`, false, false, false) 358 kvs = kvs.Add(`f2`, 123, false, false) 359 kvs = kvs.Add(`f3`, 123, false, false) 360 361 t.Logf("kvs:\n%s", kvs.Pretty()) 362 kvs = kvs.Del(`f1`) 363 t.Logf("kvs:\n%s", kvs.Pretty()) 364 365 t.Logf("pt pool: %s", pp) 366 }) 367 368 t.Run(`test-del-on-pt-pool`, func(t *T.T) { 369 pp := NewReservedCapPointPool(1000) 370 371 SetPointPool(pp) 372 defer ClearPointPool() 373 374 var kvs KVs 375 376 defer func() { 377 for _, kv := range kvs { 378 pp.PutKV(kv) 379 } 380 }() 381 382 kvs = kvs.Add(`f1`, false, false, false) 383 kvs = kvs.Add(`f2`, 123, false, false) 384 kvs = kvs.Add(`f3`, 123, false, false) 385 386 t.Logf("kvs:\n%s", kvs.Pretty()) 387 kvs = kvs.Del(`f1`) 388 t.Logf("kvs:\n%s", kvs.Pretty()) 389 390 t.Logf("pt pool: %s", pp) 391 }) 392 393 t.Run(`test-update-on-kvs`, func(t *T.T) { 394 pt := NewPointV2("ptname", nil) 395 396 pt.pt.Fields = KVs(pt.pt.Fields).Add("f1", 1.23, false, false) 397 398 t.Logf("point: %s", pt.Pretty()) 399 400 assert.NotNil(t, pt.Get("f1")) 401 }) 402 403 t.Run("array-int-value", func(t *T.T) { 404 var kvs KVs 405 kvs = kvs.Add("f_arr", MustNewAnyArray(1, 2, 3), false, false) 406 assert.Equal(t, []any{int64(1), int64(2), int64(3)}, kvs.Get("f_arr").Raw()) 407 t.Logf("kvs: %s", kvs.Pretty()) 408 }) 409 410 t.Run("array-bytes-value", func(t *T.T) { 411 var kvs KVs 412 kvs = kvs.Add("f_arr", MustNewAnyArray([]byte("hello"), []byte("world")), false, false) 413 assert.Equal(t, []any{[]byte("hello"), []byte("world")}, kvs.Get("f_arr").Raw()) 414 t.Logf("kvs: %s", kvs.Pretty()) 415 416 pt := NewPointV2("some", kvs) 417 418 t.Logf("pt pretty: %s", pt.Pretty()) 419 t.Logf("pt lineproto: %s", pt.LineProto()) 420 }) 421 422 t.Run("array-float-value", func(t *T.T) { 423 kvs := NewKVs(map[string]any{ 424 "f_arr": []float64{1.0, 2.0}, 425 }) 426 t.Logf("kvs: %s", kvs.Pretty()) 427 }) 428 429 t.Run("array-bytes-value", func(t *T.T) { 430 kvs := NewKVs(map[string]any{ 431 "f_arr": [][]byte{[]byte("hello"), []byte("world")}, 432 }) 433 t.Logf("kvs: %s", kvs.Pretty()) 434 }) 435 } 436 437 func TestKVsDel(t *T.T) { 438 t.Run("del", func(t *T.T) { 439 var kvs KVs 440 441 kvs = kvs.Add(`f1`, false, false, false) 442 kvs = kvs.Add(`f2`, 123, false, false) 443 kvs = kvs.Add(`f3`, 123, false, false) 444 445 kvs = kvs.Del(`f1`) 446 assert.Len(t, kvs, 2) 447 kvs = kvs.Del(`f3`) 448 assert.Len(t, kvs, 1) 449 assert.NotNil(t, kvs.Get(`f2`)) 450 }) 451 452 t.Run(`del-on-point-pool`, func(t *T.T) { 453 var kvs KVs 454 455 pp := NewReservedCapPointPool(1000) 456 SetPointPool(pp) 457 defer func() { 458 ClearPointPool() 459 }() 460 461 kvs = kvs.Add(`f1`, false, false, false) 462 kvs = kvs.Add(`f2`, 123, false, false) 463 kvs = kvs.Add(`f3`, 123, false, false) 464 465 kvs = kvs.Del(`f1`) 466 assert.Len(t, kvs, 2) 467 kvs = kvs.Del(`f3`) 468 469 assert.Len(t, kvs, 1) 470 assert.NotNil(t, kvs.Get(`f2`)) 471 472 _ = kvs.Add(`f-x`, 123, false, false) 473 474 assert.True(t, pp.(*ReservedCapPointPool).poolGet() > 0) 475 assert.True(t, pp.(*ReservedCapPointPool).poolPut() == 0) // chan is 1000, not put to pool 476 477 assert.True(t, pp.(*ReservedCapPointPool).chanGet() > 0) 478 assert.True(t, pp.(*ReservedCapPointPool).chanPut() > 0) 479 480 t.Logf("point pool: %s", pp.(*ReservedCapPointPool).String()) 481 }) 482 } 483 484 func BenchmarkKVsDel(b *T.B) { 485 addTestKVs := func(kvs KVs) KVs { 486 kvs = kvs.Add(`f1`, false, false, false) 487 kvs = kvs.Add(`f2`, 123, false, false) 488 kvs = kvs.Add(`f3`, "some string", false, false) 489 kvs = kvs.Add(`f4`, []byte("hello world"), false, false) 490 kvs = kvs.Add(`f5`, 3.14, false, false) 491 kvs = kvs.Add(`f6`, uint(8), false, false) 492 493 return kvs 494 } 495 496 b.Run("del-on-slice-Delete", func(b *T.B) { 497 for i := 0; i < b.N; i++ { 498 var kvs KVs 499 kvs = addTestKVs(kvs) 500 _ = kvs.Del(`f1`) 501 } 502 }) 503 504 b.Run("del-on-slice-Delete-with-point-pool", func(b *T.B) { 505 pp := NewReservedCapPointPool(1000) 506 SetPointPool(pp) 507 defer func() { 508 b.Logf("point pool: %s", pp.(*ReservedCapPointPool).String()) 509 ClearPointPool() 510 }() 511 512 for i := 0; i < b.N; i++ { 513 var kvs KVs 514 kvs = addTestKVs(kvs) 515 _ = kvs.Del(`f1`) 516 } 517 }) 518 519 b.Run("del-on-new-slice", func(b *T.B) { 520 del := func(kvs KVs, k string) KVs { 521 var keep KVs // new slice 522 for _, f := range kvs { 523 if f.Key != k { 524 keep = append(keep, f) 525 } 526 } 527 return keep 528 } 529 530 for i := 0; i < b.N; i++ { 531 var kvs KVs 532 kvs = addTestKVs(kvs) 533 _ = del(kvs, `f1`) 534 } 535 }) 536 }