github.com/GuanceCloud/cliutils@v1.1.21/lineproto/lp_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 lineproto 7 8 import ( 9 "fmt" 10 "runtime" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/GuanceCloud/cliutils" 16 "github.com/GuanceCloud/cliutils/testutil" 17 influxdb "github.com/influxdata/influxdb1-client/v2" 18 ) 19 20 func TestUnsafeBytesToString(t *testing.T) { 21 runes := []byte{'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!'} 22 fmt.Printf("%p\n", runes) 23 s := unsafeBytesToString(runes) 24 runes = []byte{'g', 'o', 'l', 'a', 'n', 'g'} 25 fmt.Printf("%p\n", runes) 26 runtime.GC() 27 testutil.Equals(t, s, "hello world!") 28 } 29 30 func TestInterfaceToValue(t *testing.T) { 31 ints := []interface{}{ 32 -5, 33 int8(-5), 34 int16(-5), 35 int32(-5), 36 int64(-5), 37 38 uint(5), 39 uint8(5), 40 uint16(5), 41 uint32(5), 42 uint64(5), 43 44 float32(3.14), 45 3.14, 46 47 true, 48 "hello world", 49 []byte{'f', 'o', 'o'}, 50 51 []string{"hello", "world"}, 52 map[string]int{"foo": 333333, "bar": 44444}, 53 54 struct { 55 Name string 56 Age int 57 }{"foobar", 16}, 58 } 59 60 for _, i := range ints { 61 v, ok := InterfaceToValue(i) 62 if !ok { 63 t.Errorf("can not new value from interface: %T, %v", i, i) 64 } 65 t.Logf("%T, %v -> %v", i, i, v) 66 } 67 } 68 69 func TestPointString(t *testing.T) { 70 tags := map[string]string{ 71 "t1": cliutils.CreateRandomString(100), 72 "t2": cliutils.CreateRandomString(100), 73 } 74 fields := map[string]interface{}{ 75 "f1": int64(1024), 76 "f2": 1024.2048, 77 "f3": cliutils.CreateRandomString(128), 78 } 79 80 pt, _ := NewPoint("foobar", tags, fields, time.Now()) 81 line, err := pt.String() 82 if err != nil { 83 t.Fatal(err) 84 } 85 t.Logf("[%s]\n", line) 86 } 87 88 func TestParse(t *testing.T) { 89 lines := ` 90 91 92 error,t1=tag1,t2=tag2 f1=1.0,f2=2i,f3="abc" 93 view,t1=tag2,t2=tag2 f1=1.0,f2=2i,f3="abc" 1625823259000000000 94 resource,t1=tag3,t2=tag2 f1=1.0,f2=2i,f3="abc" 1621239130 95 long_task,t1=tag4,t2=tag2 f1=1.0,f2=2i,f3="abc" 96 action,t1=tag5,t2=tag2 f1=1.0,f2=2i,f3="abc" 97 98 99 100 ` 101 102 pts, err := Parse([]byte(lines), DefaultOption) 103 if err != nil { 104 t.Error(err) 105 } 106 107 if len(pts) != 5 { 108 t.Errorf("expected %d points, actually get %d points", 5, len(pts)) 109 } 110 111 for _, pt := range pts { 112 t.Logf("%+#v", pt) 113 } 114 } 115 116 func BenchmarkParse(b *testing.B) { 117 cases := []struct { 118 name string 119 data []byte 120 opt *Option 121 optSetters []OptionSetter 122 }{ 123 { 124 name: "parse-multi-short", 125 data: []byte(strings.Join([]string{ 126 `foo,tag1=val1,tag2=val2 x=1,y="hello" 1625823259000000`, 127 `foo,tag1=val1,tag2=val2 x=1,y="hello" 1625823259000000`, 128 `foo,tag1=val1,tag2=val2 x=1,y="hello" 1625823259000000`, 129 `foo,tag1=val1,tag2=val2 x=1,y="hello" 1625823259000000`, 130 }, "\n")), 131 opt: &Option{PrecisionV2: Microsecond}, 132 optSetters: []OptionSetter{WithPrecisionV2(Microsecond)}, 133 }, 134 135 { 136 name: "parse-multi-long-with-32k-field", 137 data: []byte(strings.Join([]string{ 138 fmt.Sprintf(`foo,tag1=%s,tag2=%s f1=1,f2="%s",f3=3i 1625823259000000`, cliutils.CreateRandomString(100), cliutils.CreateRandomString(100), cliutils.CreateRandomString(32*1024)), 139 fmt.Sprintf(`foo,tag1=%s,tag2=%s f1=1,f2="%s",f3=3i 1625823259000000`, cliutils.CreateRandomString(100), cliutils.CreateRandomString(100), cliutils.CreateRandomString(32*1024)), 140 fmt.Sprintf(`foo,tag1=%s,tag2=%s f1=1,f2="%s",f3=3i 1625823259000000`, cliutils.CreateRandomString(100), cliutils.CreateRandomString(100), cliutils.CreateRandomString(32*1024)), 141 fmt.Sprintf(`foo,tag1=%s,tag2=%s f1=1,f2="%s",f3=3i 1625823259000000`, cliutils.CreateRandomString(100), cliutils.CreateRandomString(100), cliutils.CreateRandomString(32*1024)), 142 }, "\n")), 143 opt: &Option{PrecisionV2: Microsecond}, 144 optSetters: []OptionSetter{WithPrecisionV2(Microsecond)}, 145 }, 146 } 147 148 for _, tc := range cases { 149 b.Run(tc.name+"-New", func(b *testing.B) { 150 for i := 0; i < b.N; i++ { 151 pts, err := ParseWithOptionSetter(tc.data, tc.optSetters...) 152 if err != nil { 153 b.Errorf("Parse: %s", err.Error()) 154 } 155 _ = pts 156 } 157 }) 158 159 b.Run(tc.name+"-Old", func(b *testing.B) { 160 for i := 0; i < b.N; i++ { 161 pts, err := ParsePoints(tc.data, tc.opt) 162 if err != nil { 163 b.Errorf("Parse: %s", err.Error()) 164 } 165 _ = pts 166 } 167 }) 168 } 169 } 170 171 func TestNewLineEncoder(t *testing.T) { 172 cases := []struct { 173 name string 174 pts []struct { 175 measurement string 176 tags map[string]string 177 fields map[string]interface{} 178 time time.Time 179 } 180 opt *Option 181 }{ 182 { 183 name: "encode-multi-short", 184 opt: &Option{PrecisionV2: Microsecond}, 185 pts: []struct { 186 measurement string 187 tags map[string]string 188 fields map[string]interface{} 189 time time.Time 190 }{ 191 { 192 measurement: "foo", 193 tags: map[string]string{ 194 "t2": cliutils.CreateRandomString(100), 195 "t1": cliutils.CreateRandomString(100), 196 }, 197 fields: map[string]interface{}{ 198 "f3": int64(1024), 199 "f1": 1024.2048, 200 "f2": cliutils.CreateRandomString(128), 201 }, 202 time: time.Now(), 203 }, 204 { 205 measurement: "foo2", 206 tags: map[string]string{ 207 "aaa": cliutils.CreateRandomString(110), 208 "AAA": cliutils.CreateRandomString(110), 209 }, 210 fields: map[string]interface{}{ 211 "f1": int64(1024), 212 "f5": 1024.2048, 213 "f3": cliutils.CreateRandomString(138), 214 }, 215 time: time.Now(), 216 }, 217 218 { 219 measurement: "foo3", 220 tags: map[string]string{ 221 "t31": cliutils.CreateRandomString(100), 222 "t22": cliutils.CreateRandomString(120), 223 }, 224 fields: map[string]interface{}{ 225 "f1": int64(1024), 226 "f222": 1024.2048, 227 "f3": cliutils.CreateRandomString(148), 228 }, 229 time: time.Now(), 230 }, 231 }, 232 }, 233 } 234 235 encoder := NewLineEncoder() 236 237 var point *Point 238 for _, tc := range cases { 239 for _, pt := range tc.pts { 240 newPoint, err := NewPoint(pt.measurement, 241 pt.tags, 242 pt.fields, 243 pt.time) 244 if err != nil { 245 t.Fatal(err) 246 } 247 point = newPoint 248 249 err = encoder.AppendPoint(newPoint) 250 if err != nil { 251 t.Fatal(err) 252 } 253 254 bts, _ := encoder.Bytes() 255 fmt.Println(len(bts)) 256 } 257 } 258 259 chars, _ := encoder.Bytes() 260 261 fmt.Println(string(chars)) 262 263 lineBytes, err := encoder.BytesWithoutLn() 264 if err != nil { 265 t.Fatal(err) 266 } 267 268 fmt.Printf("[%s]\n", lineBytes) 269 270 encoder.SetBuffer(chars[807:]) 271 if err := encoder.AppendPoint(point); err != nil { 272 t.Fatal(err) 273 } 274 275 chars, _ = encoder.Bytes() 276 277 fmt.Println(string(chars)) 278 279 encoder = NewLineEncoder() 280 chars, err = encoder.Bytes() 281 if err != nil { 282 t.Fatal(err) 283 } 284 fmt.Println(chars) 285 str, err := encoder.UnsafeString() 286 if err != nil { 287 t.Fatal(err) 288 } 289 fmt.Printf("%q\n", str) 290 } 291 292 func TestEncode(t *testing.T) { 293 cases := []struct { 294 name string 295 pts []struct { 296 measurement string 297 tags map[string]string 298 fields map[string]interface{} 299 time time.Time 300 } 301 opt *Option 302 }{ 303 { 304 name: "encode-multi-short", 305 opt: &Option{PrecisionV2: Microsecond}, 306 pts: []struct { 307 measurement string 308 tags map[string]string 309 fields map[string]interface{} 310 time time.Time 311 }{ 312 { 313 measurement: "foo", 314 tags: map[string]string{ 315 "tttttt": "", 316 "t1": cliutils.CreateRandomString(100), 317 "t2": cliutils.CreateRandomString(100), 318 }, 319 fields: map[string]interface{}{ 320 "f1": int64(1024), 321 "f2": 1024.2048, 322 "f3": cliutils.CreateRandomString(128), 323 "f4": "", 324 }, 325 time: time.Now(), 326 }, 327 { 328 measurement: "foo2", 329 tags: map[string]string{ 330 "tttt": "", 331 "t1": cliutils.CreateRandomString(100), 332 "t2": cliutils.CreateRandomString(100), 333 }, 334 fields: map[string]interface{}{ 335 "ffff": "", 336 "f1": int64(1024), 337 "f2": 1024.2048, 338 "f3": cliutils.CreateRandomString(128), 339 }, 340 time: time.Now(), 341 }, 342 }, 343 }, 344 } 345 346 for _, tc := range cases { 347 t.Run(tc.name+"-New", func(t *testing.T) { 348 pts := make([]*Point, 0, len(tc.pts)) 349 for _, pt := range tc.pts { 350 newPoint, err := NewPoint(pt.measurement, 351 pt.tags, 352 pt.fields, 353 pt.time) 354 if err != nil { 355 t.Error(err) 356 return 357 } 358 359 pts = append(pts, newPoint) 360 } 361 362 lines, err := Encode(pts) 363 if err != nil { 364 t.Error(err) 365 } else { 366 t.Logf("[%s]", string(lines)) 367 } 368 }) 369 } 370 } 371 372 func BenchmarkEncode(b *testing.B) { 373 cases := []struct { 374 name string 375 pts []struct { 376 measurement string 377 tags map[string]string 378 fields map[string]interface{} 379 time time.Time 380 } 381 opt *Option 382 }{ 383 { 384 name: "encode-multi-short", 385 opt: &Option{PrecisionV2: Microsecond}, 386 pts: []struct { 387 measurement string 388 tags map[string]string 389 fields map[string]interface{} 390 time time.Time 391 }{ 392 { 393 measurement: "foo", 394 tags: map[string]string{ 395 "t1": cliutils.CreateRandomString(100), 396 "t2": cliutils.CreateRandomString(100), 397 }, 398 fields: map[string]interface{}{ 399 "f1": int64(1024), 400 "f2": 1024.2048, 401 "f3": cliutils.CreateRandomString(128), 402 }, 403 time: time.Now(), 404 }, 405 }, 406 }, 407 408 { 409 name: "encode-multi-long-with-32k-fields", 410 opt: &Option{PrecisionV2: Microsecond}, 411 pts: []struct { 412 measurement string 413 tags map[string]string 414 fields map[string]interface{} 415 time time.Time 416 }{ 417 { 418 measurement: "foo", 419 tags: map[string]string{ 420 "t1": cliutils.CreateRandomString(100), 421 "t2": cliutils.CreateRandomString(100), 422 }, 423 fields: map[string]interface{}{ 424 "f1": int64(1024), 425 "f2": 1024.2048, 426 "f3": cliutils.CreateRandomString(1024), 427 "f4": cliutils.CreateRandomString(32 * 1024), 428 }, 429 time: time.Now(), 430 }, 431 432 { 433 measurement: "foo", 434 tags: map[string]string{ 435 "t1": cliutils.CreateRandomString(100), 436 "t2": cliutils.CreateRandomString(100), 437 }, 438 fields: map[string]interface{}{ 439 "f1": int64(1024), 440 "f2": 1024.2048, 441 "f3": cliutils.CreateRandomString(1024), 442 "f4": cliutils.CreateRandomString(32 * 1024), 443 }, 444 time: time.Now(), 445 }, 446 447 { 448 measurement: "foo", 449 tags: map[string]string{ 450 "t1": cliutils.CreateRandomString(100), 451 "t2": cliutils.CreateRandomString(100), 452 }, 453 fields: map[string]interface{}{ 454 "f1": int64(1024), 455 "f2": 1024.2048, 456 "f3": cliutils.CreateRandomString(1024), 457 "f4": cliutils.CreateRandomString(32 * 1024), 458 }, 459 time: time.Now(), 460 }, 461 }, 462 }, 463 } 464 465 for _, tc := range cases { 466 b.Run(tc.name+"-New", func(b *testing.B) { 467 encoder := NewLineEncoder() 468 469 for i := 0; i < b.N; i++ { 470 for _, pt := range tc.pts { 471 newPoint, err := NewPoint(pt.measurement, 472 pt.tags, 473 pt.fields, 474 pt.time) 475 if err != nil { 476 b.Error(err) 477 return 478 } 479 encoder.Reset() 480 _ = encoder.AppendPoint(newPoint) 481 _, err = encoder.Bytes() 482 if err != nil { 483 b.Error(err) 484 return 485 } 486 } 487 } 488 }) 489 490 b.Run(tc.name+"-Old", func(b *testing.B) { 491 for i := 0; i < b.N; i++ { 492 for _, pt := range tc.pts { 493 oldPoint, err := influxdb.NewPoint(pt.measurement, 494 pt.tags, 495 pt.fields, 496 pt.time) 497 if err != nil { 498 b.Error(err) 499 return 500 } 501 502 _ = oldPoint.String() 503 } 504 } 505 }) 506 } 507 } 508 509 func TestLineEncoderBytesWithoutLn(t *testing.T) { 510 cases := []struct { 511 name string 512 pts []struct { 513 measurement string 514 tags map[string]string 515 fields map[string]interface{} 516 time time.Time 517 } 518 opt *Option 519 }{ 520 { 521 name: "encode-multi-short", 522 opt: &Option{PrecisionV2: Microsecond}, 523 pts: []struct { 524 measurement string 525 tags map[string]string 526 fields map[string]interface{} 527 time time.Time 528 }{ 529 { 530 measurement: "foo", 531 tags: map[string]string{ 532 "t2": cliutils.CreateRandomString(100), 533 "t1": cliutils.CreateRandomString(100), 534 }, 535 fields: map[string]interface{}{ 536 "f3": int64(1024), 537 "f1": 1024.2048, 538 "f2": cliutils.CreateRandomString(128), 539 }, 540 time: time.Now(), 541 }, 542 { 543 measurement: "foo2", 544 tags: map[string]string{ 545 "aaa": cliutils.CreateRandomString(110), 546 "AAA": cliutils.CreateRandomString(110), 547 }, 548 fields: map[string]interface{}{ 549 "f1": int64(1024), 550 "f5": 1024.2048, 551 "f3": cliutils.CreateRandomString(138), 552 }, 553 time: time.Now(), 554 }, 555 556 { 557 measurement: "foo3", 558 tags: map[string]string{ 559 "t31": cliutils.CreateRandomString(100), 560 "t22": cliutils.CreateRandomString(120), 561 }, 562 fields: map[string]interface{}{ 563 "f1": int64(1024), 564 "f222": 1024.2048, 565 "f3": cliutils.CreateRandomString(148), 566 }, 567 time: time.Now(), 568 }, 569 }, 570 }, 571 } 572 573 for _, tc := range cases { 574 t.Run(tc.name, func(t *testing.T) { 575 encoder := NewLineEncoder() 576 577 for _, pt := range tc.pts { 578 encoder.Reset() 579 point, _ := NewPoint(pt.measurement, pt.tags, pt.fields, pt.time) 580 if err := encoder.AppendPoint(point); err != nil { 581 t.Fatal(err) 582 } 583 line, err := encoder.BytesWithoutLn() 584 if err != nil { 585 t.Fatal(err) 586 } 587 588 t.Logf("%q\n", string(line)) 589 } 590 }) 591 } 592 }