go-hep.org/x/hep@v0.38.1/groot/rdict/streamer_test.go (about) 1 // Copyright ©2018 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package rdict 6 7 import ( 8 "fmt" 9 "reflect" 10 "testing" 11 "unsafe" 12 13 "go-hep.org/x/hep/groot/rbase" 14 "go-hep.org/x/hep/groot/rbytes" 15 "go-hep.org/x/hep/groot/rcont" 16 "go-hep.org/x/hep/groot/rmeta" 17 "go-hep.org/x/hep/groot/root" 18 ) 19 20 func TestIsTObject(t *testing.T) { 21 for _, tc := range []struct { 22 typ reflect.Type 23 want bool 24 }{ 25 { 26 typ: reflect.TypeOf(rbase.Object{}), 27 want: false, 28 }, 29 { 30 typ: reflect.TypeOf(&rbase.Object{}), 31 want: true, 32 }, 33 { 34 typ: reflect.TypeOf((*rbase.ObjString)(nil)), 35 want: true, 36 }, 37 { 38 typ: reflect.TypeOf(int(0)), 39 want: false, 40 }, 41 { 42 typ: reflect.TypeOf((*rcont.List)(nil)), 43 want: true, 44 }, 45 { 46 typ: reflect.TypeOf(tobject{}), 47 want: true, 48 }, 49 { 50 typ: reflect.TypeOf(&tobject{}), 51 want: true, 52 }, 53 } { 54 t.Run(fmt.Sprintf("type=%v", tc.typ), func(t *testing.T) { 55 got := isTObject(tc.typ) 56 if got != tc.want { 57 t.Fatalf("invalid is-TObject: got=%v, want=%v", got, tc.want) 58 } 59 }) 60 } 61 } 62 63 func TestHasCount(t *testing.T) { 64 for _, tc := range []struct { 65 tag reflect.StructTag 66 ok bool 67 want string 68 }{ 69 { 70 tag: ``, 71 }, 72 { 73 tag: `groot:"Name"`, 74 }, 75 { 76 tag: `groot:"Name[N]"`, 77 ok: true, 78 want: "N", 79 }, 80 { 81 tag: `groot:"Name[n1_2_3]"`, 82 ok: true, 83 want: "n1_2_3", 84 }, 85 { 86 tag: `groot:"Name[ N ]"`, 87 ok: true, 88 want: "N", 89 }, 90 { 91 tag: `groot:"Name[]"`, 92 }, 93 { 94 tag: `groot:"Name[ ]"`, 95 }, 96 { 97 tag: `groot:"Name[1]"`, 98 }, 99 { 100 tag: `groot:"Name[N;1]"`, 101 }, 102 { 103 tag: `groot:"Name[N-1]"`, 104 }, 105 { 106 tag: `groot:"Name[N'1]"`, 107 }, 108 { 109 tag: `groot:"Name[1N]"`, 110 }, 111 { 112 tag: `groot:"Name[1,2,3]"`, 113 }, 114 } { 115 t.Run(string(tc.tag), func(t *testing.T) { 116 got, ok := hasCount(reflect.StructField{Tag: tc.tag}) 117 if ok != tc.ok { 118 t.Fatalf("invalid ok: got=%v, want=%v", ok, tc.ok) 119 } 120 if got != tc.want { 121 t.Fatalf("invalid count: got=%q, want=%q", got, tc.want) 122 } 123 }) 124 } 125 } 126 127 func TestTypenameOf(t *testing.T) { 128 for _, tc := range []struct { 129 name string 130 typ reflect.Type 131 want string 132 panics string 133 }{ 134 { 135 name: "bool", 136 typ: reflect.TypeOf(false), 137 want: "bool", 138 }, 139 { 140 name: "*bool", 141 typ: reflect.TypeOf((*bool)(nil)), 142 want: "bool*", 143 }, 144 { 145 name: "int8", 146 typ: reflect.TypeOf(int8(0)), 147 want: "int8_t", 148 }, 149 { 150 name: "int16", 151 typ: reflect.TypeOf(int16(0)), 152 want: "int16_t", 153 }, 154 { 155 name: "int32", 156 typ: reflect.TypeOf(int32(0)), 157 want: "int32_t", 158 }, 159 { 160 name: "int64", 161 typ: reflect.TypeOf(int64(0)), 162 want: "int64_t", 163 }, 164 { 165 name: "uint8", 166 typ: reflect.TypeOf(uint8(0)), 167 want: "uint8_t", 168 }, 169 { 170 name: "uint16", 171 typ: reflect.TypeOf(uint16(0)), 172 want: "uint16_t", 173 }, 174 { 175 name: "uint32", 176 typ: reflect.TypeOf(uint32(0)), 177 want: "uint32_t", 178 }, 179 { 180 name: "uint64", 181 typ: reflect.TypeOf(uint64(0)), 182 want: "uint64_t", 183 }, 184 { 185 name: "float32", 186 typ: reflect.TypeOf(float32(0)), 187 want: "float", 188 }, 189 { 190 name: "float64", 191 typ: reflect.TypeOf(float64(0)), 192 want: "double", 193 }, 194 { 195 name: "Float16_t", 196 typ: reflect.TypeOf(root.Float16(0)), 197 want: "Float16_t", 198 }, 199 { 200 name: "Double32_t", 201 typ: reflect.TypeOf(root.Double32(0)), 202 want: "Double32_t", 203 }, 204 { 205 name: "string", 206 typ: reflect.TypeOf(""), 207 want: "string", 208 }, 209 { 210 name: "[2]float32", 211 typ: reflect.TypeOf([2]float32{}), 212 want: "float[2]", 213 }, 214 { 215 name: "[2]string", 216 typ: reflect.TypeOf([2]string{}), 217 want: "string[2]", 218 }, 219 { 220 name: "[2][3]string", 221 typ: reflect.TypeOf([2][3]string{}), 222 want: "string[2][3]", 223 }, 224 { 225 name: "vector<string>", 226 typ: reflect.TypeOf([]string{}), 227 want: "vector<string>", 228 }, 229 { 230 name: "vector<int32_t>", 231 typ: reflect.TypeOf([]int32{}), 232 want: "vector<int32_t>", 233 }, 234 { 235 name: "vector<vector<int32_t> >", 236 typ: reflect.TypeOf([][]int32{}), 237 want: "vector<vector<int32_t> >", 238 }, 239 { 240 name: "vector<vector<vector<int32_t> > >", 241 typ: reflect.TypeOf([][][]int32{}), 242 want: "vector<vector<vector<int32_t> > >", 243 }, 244 { 245 name: "vector<Float16_t>", 246 typ: reflect.TypeOf([]root.Float16{}), 247 want: "vector<Float16_t>", 248 }, 249 { 250 name: "vector<Double32_t>", 251 typ: reflect.TypeOf([]root.Double32{}), 252 want: "vector<Double32_t>", 253 }, 254 { 255 name: "empty-struct", 256 typ: reflect.TypeOf(struct{}{}), 257 panics: "rdict: invalid reflect type struct {}", 258 }, 259 { 260 name: "struct-event", 261 typ: reflect.TypeOf(func() any { 262 type Event struct{} 263 return Event{} 264 }()), 265 want: "Event", 266 }, 267 { 268 name: "TObjString*", 269 typ: reflect.TypeOf((*rbase.ObjString)(nil)), 270 want: "TObjString*", 271 }, 272 { 273 name: "TObjString", 274 typ: reflect.TypeOf((*rbase.ObjString)(nil)).Elem(), 275 want: "TObjString", 276 }, 277 { 278 name: "vector<TObjString>", 279 typ: reflect.TypeOf([]rbase.ObjString{}), 280 want: "vector<TObjString>", 281 }, 282 { 283 name: "vector<TObjString*>", 284 typ: reflect.TypeOf([]*rbase.ObjString{}), 285 want: "vector<TObjString*>", 286 }, 287 { 288 name: "struct0*", 289 typ: reflect.TypeOf((*struct0)(nil)), 290 want: "struct0*", 291 }, 292 { 293 name: "struct0", 294 typ: reflect.TypeOf((*struct0)(nil)).Elem(), 295 want: "struct0", 296 }, 297 { 298 name: "vector<struct0>", 299 typ: reflect.TypeOf([]struct0{}), 300 want: "vector<struct0>", 301 }, 302 { 303 name: "vector<struct0*>", 304 typ: reflect.TypeOf([]*struct0{}), 305 want: "vector<struct0*>", 306 }, 307 { 308 name: "tobject", 309 typ: reflect.TypeOf(tobject{}), 310 want: "tobject", 311 }, 312 { 313 name: "*tobject", 314 typ: reflect.TypeOf(&tobject{}), 315 want: "tobject*", 316 }, 317 } { 318 t.Run(tc.name, func(t *testing.T) { 319 if tc.panics != "" { 320 defer func() { 321 err := recover() 322 if err == nil { 323 t.Fatalf("expected a panic (%q)", tc.panics) 324 } 325 if got, want := err.(error).Error(), tc.panics; got != want { 326 t.Fatalf("invalid panic message:\ngot= %q\nwant=%q", 327 got, want, 328 ) 329 } 330 }() 331 } 332 333 got := typenameOf(tc.typ) 334 if got, want := got, tc.want; got != want { 335 t.Fatalf("invalid typename:\ngot= %q\nwant=%q", got, want) 336 } 337 }) 338 } 339 } 340 341 func TestStreamerOf(t *testing.T) { 342 for _, tc := range []struct { 343 typ reflect.Type 344 want rbytes.StreamerInfo 345 panics string 346 }{ 347 { 348 typ: reflect.TypeOf(&rbase.ObjString{}), 349 want: func() rbytes.StreamerInfo { 350 si, ok := StreamerInfos.Get("TObjString", -1) 351 if !ok { 352 t.Fatalf("could not get streamer for TObjString") 353 } 354 return si 355 }(), 356 }, 357 { 358 typ: reflect.TypeOf((*struct0)(nil)).Elem(), 359 want: &StreamerInfo{ 360 named: *rbase.NewNamed("struct0", "struct0"), 361 clsver: 1, 362 objarr: rcont.NewObjArray(), 363 elems: []rbytes.StreamerElement{ 364 &StreamerObjectPointer{ 365 StreamerElement: StreamerElement{ 366 named: *rbase.NewNamed("ObjPtr", ""), 367 etype: rmeta.ObjectP, 368 esize: diskPtrSize, 369 offset: 0, 370 ename: "TObjString*", 371 }, 372 }, 373 &StreamerObjectAnyPointer{ 374 StreamerElement: StreamerElement{ 375 named: *rbase.NewNamed("UsrPtr", ""), 376 etype: rmeta.AnyP, 377 esize: diskPtrSize, 378 offset: 0, 379 ename: "struct1*", 380 }, 381 }, 382 }, 383 }, 384 }, 385 { 386 typ: reflect.TypeOf((*struct1)(nil)).Elem(), 387 want: &StreamerInfo{ 388 named: *rbase.NewNamed("struct1", "struct1"), 389 clsver: 1, 390 objarr: rcont.NewObjArray(), 391 elems: []rbytes.StreamerElement{ 392 &StreamerSTLstring{ 393 StreamerSTL: StreamerSTL{ 394 StreamerElement: StreamerElement{ 395 named: *rbase.NewNamed("Name", ""), 396 etype: rmeta.Streamer, 397 esize: sizeOfStdString, 398 offset: 0, 399 ename: "string", 400 }, 401 }, 402 }, 403 &StreamerBasicType{StreamerElement{ 404 named: *rbase.NewNamed("Bool", ""), 405 etype: rmeta.Bool, 406 esize: 1, 407 offset: 0, 408 ename: "bool", 409 }}, 410 &StreamerBasicType{StreamerElement{ 411 named: *rbase.NewNamed("I8", ""), 412 etype: rmeta.Int8, 413 esize: 1, 414 offset: 0, 415 ename: "int8_t", 416 }}, 417 &StreamerBasicType{StreamerElement{ 418 named: *rbase.NewNamed("I16", ""), 419 etype: rmeta.Int16, 420 esize: 2, 421 offset: 0, 422 ename: "int16_t", 423 }}, 424 &StreamerBasicType{StreamerElement{ 425 named: *rbase.NewNamed("I32", ""), 426 etype: rmeta.Int32, 427 esize: 4, 428 offset: 0, 429 ename: "int32_t", 430 }}, 431 &StreamerBasicType{StreamerElement{ 432 named: *rbase.NewNamed("I64", ""), 433 etype: rmeta.Int64, 434 esize: 8, 435 offset: 0, 436 ename: "int64_t", 437 }}, 438 &StreamerBasicType{StreamerElement{ 439 named: *rbase.NewNamed("U8", ""), 440 etype: rmeta.Uint8, 441 esize: 1, 442 offset: 0, 443 ename: "uint8_t", 444 }}, 445 &StreamerBasicType{StreamerElement{ 446 named: *rbase.NewNamed("U16", ""), 447 etype: rmeta.Uint16, 448 esize: 2, 449 offset: 0, 450 ename: "uint16_t", 451 }}, 452 &StreamerBasicType{StreamerElement{ 453 named: *rbase.NewNamed("U32", ""), 454 etype: rmeta.Uint32, 455 esize: 4, 456 offset: 0, 457 ename: "uint32_t", 458 }}, 459 &StreamerBasicType{StreamerElement{ 460 named: *rbase.NewNamed("U64", ""), 461 etype: rmeta.Uint64, 462 esize: 8, 463 offset: 0, 464 ename: "uint64_t", 465 }}, 466 &StreamerBasicType{StreamerElement{ 467 named: *rbase.NewNamed("F32", ""), 468 etype: rmeta.Float32, 469 esize: 4, 470 offset: 0, 471 ename: "float", 472 }}, 473 &StreamerBasicType{StreamerElement{ 474 named: *rbase.NewNamed("F64", ""), 475 etype: rmeta.Float64, 476 esize: 8, 477 offset: 0, 478 ename: "double", 479 }}, 480 &StreamerBasicType{StreamerElement{ 481 named: *rbase.NewNamed("F16", ""), 482 etype: rmeta.Float16, 483 esize: 4, 484 offset: 0, 485 ename: "Float16_t", 486 }}, 487 &StreamerBasicType{StreamerElement{ 488 named: *rbase.NewNamed("D32", ""), 489 etype: rmeta.Double32, 490 esize: 8, 491 offset: 0, 492 ename: "Double32_t", 493 }}, 494 &StreamerBasicType{StreamerElement{ 495 named: *rbase.NewNamed("Cxx::MyFloat64", ""), 496 etype: rmeta.Float64, 497 esize: 8, 498 offset: 0, 499 ename: "double", 500 }}, 501 }, 502 }, 503 }, 504 { 505 typ: reflect.TypeOf((*struct2)(nil)).Elem(), 506 want: &StreamerInfo{ 507 named: *rbase.NewNamed("struct2", "struct2"), 508 clsver: 1, 509 objarr: rcont.NewObjArray(), 510 elems: []rbytes.StreamerElement{ 511 &StreamerObjectAny{StreamerElement{ 512 named: *rbase.NewNamed("V1", ""), 513 etype: rmeta.Any, 514 esize: 88, 515 offset: 0, 516 ename: "struct1", 517 }}, 518 }, 519 }, 520 }, 521 { 522 typ: reflect.TypeOf((*struct3)(nil)).Elem(), 523 want: &StreamerInfo{ 524 named: *rbase.NewNamed("struct3", "struct3"), 525 clsver: 1, 526 objarr: rcont.NewObjArray(), 527 elems: []rbytes.StreamerElement{ 528 &StreamerString{StreamerElement{ 529 named: *rbase.NewNamed("Names", ""), 530 etype: rmeta.OffsetL + rmeta.TString, 531 esize: 10 * sizeOfTString, 532 offset: 0, 533 arrlen: 10, 534 arrdim: 1, 535 maxidx: [5]int32{10, 0, 0, 0, 0}, 536 ename: "TString", 537 }}, 538 &StreamerBasicType{StreamerElement{ 539 named: *rbase.NewNamed("Bools", ""), 540 etype: rmeta.OffsetL + rmeta.Bool, 541 esize: 10 * 1, 542 offset: 0, 543 arrlen: 10, 544 arrdim: 1, 545 maxidx: [5]int32{10, 0, 0, 0, 0}, 546 ename: "bool", 547 }}, 548 &StreamerBasicType{StreamerElement{ 549 named: *rbase.NewNamed("I8s", ""), 550 etype: rmeta.OffsetL + rmeta.Int8, 551 esize: 10 * 1, 552 offset: 0, 553 arrlen: 10, 554 arrdim: 1, 555 maxidx: [5]int32{10, 0, 0, 0, 0}, 556 ename: "int8_t", 557 }}, 558 &StreamerBasicType{StreamerElement{ 559 named: *rbase.NewNamed("I16s", ""), 560 etype: rmeta.OffsetL + rmeta.Int16, 561 esize: 10 * 2, 562 offset: 0, 563 arrlen: 10, 564 arrdim: 1, 565 maxidx: [5]int32{10, 0, 0, 0, 0}, 566 ename: "int16_t", 567 }}, 568 &StreamerBasicType{StreamerElement{ 569 named: *rbase.NewNamed("I32s", ""), 570 etype: rmeta.OffsetL + rmeta.Int32, 571 esize: 10 * 4, 572 offset: 0, 573 arrlen: 10, 574 arrdim: 1, 575 maxidx: [5]int32{10, 0, 0, 0, 0}, 576 ename: "int32_t", 577 }}, 578 &StreamerBasicType{StreamerElement{ 579 named: *rbase.NewNamed("I64s", ""), 580 etype: rmeta.OffsetL + rmeta.Int64, 581 esize: 10 * 8, 582 offset: 0, 583 arrlen: 10, 584 arrdim: 1, 585 maxidx: [5]int32{10, 0, 0, 0, 0}, 586 ename: "int64_t", 587 }}, 588 &StreamerBasicType{StreamerElement{ 589 named: *rbase.NewNamed("U8s", ""), 590 etype: rmeta.OffsetL + rmeta.Uint8, 591 esize: 10 * 1, 592 offset: 0, 593 arrlen: 10, 594 arrdim: 1, 595 maxidx: [5]int32{10, 0, 0, 0, 0}, 596 ename: "uint8_t", 597 }}, 598 &StreamerBasicType{StreamerElement{ 599 named: *rbase.NewNamed("U16s", ""), 600 etype: rmeta.OffsetL + rmeta.Uint16, 601 esize: 10 * 2, 602 offset: 0, 603 arrlen: 10, 604 arrdim: 1, 605 maxidx: [5]int32{10, 0, 0, 0, 0}, 606 ename: "uint16_t", 607 }}, 608 &StreamerBasicType{StreamerElement{ 609 named: *rbase.NewNamed("U32s", ""), 610 etype: rmeta.OffsetL + rmeta.Uint32, 611 esize: 10 * 4, 612 offset: 0, 613 arrlen: 10, 614 arrdim: 1, 615 maxidx: [5]int32{10, 0, 0, 0, 0}, 616 ename: "uint32_t", 617 }}, 618 &StreamerBasicType{StreamerElement{ 619 named: *rbase.NewNamed("U64s", ""), 620 etype: rmeta.OffsetL + rmeta.Uint64, 621 esize: 10 * 8, 622 offset: 0, 623 arrlen: 10, 624 arrdim: 1, 625 maxidx: [5]int32{10, 0, 0, 0, 0}, 626 ename: "uint64_t", 627 }}, 628 &StreamerBasicType{StreamerElement{ 629 named: *rbase.NewNamed("F32s", ""), 630 etype: rmeta.OffsetL + rmeta.Float32, 631 esize: 10 * 4, 632 offset: 0, 633 arrlen: 10, 634 arrdim: 1, 635 maxidx: [5]int32{10, 0, 0, 0, 0}, 636 ename: "float", 637 }}, 638 &StreamerBasicType{StreamerElement{ 639 named: *rbase.NewNamed("F64s", ""), 640 etype: rmeta.OffsetL + rmeta.Float64, 641 esize: 10 * 8, 642 offset: 0, 643 arrlen: 10, 644 arrdim: 1, 645 maxidx: [5]int32{10, 0, 0, 0, 0}, 646 ename: "double", 647 }}, 648 &StreamerBasicType{StreamerElement{ 649 named: *rbase.NewNamed("F16s", ""), 650 etype: rmeta.OffsetL + rmeta.Float16, 651 esize: 10 * 4, 652 offset: 0, 653 arrlen: 10, 654 arrdim: 1, 655 maxidx: [5]int32{10, 0, 0, 0, 0}, 656 ename: "Float16_t", 657 }}, 658 &StreamerBasicType{StreamerElement{ 659 named: *rbase.NewNamed("D32s", ""), 660 etype: rmeta.OffsetL + rmeta.Double32, 661 esize: 10 * 8, 662 offset: 0, 663 arrlen: 10, 664 arrdim: 1, 665 maxidx: [5]int32{10, 0, 0, 0, 0}, 666 ename: "Double32_t", 667 }}, 668 &StreamerObjectAny{StreamerElement{ 669 named: *rbase.NewNamed("S1s", ""), 670 etype: rmeta.OffsetL + rmeta.Any, 671 esize: 10 * 88, 672 offset: 0, 673 arrlen: 10, 674 arrdim: 1, 675 maxidx: [5]int32{10, 0, 0, 0, 0}, 676 ename: "struct1", 677 }}, 678 &StreamerObject{StreamerElement{ 679 named: *rbase.NewNamed("ObjStrs", ""), 680 etype: rmeta.OffsetL + rmeta.Object, 681 esize: 10 * sizeOfTObjString, 682 offset: 0, 683 arrlen: 10, 684 arrdim: 1, 685 maxidx: [5]int32{10, 0, 0, 0, 0}, 686 ename: "TObjString", 687 }}, 688 }, 689 }, 690 }, 691 { 692 typ: reflect.TypeOf((*struct4)(nil)).Elem(), 693 want: &StreamerInfo{ 694 named: *rbase.NewNamed("struct4", "struct4"), 695 clsver: 1, 696 objarr: rcont.NewObjArray(), 697 elems: []rbytes.StreamerElement{ 698 NewCxxStreamerSTL(StreamerElement{ 699 named: *rbase.NewNamed("Names", ""), 700 etype: rmeta.Streamer, 701 esize: 3 * int32(ptrSize), 702 offset: 0, 703 ename: "vector<string>", 704 }, rmeta.STLvector, rmeta.STLstring), 705 NewCxxStreamerSTL(StreamerElement{ 706 named: *rbase.NewNamed("Bools", ""), 707 etype: rmeta.Streamer, 708 esize: 3 * int32(ptrSize), 709 offset: 0, 710 ename: "vector<bool>", 711 }, rmeta.STLvector, rmeta.Bool), 712 NewCxxStreamerSTL(StreamerElement{ 713 named: *rbase.NewNamed("I8s", ""), 714 etype: rmeta.Streamer, 715 esize: 3 * int32(ptrSize), 716 offset: 0, 717 ename: "vector<int8_t>", 718 }, rmeta.STLvector, rmeta.Int8), 719 NewCxxStreamerSTL(StreamerElement{ 720 named: *rbase.NewNamed("I16s", ""), 721 etype: rmeta.Streamer, 722 esize: 3 * int32(ptrSize), 723 offset: 0, 724 ename: "vector<int16_t>", 725 }, rmeta.STLvector, rmeta.Int16), 726 NewCxxStreamerSTL(StreamerElement{ 727 named: *rbase.NewNamed("I32s", ""), 728 etype: rmeta.Streamer, 729 esize: 3 * int32(ptrSize), 730 offset: 0, 731 ename: "vector<int32_t>", 732 }, rmeta.STLvector, rmeta.Int32), 733 NewCxxStreamerSTL(StreamerElement{ 734 named: *rbase.NewNamed("I64s", ""), 735 etype: rmeta.Streamer, 736 esize: 3 * int32(ptrSize), 737 offset: 0, 738 ename: "vector<int64_t>", 739 }, rmeta.STLvector, rmeta.Int64), 740 NewCxxStreamerSTL(StreamerElement{ 741 named: *rbase.NewNamed("U8s", ""), 742 etype: rmeta.Streamer, 743 esize: 3 * int32(ptrSize), 744 offset: 0, 745 ename: "vector<uint8_t>", 746 }, rmeta.STLvector, rmeta.Uint8), 747 NewCxxStreamerSTL(StreamerElement{ 748 named: *rbase.NewNamed("U16s", ""), 749 etype: rmeta.Streamer, 750 esize: 3 * int32(ptrSize), 751 offset: 0, 752 ename: "vector<uint16_t>", 753 }, rmeta.STLvector, rmeta.Uint16), 754 NewCxxStreamerSTL(StreamerElement{ 755 named: *rbase.NewNamed("U32s", ""), 756 etype: rmeta.Streamer, 757 esize: 3 * int32(ptrSize), 758 offset: 0, 759 ename: "vector<uint32_t>", 760 }, rmeta.STLvector, rmeta.Uint32), 761 NewCxxStreamerSTL(StreamerElement{ 762 named: *rbase.NewNamed("U64s", ""), 763 etype: rmeta.Streamer, 764 esize: 3 * int32(ptrSize), 765 offset: 0, 766 ename: "vector<uint64_t>", 767 }, rmeta.STLvector, rmeta.Uint64), 768 NewCxxStreamerSTL(StreamerElement{ 769 named: *rbase.NewNamed("F32s", ""), 770 etype: rmeta.Streamer, 771 esize: 3 * int32(ptrSize), 772 offset: 0, 773 ename: "vector<float>", 774 }, rmeta.STLvector, rmeta.Float32), 775 NewCxxStreamerSTL(StreamerElement{ 776 named: *rbase.NewNamed("F64s", ""), 777 etype: rmeta.Streamer, 778 esize: 3 * int32(ptrSize), 779 offset: 0, 780 ename: "vector<double>", 781 }, rmeta.STLvector, rmeta.Float64), 782 NewCxxStreamerSTL(StreamerElement{ 783 named: *rbase.NewNamed("F16s", ""), 784 etype: rmeta.Streamer, 785 esize: 3 * int32(ptrSize), 786 offset: 0, 787 ename: "vector<Float16_t>", 788 }, rmeta.STLvector, rmeta.Float16), 789 NewCxxStreamerSTL(StreamerElement{ 790 named: *rbase.NewNamed("D32s", ""), 791 etype: rmeta.Streamer, 792 esize: 3 * int32(ptrSize), 793 offset: 0, 794 ename: "vector<Double32_t>", 795 }, rmeta.STLvector, rmeta.Double32), 796 NewCxxStreamerSTL(StreamerElement{ 797 named: *rbase.NewNamed("S1s", ""), 798 etype: rmeta.Streamer, 799 esize: 3 * int32(ptrSize), 800 offset: 0, 801 ename: "vector<struct1>", 802 }, rmeta.STLvector, rmeta.Any), 803 NewCxxStreamerSTL(StreamerElement{ 804 named: *rbase.NewNamed("ObjStrs", ""), 805 etype: rmeta.Streamer, 806 esize: 3 * int32(ptrSize), 807 offset: 0, 808 ename: "vector<TObjString>", 809 }, rmeta.STLvector, rmeta.Object), 810 }, 811 }, 812 }, 813 { 814 typ: reflect.TypeOf((*struct5)(nil)).Elem(), 815 want: &StreamerInfo{ 816 named: *rbase.NewNamed("struct5", "struct5"), 817 clsver: 1, 818 objarr: rcont.NewObjArray(), 819 elems: []rbytes.StreamerElement{ 820 &StreamerBasicType{ 821 StreamerElement: Element{ 822 Name: *rbase.NewNamed("N", ""), 823 Type: rmeta.Int32, // should be rmeta.Counter 824 Size: 4, 825 EName: "int32_t", 826 }.New(), 827 }, 828 NewStreamerLoop( 829 Element{ 830 Name: *rbase.NewNamed("Names", "[N]"), 831 Size: 4, 832 EName: "TString*", 833 }.New(), 1, "N", "struct5", 834 ), 835 NewStreamerBasicPointer( 836 Element{ 837 Name: *rbase.NewNamed("Bools", "[N]"), 838 Type: rmeta.OffsetP + rmeta.Bool, 839 Size: 1, 840 EName: "bool*", 841 }.New(), 1, "N", "struct5", 842 ), 843 NewStreamerBasicPointer( 844 Element{ 845 Name: *rbase.NewNamed("I8s", "[N]"), 846 Type: rmeta.OffsetP + rmeta.Int8, 847 Size: 1, 848 EName: "int8_t*", 849 }.New(), 1, "N", "struct5", 850 ), 851 NewStreamerBasicPointer( 852 Element{ 853 Name: *rbase.NewNamed("I16s", "[N]"), 854 Type: rmeta.OffsetP + rmeta.Int16, 855 Size: 2, 856 EName: "int16_t*", 857 }.New(), 1, "N", "struct5", 858 ), 859 NewStreamerBasicPointer( 860 Element{ 861 Name: *rbase.NewNamed("I32s", "[N]"), 862 Type: rmeta.OffsetP + rmeta.Int32, 863 Size: 4, 864 EName: "int32_t*", 865 }.New(), 1, "N", "struct5", 866 ), 867 NewStreamerBasicPointer( 868 Element{ 869 Name: *rbase.NewNamed("I64s", "[N]"), 870 Type: rmeta.OffsetP + rmeta.Int64, 871 Size: 8, 872 EName: "int64_t*", 873 }.New(), 1, "N", "struct5", 874 ), 875 NewStreamerBasicPointer( 876 Element{ 877 Name: *rbase.NewNamed("U8s", "[N]"), 878 Type: rmeta.OffsetP + rmeta.Uint8, 879 Size: 1, 880 EName: "uint8_t*", 881 }.New(), 1, "N", "struct5", 882 ), 883 NewStreamerBasicPointer( 884 Element{ 885 Name: *rbase.NewNamed("U16s", "[N]"), 886 Type: rmeta.OffsetP + rmeta.Uint16, 887 Size: 2, 888 EName: "uint16_t*", 889 }.New(), 1, "N", "struct5", 890 ), 891 NewStreamerBasicPointer( 892 Element{ 893 Name: *rbase.NewNamed("U32s", "[N]"), 894 Type: rmeta.OffsetP + rmeta.Uint32, 895 Size: 4, 896 EName: "uint32_t*", 897 }.New(), 1, "N", "struct5", 898 ), 899 NewStreamerBasicPointer( 900 Element{ 901 Name: *rbase.NewNamed("U64s", "[N]"), 902 Type: rmeta.OffsetP + rmeta.Uint64, 903 Size: 8, 904 EName: "uint64_t*", 905 }.New(), 1, "N", "struct5", 906 ), 907 NewStreamerBasicPointer( 908 Element{ 909 Name: *rbase.NewNamed("F32s", "[N]"), 910 Type: rmeta.OffsetP + rmeta.Float32, 911 Size: 4, 912 EName: "float*", 913 }.New(), 1, "N", "struct5", 914 ), 915 NewStreamerBasicPointer( 916 Element{ 917 Name: *rbase.NewNamed("F64s", "[N]"), 918 Type: rmeta.OffsetP + rmeta.Float64, 919 Size: 8, 920 EName: "double*", 921 }.New(), 1, "N", "struct5", 922 ), 923 NewStreamerBasicPointer( 924 Element{ 925 Name: *rbase.NewNamed("F16s", "[N]"), 926 Type: rmeta.OffsetP + rmeta.Float16, 927 Size: 4, 928 EName: "Float16_t*", 929 }.New(), 1, "N", "struct5", 930 ), 931 NewStreamerBasicPointer( 932 Element{ 933 Name: *rbase.NewNamed("D32s", "[N]"), 934 Type: rmeta.OffsetP + rmeta.Double32, 935 Size: 8, 936 EName: "Double32_t*", 937 }.New(), 1, "N", "struct5", 938 ), 939 NewStreamerLoop( 940 Element{ 941 Name: *rbase.NewNamed("S1s", "[N]"), 942 Size: 8, 943 EName: "struct1*", 944 }.New(), 1, "N", "struct5", 945 ), 946 NewStreamerLoop( 947 Element{ 948 Name: *rbase.NewNamed("ObjStrs", "[N]"), 949 Size: 8, 950 EName: "TObjString*", 951 }.New(), 1, "N", "struct5", 952 ), 953 }, 954 }, 955 }, 956 { 957 typ: reflect.TypeOf((*struct6)(nil)).Elem(), 958 want: &StreamerInfo{ 959 named: *rbase.NewNamed("struct6", "struct6"), 960 clsver: 1, 961 objarr: rcont.NewObjArray(), 962 elems: []rbytes.StreamerElement{ 963 NewCxxStreamerSTL(StreamerElement{ 964 named: *rbase.NewNamed("Names", ""), 965 etype: rmeta.Streamer, 966 esize: 3 * int32(ptrSize), 967 offset: 0, 968 ename: "vector<vector<string> >", 969 }, rmeta.STLvector, rmeta.Any), 970 NewCxxStreamerSTL(StreamerElement{ 971 named: *rbase.NewNamed("Bools", ""), 972 etype: rmeta.Streamer, 973 esize: 3 * int32(ptrSize), 974 offset: 0, 975 ename: "vector<vector<bool> >", 976 }, rmeta.STLvector, rmeta.Any), 977 NewCxxStreamerSTL(StreamerElement{ 978 named: *rbase.NewNamed("I8s", ""), 979 etype: rmeta.Streamer, 980 esize: 3 * int32(ptrSize), 981 offset: 0, 982 ename: "vector<vector<int8_t> >", 983 }, rmeta.STLvector, rmeta.Any), 984 NewCxxStreamerSTL(StreamerElement{ 985 named: *rbase.NewNamed("I16s", ""), 986 etype: rmeta.Streamer, 987 esize: 3 * int32(ptrSize), 988 offset: 0, 989 ename: "vector<vector<int16_t> >", 990 }, rmeta.STLvector, rmeta.Any), 991 NewCxxStreamerSTL(StreamerElement{ 992 named: *rbase.NewNamed("I32s", ""), 993 etype: rmeta.Streamer, 994 esize: 3 * int32(ptrSize), 995 offset: 0, 996 ename: "vector<vector<int32_t> >", 997 }, rmeta.STLvector, rmeta.Any), 998 NewCxxStreamerSTL(StreamerElement{ 999 named: *rbase.NewNamed("I64s", ""), 1000 etype: rmeta.Streamer, 1001 esize: 3 * int32(ptrSize), 1002 offset: 0, 1003 ename: "vector<vector<int64_t> >", 1004 }, rmeta.STLvector, rmeta.Any), 1005 NewCxxStreamerSTL(StreamerElement{ 1006 named: *rbase.NewNamed("U8s", ""), 1007 etype: rmeta.Streamer, 1008 esize: 3 * int32(ptrSize), 1009 offset: 0, 1010 ename: "vector<vector<uint8_t> >", 1011 }, rmeta.STLvector, rmeta.Any), 1012 NewCxxStreamerSTL(StreamerElement{ 1013 named: *rbase.NewNamed("U16s", ""), 1014 etype: rmeta.Streamer, 1015 esize: 3 * int32(ptrSize), 1016 offset: 0, 1017 ename: "vector<vector<uint16_t> >", 1018 }, rmeta.STLvector, rmeta.Any), 1019 NewCxxStreamerSTL(StreamerElement{ 1020 named: *rbase.NewNamed("U32s", ""), 1021 etype: rmeta.Streamer, 1022 esize: 3 * int32(ptrSize), 1023 offset: 0, 1024 ename: "vector<vector<uint32_t> >", 1025 }, rmeta.STLvector, rmeta.Any), 1026 NewCxxStreamerSTL(StreamerElement{ 1027 named: *rbase.NewNamed("U64s", ""), 1028 etype: rmeta.Streamer, 1029 esize: 3 * int32(ptrSize), 1030 offset: 0, 1031 ename: "vector<vector<uint64_t> >", 1032 }, rmeta.STLvector, rmeta.Any), 1033 NewCxxStreamerSTL(StreamerElement{ 1034 named: *rbase.NewNamed("F32s", ""), 1035 etype: rmeta.Streamer, 1036 esize: 3 * int32(ptrSize), 1037 offset: 0, 1038 ename: "vector<vector<float> >", 1039 }, rmeta.STLvector, rmeta.Any), 1040 NewCxxStreamerSTL(StreamerElement{ 1041 named: *rbase.NewNamed("F64s", ""), 1042 etype: rmeta.Streamer, 1043 esize: 3 * int32(ptrSize), 1044 offset: 0, 1045 ename: "vector<vector<double> >", 1046 }, rmeta.STLvector, rmeta.Any), 1047 NewCxxStreamerSTL(StreamerElement{ 1048 named: *rbase.NewNamed("F16s", ""), 1049 etype: rmeta.Streamer, 1050 esize: 3 * int32(ptrSize), 1051 offset: 0, 1052 ename: "vector<vector<Float16_t> >", 1053 }, rmeta.STLvector, rmeta.Any), 1054 NewCxxStreamerSTL(StreamerElement{ 1055 named: *rbase.NewNamed("D32s", ""), 1056 etype: rmeta.Streamer, 1057 esize: 3 * int32(ptrSize), 1058 offset: 0, 1059 ename: "vector<vector<Double32_t> >", 1060 }, rmeta.STLvector, rmeta.Any), 1061 NewCxxStreamerSTL(StreamerElement{ 1062 named: *rbase.NewNamed("S1s", ""), 1063 etype: rmeta.Streamer, 1064 esize: 3 * int32(ptrSize), 1065 offset: 0, 1066 ename: "vector<vector<struct1> >", 1067 }, rmeta.STLvector, rmeta.Any), 1068 }, 1069 }, 1070 }, 1071 { 1072 typ: reflect.TypeOf((*struct7)(nil)).Elem(), 1073 want: &StreamerInfo{ 1074 named: *rbase.NewNamed("struct7", "struct7"), 1075 clsver: 1, 1076 objarr: rcont.NewObjArray(), 1077 elems: []rbytes.StreamerElement{ 1078 &StreamerBasicType{StreamerElement{ 1079 named: *rbase.NewNamed("ArrI32", ""), 1080 etype: rmeta.OffsetL + rmeta.Int32, 1081 esize: 1 * 2 * 3 * 4 * 5 * 4, 1082 offset: 0, 1083 arrlen: 1, 1084 arrdim: 5, 1085 maxidx: [5]int32{1, 2, 3, 4, 5}, 1086 ename: "int32_t", 1087 }}, 1088 &StreamerString{StreamerElement{ 1089 named: *rbase.NewNamed("ArrStr", ""), 1090 etype: rmeta.OffsetL + rmeta.TString, 1091 esize: 1 * 2 * 3 * 4 * 5 * sizeOfTString, 1092 offset: 0, 1093 arrlen: 1, 1094 arrdim: 5, 1095 maxidx: [5]int32{1, 2, 3, 4, 5}, 1096 ename: "TString", 1097 }}, 1098 &StreamerObject{StreamerElement{ 1099 named: *rbase.NewNamed("ArrObj", ""), 1100 etype: rmeta.OffsetL + rmeta.Object, 1101 esize: 1 * 2 * 3 * 4 * 5 * 40, 1102 offset: 0, 1103 arrlen: 1, 1104 arrdim: 5, 1105 maxidx: [5]int32{1, 2, 3, 4, 5}, 1106 ename: "TObjString", 1107 }}, 1108 &StreamerObjectAny{StreamerElement{ 1109 named: *rbase.NewNamed("ArrUsr", ""), 1110 etype: rmeta.OffsetL + rmeta.Any, 1111 esize: 1 * 2 * 3 * 4 * 5 * 88, 1112 offset: 0, 1113 arrlen: 1, 1114 arrdim: 5, 1115 maxidx: [5]int32{1, 2, 3, 4, 5}, 1116 ename: "struct1", 1117 }}, 1118 }, 1119 }, 1120 }, 1121 { 1122 // FIXME(sbinet): add support for maps. 1123 typ: reflect.TypeOf(panicFIXMEStruct0{}), 1124 want: &StreamerInfo{ 1125 named: *rbase.NewNamed("panicFIXMEStruct0", "panicFIXMEStruct0"), 1126 clsver: 1, 1127 }, 1128 panics: `rdict: invalid struct field (name=Map, type=map[int32]int32, kind=map)`, 1129 }, 1130 { 1131 // FIXME(sbinet): add support for interfaces? 1132 typ: reflect.TypeOf(panicFIXMEStruct1{}), 1133 want: &StreamerInfo{ 1134 named: *rbase.NewNamed("panicFIXMEStruct1", "panicFIXMEStruct1"), 1135 clsver: 1, 1136 }, 1137 panics: `rdict: invalid struct field (name=Iface, type=error, kind=interface)`, 1138 }, 1139 { 1140 // FIXME(sbinet): add support for complex-64 1141 typ: reflect.TypeOf(panicFIXMEStruct2{}), 1142 want: &StreamerInfo{ 1143 named: *rbase.NewNamed("panicFIXMEStruct2", "panicFIXMEStruct2"), 1144 clsver: 1, 1145 }, 1146 panics: `rdict: invalid struct field (name=C64, type=complex64, kind=complex64)`, 1147 }, 1148 { 1149 // FIXME(sbinet): add support for complex-128 1150 typ: reflect.TypeOf(panicFIXMEStruct3{}), 1151 want: &StreamerInfo{ 1152 named: *rbase.NewNamed("panicFIXMEStruct3", "panicFIXMEStruct3"), 1153 clsver: 1, 1154 }, 1155 panics: `rdict: invalid struct field (name=C128, type=complex128, kind=complex128)`, 1156 }, 1157 { 1158 typ: reflect.TypeOf(panicStruct0{}), 1159 want: &StreamerInfo{ 1160 named: *rbase.NewNamed("panicStruct0", "panicStruct0"), 1161 clsver: 1, 1162 }, 1163 panics: `rdict: invalid struct field (name=Chan, type=chan int32, kind=chan)`, 1164 }, 1165 { 1166 typ: reflect.TypeOf(panicStruct1{}), 1167 want: &StreamerInfo{ 1168 named: *rbase.NewNamed("panicStruct1", "panicStruct1"), 1169 clsver: 1, 1170 }, 1171 panics: `rdict: invalid struct field (name=Int, type=int, kind=int)`, 1172 }, 1173 { 1174 typ: reflect.TypeOf(panicStruct2{}), 1175 want: &StreamerInfo{ 1176 named: *rbase.NewNamed("panicStruct2", "panicStruct2"), 1177 clsver: 1, 1178 }, 1179 panics: `rdict: invalid struct field (name=Uint, type=uint, kind=uint)`, 1180 }, 1181 { 1182 typ: reflect.TypeOf(panicStruct3{}), 1183 want: &StreamerInfo{ 1184 named: *rbase.NewNamed("panicStruct3", "panicStruct3"), 1185 clsver: 1, 1186 }, 1187 panics: `rdict: invalid struct field (name=Uintptr, type=uintptr, kind=uintptr)`, 1188 }, 1189 { 1190 typ: reflect.TypeOf(panicStruct4{}), 1191 want: &StreamerInfo{ 1192 named: *rbase.NewNamed("panicStruct4", "panicStruct4"), 1193 clsver: 1, 1194 }, 1195 panics: `rdict: invalid struct field (name=Unsafe, type=unsafe.Pointer, kind=unsafe.Pointer)`, 1196 }, 1197 { 1198 typ: reflect.TypeOf(panicStruct5{}), 1199 want: &StreamerInfo{ 1200 named: *rbase.NewNamed("panicStruct5", "panicStruct5"), 1201 clsver: 1, 1202 }, 1203 panics: `rdict: invalid struct field (name=Func, type=func(), kind=func)`, 1204 }, 1205 } { 1206 t.Run(tc.want.Name(), func(t *testing.T) { 1207 if tc.panics != "" { 1208 defer func() { 1209 err := recover() 1210 if err == nil { 1211 t.Fatalf("expected a panic (%s)", tc.panics) 1212 } 1213 if got, want := err.(error).Error(), tc.panics; got != want { 1214 t.Fatalf( 1215 "invalid panic message:\ngot= %s\nwant=%s", 1216 got, want, 1217 ) 1218 } 1219 }() 1220 } 1221 1222 ctx := newStreamerStore(StreamerInfos) 1223 got := StreamerOf(ctx, tc.typ) 1224 if !reflect.DeepEqual(got, tc.want) { 1225 egot := got.Elements() 1226 ewat := tc.want.Elements() 1227 for i := range egot { 1228 if !reflect.DeepEqual(egot[i], ewat[i]) { 1229 t.Logf("i=%d\ngot= %#v\nwant=%#v", i, egot[i], ewat[i]) 1230 } 1231 } 1232 t.Fatalf("invalid streamer info.\ngot:\n%v\nwant:\n%v", got, tc.want) 1233 } 1234 }) 1235 } 1236 } 1237 1238 type struct0 struct { 1239 TObjPtr *rbase.ObjString `groot:"ObjPtr"` 1240 TUsrPtr *struct1 `groot:"UsrPtr"` 1241 } 1242 1243 type struct1 struct { 1244 Name string 1245 Bool bool 1246 I8 int8 1247 I16 int16 1248 I32 int32 1249 I64 int64 1250 U8 uint8 1251 U16 uint16 1252 U32 uint32 1253 U64 uint64 1254 F32 float32 1255 F64 float64 1256 F16 root.Float16 1257 D32 root.Double32 1258 Float64 float64 `groot:"Cxx::MyFloat64"` 1259 } 1260 1261 type struct2 struct { 1262 V1 struct1 1263 } 1264 1265 type struct3 struct { 1266 Names [10]string 1267 Bools [10]bool 1268 I8s [10]int8 1269 I16s [10]int16 1270 I32s [10]int32 1271 I64s [10]int64 1272 U8s [10]uint8 1273 U16s [10]uint16 1274 U32s [10]uint32 1275 U64s [10]uint64 1276 F32s [10]float32 1277 F64s [10]float64 1278 F16s [10]root.Float16 1279 D32s [10]root.Double32 1280 S1s [10]struct1 1281 ObjStrs [10]rbase.ObjString 1282 } 1283 1284 type struct4 struct { 1285 Names []string 1286 Bools []bool 1287 I8s []int8 1288 I16s []int16 1289 I32s []int32 1290 I64s []int64 1291 U8s []uint8 1292 U16s []uint16 1293 U32s []uint32 1294 U64s []uint64 1295 F32s []float32 1296 F64s []float64 1297 F16s []root.Float16 1298 D32s []root.Double32 1299 S1s []struct1 1300 ObjStrs []rbase.ObjString 1301 } 1302 1303 type struct5 struct { 1304 N int32 1305 Names []string `groot:"Names[N]"` 1306 Bools []bool `groot:"Bools[N]"` 1307 I8s []int8 `groot:"I8s[N]"` 1308 I16s []int16 `groot:"I16s[N]"` 1309 I32s []int32 `groot:"I32s[N]"` 1310 I64s []int64 `groot:"I64s[N]"` 1311 U8s []uint8 `groot:"U8s[N]"` 1312 U16s []uint16 `groot:"U16s[N]"` 1313 U32s []uint32 `groot:"U32s[N]"` 1314 U64s []uint64 `groot:"U64s[N]"` 1315 F32s []float32 `groot:"F32s[N]"` 1316 F64s []float64 `groot:"F64s[N]"` 1317 F16s []root.Float16 `groot:"F16s[N]"` 1318 D32s []root.Double32 `groot:"D32s[N]"` 1319 S1s []struct1 `groot:"S1s[N]"` 1320 ObjStrs []rbase.ObjString `groot:"ObjStrs[N]"` 1321 } 1322 1323 type struct6 struct { 1324 Names [][]string 1325 Bools [][]bool 1326 I8s [][]int8 1327 I16s [][]int16 1328 I32s [][]int32 1329 I64s [][]int64 1330 U8s [][]uint8 1331 U16s [][]uint16 1332 U32s [][]uint32 1333 U64s [][]uint64 1334 F32s [][]float32 1335 F64s [][]float64 1336 F16s [][]root.Float16 1337 D32s [][]root.Double32 1338 S1s [][]struct1 1339 } 1340 1341 type struct7 struct { 1342 ArrI32 [1][2][3][4][5]int32 `groot:"ArrI32[1][2][3][4][5]"` 1343 ArrStr [1][2][3][4][5]string `groot:"ArrStr[1][2][3][4][5]"` 1344 ArrObj [1][2][3][4][5]rbase.ObjString `groot:"ArrObj[1][2][3][4][5]"` 1345 ArrUsr [1][2][3][4][5]struct1 `groot:"ArrUsr[1][2][3][4][5]"` 1346 } 1347 1348 type panicFIXMEStruct0 struct { 1349 Map map[int32]int32 `groot:"Map"` 1350 } 1351 1352 type panicFIXMEStruct1 struct { 1353 Iface error 1354 } 1355 1356 type panicFIXMEStruct2 struct { 1357 C64 complex64 1358 } 1359 1360 type panicFIXMEStruct3 struct { 1361 C128 complex128 1362 } 1363 1364 type panicStruct0 struct { 1365 Chan chan int32 1366 } 1367 1368 type panicStruct1 struct { 1369 Int int 1370 } 1371 1372 type panicStruct2 struct { 1373 Uint uint 1374 } 1375 1376 type panicStruct3 struct { 1377 Uintptr uintptr 1378 } 1379 1380 type panicStruct4 struct { 1381 Unsafe unsafe.Pointer 1382 } 1383 1384 type panicStruct5 struct { 1385 Func func() 1386 } 1387 1388 type tobject struct{} 1389 1390 func (tobject) Class() string { return "tobject" } 1391 1392 var ( 1393 _ root.Object = (*tobject)(nil) 1394 )