github.com/GuanceCloud/cliutils@v1.1.21/point/new_point_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 "fmt" 10 "math" 11 "math/rand" 12 "sort" 13 "testing" 14 T "testing" 15 "time" 16 17 "github.com/stretchr/testify/assert" 18 ) 19 20 func getNFields(n int) map[string]interface{} { 21 i := 0 22 fields := map[string]interface{}{} 23 for { 24 var v interface{} 25 v = i // int 26 27 if i%2 == 0 { // string 28 v = fmt.Sprintf("fieldv-%d", i) 29 } 30 31 if i%3 == 0 { // float 32 v = rand.NormFloat64() 33 } 34 35 if i%4 == 0 { // bool 36 if i/2%2 == 0 { 37 v = false 38 } else { 39 v = true 40 } 41 } 42 43 fields[fmt.Sprintf("field-%d", i)] = v 44 if i > n { 45 return fields 46 } 47 48 i++ 49 } 50 } 51 52 func TestV2NewPoint(t *T.T) { 53 t.Run("valid-fields", func(t *T.T) { 54 pt := NewPointV2("abc", NewKVs( 55 map[string]interface{}{ 56 "[]byte": []byte("abc"), 57 "[]uint8": []uint8("abc"), 58 59 "b-false": false, 60 "b-true": true, 61 "float": 1.0, 62 "float32": float32(1.0), 63 "float64": float64(1.0), 64 "float64-2": float64(1.1), 65 "i": int(1), 66 "i16": int16(1), 67 "i32": int32(1), 68 "i64": int64(1), 69 "i8": int8(1), 70 "u": uint(1), 71 "u16": uint16(1), 72 "u32": uint32(1), 73 "u64-large": uint64(math.MaxInt64 + 1), // skipped in expect string 74 "u64": uint64(1), 75 "u8": uint8(1), 76 }), WithTime(time.Unix(0, 123))) 77 78 assert.Equal(t, `abc []byte="YWJj"b,[]uint8="YWJj"b,b-false=false,b-true=true,float=1,float32=1,float64=1,float64-2=1.1,i=1i,i16=1i,i32=1i,i64=1i,i8=1i,u=1u,u16=1u,u32=1u,u64=1u,u64-large=9223372036854775808u,u8=1u 123`, 79 pt.LineProto()) 80 }) 81 82 t.Run("valid-fields-under-pb", func(t *T.T) { 83 kvs := map[string]interface{}{ 84 "[]byte": []byte("abc"), 85 "[]uint8": []uint8("abc"), 86 "b-false": false, 87 "b-true": true, 88 "float": 1.0, 89 "float32": float32(1.0), 90 "float64": float64(1.0), 91 "float64-2": float64(1.1), 92 "i": int(1), 93 "i16": int16(1), 94 "i32": int32(1), 95 "i64": int64(1), 96 "i8": int8(1), 97 "u": uint(1), 98 "u16": uint16(1), 99 "u32": uint32(1), 100 "u64": uint64(1), 101 "u64-large": uint64(math.MaxInt64 + 1), // skipped in expect string 102 "u8": uint8(1), 103 } 104 pt := NewPointV2(`abc`, NewKVs(kvs), WithTime(time.Unix(0, 123)), WithEncoding(Protobuf)) 105 expect := `abc []byte="YWJj"b,[]uint8="YWJj"b,b-false=false,b-true=true,float=1,float32=1,float64=1,float64-2=1.1,i=1i,i16=1i,i32=1i,i64=1i,i8=1i,u=1u,u16=1u,u32=1u,u64=1u,u64-large=9223372036854775808u,u8=1u 123` 106 assert.Equal(t, expect, pt.LineProto()) 107 }) 108 109 t.Run("basic", func(t *T.T) { 110 kvs := NewKVs(map[string]interface{}{"f1": 12}).MustAddTag(`t1`, `tval1`) 111 pt := NewPointV2(`abc`, kvs, WithTime(time.Unix(0, 123))) 112 113 assert.Equal(t, "abc,t1=tval1 f1=12i 123", pt.LineProto()) 114 }) 115 } 116 117 func TestNewPoint(t *T.T) { 118 cases := []struct { 119 opts []Option 120 121 tname, name, expect string 122 123 t map[string]string 124 f map[string]interface{} 125 126 warns int 127 withPool bool 128 }{ 129 { 130 tname: "valid-fields-with-point-pool", 131 opts: []Option{WithTime(time.Unix(0, 123))}, 132 name: "valid-fields", 133 withPool: true, 134 f: map[string]interface{}{ 135 "[]byte": []byte("abc"), 136 "[]uint8": []uint8("abc"), 137 138 "b-false": false, 139 "b-true": true, 140 "float": 1.0, 141 "float32": float32(1.0), 142 "float64": float64(1.0), 143 "float64-2": float64(1.1), 144 "i": int(1), 145 "i16": int16(1), 146 "i32": int32(1), 147 "i64": int64(1), 148 "i8": int8(1), 149 "u": uint(1), 150 "u16": uint16(1), 151 "u32": uint32(1), 152 "u64": uint64(1), 153 "u64-large": uint64(math.MaxInt64 + 1), // skipped in expect string 154 "u8": uint8(1), 155 }, 156 expect: `valid-fields []byte="YWJj"b,[]uint8="YWJj"b,b-false=false,b-true=true,float=1,float32=1,float64=1,float64-2=1.1,i=1i,i16=1i,i32=1i,i64=1i,i8=1i,u=1u,u16=1u,u32=1u,u64=1u,u64-large=9223372036854775808u,u8=1u 123`, 157 }, 158 159 { 160 tname: "valid-fields", 161 opts: []Option{WithTime(time.Unix(0, 123))}, 162 name: "valid-fields", 163 f: map[string]interface{}{ 164 "[]byte": []byte("abc"), 165 "[]uint8": []uint8("abc"), 166 167 "b-false": false, 168 "b-true": true, 169 "float": 1.0, 170 "float32": float32(1.0), 171 "float64": float64(1.0), 172 "float64-2": float64(1.1), 173 "i": int(1), 174 "i16": int16(1), 175 "i32": int32(1), 176 "i64": int64(1), 177 "i8": int8(1), 178 "u": uint(1), 179 "u16": uint16(1), 180 "u32": uint32(1), 181 "u64": uint64(1), 182 "u64-large": uint64(math.MaxInt64 + 1), // skipped in expect string 183 "u8": uint8(1), 184 }, 185 expect: `valid-fields []byte="YWJj"b,[]uint8="YWJj"b,b-false=false,b-true=true,float=1,float32=1,float64=1,float64-2=1.1,i=1i,i16=1i,i32=1i,i64=1i,i8=1i,u=1u,u16=1u,u32=1u,u64=1u,u64-large=9223372036854775808u,u8=1u 123`, 186 }, 187 188 { 189 tname: "valid-fields-under-pb", 190 opts: []Option{WithTime(time.Unix(0, 123)), WithEncoding(Protobuf)}, 191 name: "valid-fields", 192 f: map[string]interface{}{ 193 "[]byte": []byte("abc"), 194 "[]uint8": []uint8("abc"), 195 "b-false": false, 196 "b-true": true, 197 "float": 1.0, 198 "float32": float32(1.0), 199 "float64": float64(1.0), 200 "float64-2": float64(1.1), 201 "i": int(1), 202 "i16": int16(1), 203 "i32": int32(1), 204 "i64": int64(1), 205 "i8": int8(1), 206 "u": uint(1), 207 "u16": uint16(1), 208 "u32": uint32(1), 209 "u64": uint64(1), 210 "u64-large": uint64(math.MaxInt64 + 1), // skipped in expect string 211 "u8": uint8(1), 212 }, 213 expect: `valid-fields []byte="YWJj"b,[]uint8="YWJj"b,b-false=false,b-true=true,float=1,float32=1,float64=1,float64-2=1.1,i=1i,i16=1i,i32=1i,i64=1i,i8=1i,u=1u,u16=1u,u32=1u,u64=1u,u64-large=9223372036854775808u,u8=1u 123`, 214 }, 215 216 { 217 tname: "exceed-measurement-len", 218 opts: []Option{WithTime(time.Unix(0, 123)), WithMaxMeasurementLen(10)}, 219 220 name: "name-exceed-len", 221 f: map[string]interface{}{"f1": 123}, 222 expect: `name-excee f1=123i 123`, 223 warns: 1, 224 }, 225 226 { 227 tname: "empty-measurement", 228 opts: []Option{WithTime(time.Unix(0, 123))}, 229 name: "", 230 f: map[string]interface{}{"f1": 123}, 231 expect: fmt.Sprintf(`%s f1=123i 123`, DefaultMeasurementName), 232 warns: 1, 233 }, 234 235 //{ 236 // tname: "exceed-tag-kv-compose", 237 // opts: []Option{WithTime(time.Unix(0, 123)), WithMaxKVComposeLen(10)}, 238 // name: "abc", 239 // t: map[string]string{"t1": "12345", "t2": "ssclh"}, 240 // f: map[string]interface{}{"f1": 123}, 241 // expect: `abc,t1=12345 f1=123i 123`, 242 // warns: 1, 243 // }, 244 245 { 246 tname: "basic", 247 opts: []Option{WithTime(time.Unix(0, 123))}, 248 name: "abc", 249 t: map[string]string{"t1": "tval1"}, 250 f: map[string]interface{}{"f1": 12}, 251 expect: "abc,t1=tval1 f1=12i 123", 252 }, 253 { 254 tname: "metric-with-dot-in-field-key", 255 name: "abc", 256 opts: append(DefaultMetricOptions(), WithTime(time.Unix(0, 123))), 257 t: map[string]string{"t1": "tval1"}, 258 f: map[string]interface{}{"f.1": 12}, 259 expect: "abc,t1=tval1 f.1=12i 123", 260 }, 261 { 262 tname: "metric-with-dot-in-tag-key", 263 name: "abc", 264 opts: append(DefaultMetricOptions(), WithTime(time.Unix(0, 123))), 265 t: map[string]string{"t.1": "tval1"}, 266 f: map[string]interface{}{"f1": 12}, 267 expect: "abc,t.1=tval1 f1=12i 123", 268 }, 269 { 270 tname: "with-dot-in-t-f-key-on-non-metric-type", 271 name: "abc", 272 opts: append(DefaultObjectOptions(), WithTime(time.Unix(0, 123))), 273 274 t: map[string]string{"t1": "tval1"}, 275 f: map[string]interface{}{"f.1": 12}, 276 expect: fmt.Sprintf(`abc,t1=tval1 f_1=12i,name="%s" 123`, defaultObjectName), 277 warns: 2, 278 }, 279 280 { 281 tname: "with-dot-in-tag-field-key", 282 name: "abc", 283 opts: append(DefaultObjectOptions(), WithTime(time.Unix(0, 123))), 284 t: map[string]string{"t1": "abc", "t.2": "xyz"}, 285 f: map[string]interface{}{"f1": 123, "f.2": "def"}, 286 expect: fmt.Sprintf(`abc,t1=abc,t_2=xyz f1=123i,f_2="def",name="%s" 123`, defaultObjectName), 287 warns: 3, 288 }, 289 290 { 291 tname: "both-exceed-max-field-tag-count", 292 name: "abc", 293 t: map[string]string{ 294 "t1": "abc", 295 "t2": "xyz", 296 "t3": "abc", 297 "t4": "xyz", 298 "t5": "abc", 299 "t6": "abc", 300 "t7": "abc", 301 "t8": "abc", 302 "t9": "abc", 303 }, 304 f: map[string]interface{}{ 305 "f1": 123, 306 "f2": "def", 307 "f3": "def", 308 "f4": "def", 309 "f5": "def", 310 "f6": "def", 311 "f7": "def", 312 "f8": "def", 313 "f9": "def", 314 }, 315 opts: []Option{ 316 WithTime(time.Unix(0, 123)), 317 WithMaxTags(1), 318 WithMaxFields(1), 319 WithKeySorted(true), 320 }, 321 expect: `abc,t1=abc f1=123i 123`, 322 warns: 2, 323 }, 324 325 { 326 tname: "exceed-max-field-count", 327 name: "abc", 328 opts: []Option{WithTime(time.Unix(0, 123)), WithMaxFields(1), WithKeySorted(true)}, 329 t: map[string]string{ 330 "t1": "abc", 331 "t2": "xyz", 332 }, 333 f: map[string]interface{}{ 334 "f1": 123, 335 "f2": "def", 336 "f3": "def", 337 "f4": "def", 338 "f5": "def", 339 "f6": "def", 340 "f7": "def", 341 "f8": "def", 342 "f9": "def", 343 }, 344 expect: `abc,t1=abc,t2=xyz f1=123i 123`, 345 warns: 1, 346 }, 347 348 { 349 tname: "exceed-max-tag-count", 350 opts: []Option{WithTime(time.Unix(0, 123)), WithMaxTags(1), WithKeySorted(true)}, 351 name: "abc", 352 t: map[string]string{ 353 "t1": "abc", 354 "t2": "xyz", 355 "t3": "abc", 356 "t4": "xyz", 357 "t5": "abc", 358 "t6": "abc", 359 "t7": "abc", 360 "t8": "abc", 361 "t9": "abc", 362 }, 363 f: map[string]interface{}{ 364 "f1": 123, 365 }, 366 expect: `abc,t1=abc f1=123i 123`, 367 warns: 1, 368 }, 369 370 { 371 tname: "exceed-max-tag-key-len", 372 opts: []Option{WithTime(time.Unix(0, 123)), WithMaxTagKeyLen(1)}, 373 name: "abc", 374 t: map[string]string{"t1": "x"}, 375 f: map[string]interface{}{"f1": 123}, 376 expect: `abc,t=x f1=123i 123`, 377 warns: 1, 378 }, 379 380 { 381 tname: "exceed-max-tag-value-len", 382 opts: []Option{WithTime(time.Unix(0, 123)), WithMaxTagValLen(3)}, 383 name: "abc", 384 t: map[string]string{"t": "1234"}, 385 f: map[string]interface{}{"f1": 123}, 386 expect: `abc,t=123 f1=123i 123`, 387 warns: 1, 388 }, 389 390 { 391 tname: "exceed-max-field-key-len", 392 name: "abc", 393 opts: []Option{WithTime(time.Unix(0, 123)), WithMaxFieldKeyLen(3)}, 394 f: map[string]interface{}{"f123": 123}, 395 expect: `abc f12=123i 123`, 396 warns: 1, 397 }, 398 399 { 400 tname: "exceed-max-field-val-len", 401 name: "abc", 402 opts: []Option{WithTime(time.Unix(0, 123)), WithMaxFieldValLen(3)}, 403 f: map[string]interface{}{"f1": "hello"}, 404 expect: `abc f1="hel" 123`, 405 warns: 1, 406 }, 407 408 { 409 tname: "with-disabled-tag-key-source", 410 name: "abc", 411 opts: append(DefaultLoggingOptions(), WithTime(time.Unix(0, 123))), 412 413 t: map[string]string{"source": "s1"}, 414 f: map[string]interface{}{"f1": 123}, 415 expect: fmt.Sprintf(`abc f1=123i,status="%s" 123`, defaultLoggingStatus), 416 warns: 2, 417 }, 418 { 419 tname: "with-disabled-field-key", 420 name: "abc", 421 opts: append(DefaultObjectOptions(), WithTime(time.Unix(0, 123))), 422 t: map[string]string{"class": "xyz"}, 423 f: map[string]interface{}{"class": 123, "f1": 1}, 424 expect: fmt.Sprintf(`abc f1=1i,name="%s" 123`, defaultObjectName), 425 426 // NOTE: tag key `class` override field `class`, then the tag disabled 427 warns: 2, 428 }, 429 430 { 431 tname: "normal", 432 opts: []Option{WithTime(time.Unix(0, 123))}, 433 name: "abc", 434 t: map[string]string{}, 435 f: map[string]interface{}{"f1": 123}, 436 expect: "abc f1=123i 123", 437 }, 438 439 { 440 tname: "invalid-category", 441 opts: []Option{WithTime(time.Unix(0, 123))}, 442 name: "abc", 443 f: map[string]interface{}{"f1": 123}, 444 expect: `abc f1=123i 123`, 445 }, 446 447 { 448 tname: "nil-opiton", 449 name: "abc", 450 t: map[string]string{}, 451 f: map[string]interface{}{"f1": 123}, 452 }, 453 } 454 455 for _, tc := range cases { 456 t.Run(tc.tname, func(t *T.T) { 457 var ( 458 pt *Point 459 err error 460 ) 461 462 if tc.withPool { 463 pp := NewReservedCapPointPool(100) 464 SetPointPool(pp) 465 defer func() { 466 ClearPointPool() 467 468 assert.True(t, pt.HasFlag(Ppooled)) 469 pp.Put(pt) 470 }() 471 } 472 473 pt, err = NewPoint(tc.name, tc.t, tc.f, tc.opts...) 474 475 assert.NoError(t, err) 476 477 x := pt.LineProto() 478 479 if tc.expect != "" { 480 assert.Equal(t, tc.expect, x, "pt: %s, kvs: %s", pt.Pretty(), KVs(pt.pt.Fields).Pretty()) 481 } else { 482 assert.NotEqual(t, x, "", "got %s", pt.Pretty()) 483 t.Logf("got %s", x) 484 } 485 486 assert.Equal(t, tc.warns, len(pt.pt.Warns), "pt: %s", pt.Pretty()) 487 }) 488 } 489 } 490 491 func TestPointKeySorted(t *testing.T) { 492 t.Run("sorted", func(t *testing.T) { 493 pt, err := NewPoint("basic", 494 map[string]string{ 495 "t1": "v1", 496 "t2": "v2", 497 "t3": "v1", 498 "t4": "v2", 499 "t5": "v1", 500 "t6": "v2", 501 "t7": "v1", 502 "t8": "v2", 503 }, 504 map[string]any{ 505 "f1": 1, 506 "f2": 2, 507 "f3": 3, 508 "f4": 1, 509 "f5": 2, 510 "f6": 3, 511 "f7": 1, 512 "f8": 2, 513 "f9": 3, 514 }, 515 WithKeySorted(true), 516 ) 517 518 assert.NoError(t, err) 519 520 assert.True(t, sort.IsSorted(KVs(pt.pt.Fields))) 521 522 t.Logf("pt: %s", pt.Pretty()) 523 }) 524 525 t.Run("not-sorted", func(t *testing.T) { 526 pt, err := NewPoint("basic", 527 map[string]string{ 528 "t1": "v1", 529 "t2": "v2", 530 "t3": "v1", 531 "t4": "v2", 532 "t5": "v1", 533 "t6": "v2", 534 "t7": "v1", 535 "t8": "v2", 536 }, 537 map[string]any{ 538 "f1": 1, 539 "f2": 2, 540 "f3": 3, 541 "f4": 1, 542 "f5": 2, 543 "f6": 3, 544 "f7": 1, 545 "f8": 2, 546 "f9": 3, 547 }, 548 WithKeySorted(false), 549 ) 550 551 assert.NoError(t, err) 552 553 assert.False(t, sort.IsSorted(KVs(pt.pt.Fields))) 554 555 t.Logf("pt: %s", pt.Pretty()) 556 }) 557 } 558 559 func BenchmarkV2NewPoint(b *T.B) { 560 b.Run(`with-maps`, func(b *T.B) { 561 for i := 0; i < b.N; i++ { 562 tags := map[string]string{ 563 "t1": "val1", 564 "t2": "val2", 565 "t3": "val3", 566 "t4": "val4", 567 "t5": "val5", 568 "t6": "val6", 569 "t7": "val7", 570 "t8": "val8", 571 "t9": "val9", 572 "t0": "val0", 573 } 574 fields := map[string]interface{}{ 575 "f1": 123, 576 "f2": "abc", 577 "f3": 45.6, 578 "f4": 123, 579 "f5": "abc", 580 "f6": 45.6, 581 "f7": 123, 582 "f8": "abc", 583 "f9": 45.6, 584 "f10": false, 585 } 586 587 NewPointV2("abc", append(NewTags(tags), NewKVs(fields)...)) 588 } 589 }) 590 591 b.Run(`without-map-without-prealloc`, func(b *T.B) { 592 for i := 0; i < b.N; i++ { 593 var kvs KVs 594 kvs = kvs.AddTag("t1", "val1") 595 kvs = kvs.AddTag("t2", "val2") 596 kvs = kvs.AddTag("t3", "val3") 597 kvs = kvs.AddTag("t4", "val4") 598 kvs = kvs.AddTag("t5", "val5") 599 kvs = kvs.AddTag("t6", "val6") 600 kvs = kvs.AddTag("t7", "val7") 601 kvs = kvs.AddTag("t8", "val8") 602 kvs = kvs.AddTag("t9", "val9") 603 kvs = kvs.AddTag("t0", "val0") 604 605 kvs = kvs.Add("f1", 123, false, false) 606 kvs = kvs.Add("f2", "abc", false, false) 607 kvs = kvs.Add("f3", 45.6, false, false) 608 kvs = kvs.Add("f4", 123, false, false) 609 kvs = kvs.Add("f5", "abc", false, false) 610 kvs = kvs.Add("f6", 45.6, false, false) 611 kvs = kvs.Add("f7", 123, false, false) 612 kvs = kvs.Add("f8", "abc", false, false) 613 kvs = kvs.Add("f9", 45.6, false, false) 614 kvs = kvs.Add("f10", false, false, false) 615 616 NewPointV2("abc", kvs) 617 } 618 }) 619 620 b.Run(`without-map-with-prealloc`, func(b *T.B) { 621 for i := 0; i < b.N; i++ { 622 kvs := make(KVs, 0, 20) 623 kvs = kvs.AddTag("t1", "val1") 624 kvs = kvs.AddTag("t2", "val2") 625 kvs = kvs.AddTag("t3", "val3") 626 kvs = kvs.AddTag("t5", "val4") 627 kvs = kvs.AddTag("t5", "val5") 628 kvs = kvs.AddTag("t6", "val6") 629 kvs = kvs.AddTag("t7", "val7") 630 kvs = kvs.AddTag("t8", "val8") 631 kvs = kvs.AddTag("t9", "val9") 632 kvs = kvs.AddTag("t0", "val0") 633 634 kvs = kvs.Add("f1", 123, false, false) 635 kvs = kvs.Add("f2", "abc", false, false) 636 kvs = kvs.Add("f3", 45.6, false, false) 637 kvs = kvs.Add("f4", 123, false, false) 638 kvs = kvs.Add("f5", "abc", false, false) 639 kvs = kvs.Add("f6", 45.6, false, false) 640 kvs = kvs.Add("f7", 123, false, false) 641 kvs = kvs.Add("f8", "abc", false, false) 642 kvs = kvs.Add("f9", 45.6, false, false) 643 kvs = kvs.Add("f10", false, false, false) 644 645 NewPointV2("abc", kvs) 646 } 647 }) 648 649 b.Run(`without-map-with-prealloc-and-MUST`, func(b *T.B) { 650 for i := 0; i < b.N; i++ { 651 kvs := make(KVs, 0, 20) 652 kvs = kvs.MustAddTag("t1", "val1") 653 kvs = kvs.MustAddTag("t2", "val2") 654 kvs = kvs.MustAddTag("t3", "val3") 655 kvs = kvs.MustAddTag("t4", "val4") 656 kvs = kvs.MustAddTag("t5", "val5") 657 kvs = kvs.MustAddTag("t6", "val6") 658 kvs = kvs.MustAddTag("t7", "val7") 659 kvs = kvs.MustAddTag("t8", "val8") 660 kvs = kvs.MustAddTag("t9", "val9") 661 kvs = kvs.MustAddTag("t0", "val0") 662 663 kvs = kvs.Add("f1", 123, false, true) 664 kvs = kvs.Add("f2", "abc", false, true) 665 kvs = kvs.Add("f3", 45.6, false, true) 666 kvs = kvs.Add("f4", 123, false, true) 667 kvs = kvs.Add("f5", "abc", false, true) 668 kvs = kvs.Add("f6", 45.6, false, true) 669 kvs = kvs.Add("f7", 123, false, true) 670 kvs = kvs.Add("f8", "abc", false, true) 671 kvs = kvs.Add("f9", 45.6, false, true) 672 kvs = kvs.Add("f10", false, false, true) 673 674 NewPointV2("abc", kvs) 675 } 676 }) 677 678 b.Run("with-point-pool-level3", func(b *T.B) { 679 pp := NewReservedCapPointPool(100) 680 SetPointPool(pp) 681 682 defer func() { 683 SetPointPool(nil) 684 }() 685 686 b.ResetTimer() 687 for i := 0; i < b.N; i++ { 688 kvs := make(KVs, 0, 20) 689 kvs = kvs.MustAddTag("t1", "val1") 690 kvs = kvs.MustAddTag("t2", "val2") 691 kvs = kvs.MustAddTag("t3", "val3") 692 kvs = kvs.MustAddTag("t4", "val4") 693 kvs = kvs.MustAddTag("t5", "val5") 694 kvs = kvs.MustAddTag("t6", "val6") 695 kvs = kvs.MustAddTag("t7", "val7") 696 kvs = kvs.MustAddTag("t8", "val8") 697 kvs = kvs.MustAddTag("t9", "val9") 698 kvs = kvs.MustAddTag("t0", "val0") 699 700 kvs = kvs.Add("f1", 123, false, true) 701 kvs = kvs.Add("f2", "abc", false, true) 702 kvs = kvs.Add("f3", 45.6, false, true) 703 kvs = kvs.Add("f4", 123, false, true) 704 kvs = kvs.Add("f5", "abc", false, true) 705 kvs = kvs.Add("f6", 45.6, false, true) 706 kvs = kvs.Add("f7", 123, false, true) 707 kvs = kvs.Add("f8", "abc", false, true) 708 kvs = kvs.Add("f9", 45.6, false, true) 709 kvs = kvs.Add("f10", false, false, true) 710 711 pt := NewPointV2("abc", kvs) 712 pp.Put(pt) 713 } 714 }) 715 716 b.Run(`key-sorted`, func(b *T.B) { 717 ptName := `abc` 718 kvs := NewKVs(map[string]any{ 719 "f1": 123, 720 "f2": 3.14, 721 "f3": "str", 722 723 "_f1": 123, 724 "_f2": 3.14, 725 "_f3": "str", 726 727 "_f1_": 123, 728 "_f2_": 3.14, 729 "_f3_": "str", 730 }) 731 732 for i := 0; i < b.N; i++ { 733 NewPointV2(ptName, kvs, WithKeySorted(true)) 734 } 735 }) 736 737 b.Run(`key-not-sorted`, func(b *T.B) { 738 ptName := `abc` 739 kvs := NewKVs(map[string]any{ 740 "f1": 123, 741 "f2": 3.14, 742 "f3": "str", 743 744 "_f1": 123, 745 "_f2": 3.14, 746 "_f3": "str", 747 748 "_f1_": 123, 749 "_f2_": 3.14, 750 "_f3_": "str", 751 }) 752 753 for i := 0; i < b.N; i++ { 754 NewPointV2(ptName, kvs) 755 } 756 }) 757 } 758 759 func FuzzPLPBEquality(f *testing.F) { 760 cases := []struct { 761 measurement string 762 tagk string 763 tagv string 764 765 i64 int64 766 u64 uint64 767 str string 768 b bool 769 f float64 770 d []byte 771 time int64 772 }{ 773 { 774 measurement: "", 775 tagk: "tag", 776 tagv: "tval", 777 778 i64: int64(1), 779 u64: uint64(123), 780 str: "hello", 781 b: false, 782 f: 3.14, 783 d: []byte("world"), 784 time: 123, 785 }, 786 } 787 788 for _, tc := range cases { 789 f.Add(tc.measurement, tc.tagk, tc.tagv, tc.i64, tc.u64, tc.str, tc.b, tc.f, tc.d, tc.time) 790 } 791 792 f.Fuzz(func(t *testing.T, 793 measurement, tagk, tagv string, 794 i64 int64, u64 uint64, str string, b bool, f float64, d []byte, ts int64, 795 ) { 796 if ts < 0 { // force ts > 0 to make 2 point's time are equal. under ts < 0, NewPoint will use time.Now() 797 ts = 0 798 } 799 800 lppt, err := NewPoint(measurement, 801 map[string]string{tagk: tagv}, 802 map[string]interface{}{ 803 "i64": i64, 804 "u64": u64, 805 "str": str, 806 "b": b, 807 "f": f, 808 "d": d, 809 }, 810 WithTimestamp(ts), 811 WithDotInKey(true) /* random string may contains '.' */) 812 813 assert.NoError(t, err) 814 815 pbpt, err := NewPoint(measurement, 816 map[string]string{tagk: tagv}, 817 map[string]interface{}{ 818 "i64": i64, 819 "u64": u64, 820 "str": str, 821 "b": b, 822 "f": f, 823 "d": d, 824 }, 825 WithTimestamp(ts), 826 WithDotInKey(true), // random string may contains '.' 827 WithEncoding(Protobuf)) 828 829 assert.NoError(t, err) 830 831 _ = pbpt 832 _ = lppt 833 834 ok, why := lppt.EqualWithReason(pbpt) 835 assert.Truef(t, ok, "why: %s, ts: %d", why, ts) 836 }) 837 } 838 839 func TestTimeUnix(t *T.T) { 840 t.Run("-1", func(t *T.T) { 841 t.Logf("date: %s", time.Unix(0, -1000).UTC()) 842 }) 843 }