go-hep.org/x/hep@v0.38.1/groot/rtree/reader_test.go (about) 1 // Copyright ©2020 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 rtree 6 7 import ( 8 "fmt" 9 "io" 10 "path/filepath" 11 "reflect" 12 "testing" 13 14 "go-hep.org/x/hep/groot/internal/rtests" 15 "go-hep.org/x/hep/groot/riofs" 16 _ "go-hep.org/x/hep/groot/riofs/plugin/xrootd" 17 "go-hep.org/x/hep/groot/root" 18 ) 19 20 func TestReader(t *testing.T) { 21 f, err := riofs.Open("../testdata/simple.root") 22 if err != nil { 23 t.Fatalf("could not open ROOT file: %+v", err) 24 } 25 defer f.Close() 26 27 o, err := f.Get("tree") 28 if err != nil { 29 t.Fatalf("could not retrieve ROOT tree: %+v", err) 30 } 31 tree := o.(Tree) 32 33 for _, tc := range []struct { 34 name string 35 rvars []ReadVar 36 ropts []ReadOption 37 beg int64 38 end int64 39 fun func(RCtx) error 40 enew error 41 eloop error 42 }{ 43 { 44 name: "ok", 45 beg: 0, end: -1, 46 fun: func(RCtx) error { return nil }, 47 }, 48 { 49 name: "empty-range", 50 beg: 4, end: -1, 51 fun: func(RCtx) error { return nil }, 52 }, 53 { 54 name: "invalid-rvar", 55 rvars: []ReadVar{{Name: "not-there", Value: new(int16)}}, 56 beg: 0, end: -1, 57 fun: func(RCtx) error { return nil }, 58 enew: fmt.Errorf(`rtree: could not create reader: rtree: tree "tree" has no branch named "not-there"`), 59 }, 60 { 61 name: "invalid-ropt", 62 ropts: []ReadOption{func(r *Reader) error { return io.EOF }}, 63 beg: 0, end: -1, 64 fun: func(RCtx) error { return nil }, 65 enew: fmt.Errorf(`rtree: could not set reader option 1: EOF`), 66 }, 67 { 68 name: "negative-start", 69 beg: -1, end: -1, 70 fun: func(RCtx) error { return nil }, 71 enew: fmt.Errorf("rtree: invalid event reader range [-1, 4) (start=-1 < 0)"), 72 }, 73 { 74 name: "start-greater-than-end", 75 beg: 2, end: 1, 76 fun: func(RCtx) error { return nil }, 77 enew: fmt.Errorf("rtree: invalid event reader range [2, 1) (start=2 > end=1)"), 78 }, 79 { 80 name: "start-greater-than-nentries", 81 beg: 5, end: 10, 82 fun: func(RCtx) error { return nil }, 83 enew: fmt.Errorf("rtree: invalid event reader range [5, 10) (start=5 > tree-entries=4)"), 84 }, 85 { 86 name: "end-greater-than-nentries", 87 beg: 0, end: 5, 88 fun: func(RCtx) error { return nil }, 89 enew: fmt.Errorf("rtree: invalid event reader range [0, 5) (end=5 > tree-entries=4)"), 90 }, 91 { 92 name: "process-error", 93 beg: 0, end: 4, 94 fun: func(ctx RCtx) error { 95 if ctx.Entry == 2 { 96 return io.EOF 97 } 98 return nil 99 }, 100 eloop: fmt.Errorf("rtree: could not process entry 2: EOF"), 101 }, 102 } { 103 t.Run(tc.name, func(t *testing.T) { 104 var ( 105 v1 int32 106 v2 float32 107 v3 string 108 109 rvars = []ReadVar{ 110 {Name: "one", Value: &v1}, 111 {Name: "two", Value: &v2}, 112 {Name: "three", Value: &v3}, 113 } 114 ) 115 116 if tc.rvars != nil { 117 rvars = tc.rvars 118 } 119 120 ropts := []ReadOption{WithRange(tc.beg, tc.end)} 121 if tc.ropts != nil { 122 ropts = append(ropts, tc.ropts...) 123 } 124 125 r, err := NewReader(tree, rvars, ropts...) 126 switch { 127 case err != nil && tc.enew != nil: 128 if got, want := err.Error(), tc.enew.Error(); got != want { 129 t.Fatalf("invalid error:\ngot= %v\nwant=%v", got, want) 130 } 131 return 132 case err != nil && tc.enew == nil: 133 t.Fatalf("unexpected error: %v", err) 134 case err == nil && tc.enew != nil: 135 t.Fatalf("expected an error: got=%v, want=%v", err, tc.enew) 136 case err == nil && tc.enew == nil: 137 // ok. 138 } 139 defer r.Close() 140 141 err = r.Read(tc.fun) 142 143 switch { 144 case err != nil && tc.eloop != nil: 145 if got, want := err.Error(), tc.eloop.Error(); got != want { 146 t.Fatalf("invalid error:\ngot= %v\nwant=%v", got, want) 147 } 148 case err != nil && tc.eloop == nil: 149 t.Fatalf("unexpected error: %v", err) 150 case err == nil && tc.eloop != nil: 151 t.Fatalf("expected an error: got=%v, want=%v", err, tc.eloop) 152 case err == nil && tc.eloop == nil: 153 // ok. 154 } 155 156 err = r.Close() 157 if err != nil { 158 t.Fatalf("could not close tree reader: %+v", err) 159 } 160 161 // check r.Close is idem-potent. 162 err = r.Close() 163 if err != nil { 164 t.Fatalf("tree reader close not idem-potent: %+v", err) 165 } 166 }) 167 } 168 } 169 170 type ScannerData struct { 171 B bool `groot:"B"` 172 Str string `groot:"Str"` 173 I8 int8 `groot:"I8"` 174 I16 int16 `groot:"I16"` 175 I32 int32 `groot:"I32"` 176 I64 int64 `groot:"I64"` 177 U8 uint8 `groot:"U8"` 178 U16 uint16 `groot:"U16"` 179 U32 uint32 `groot:"U32"` 180 U64 uint64 `groot:"U64"` 181 F32 float32 `groot:"F32"` 182 F64 float64 `groot:"F64"` 183 D16 root.Float16 `groot:"D16"` 184 D32 root.Double32 `groot:"D32"` 185 ArrBs [10]bool `groot:"ArrBs[10]"` 186 ArrI8 [10]int8 `groot:"ArrI8[10]"` 187 ArrI16 [10]int16 `groot:"ArrI16[10]"` 188 ArrI32 [10]int32 `groot:"ArrI32[10]"` 189 ArrI64 [10]int64 `groot:"ArrI64[10]"` 190 ArrU8 [10]uint8 `groot:"ArrU8[10]"` 191 ArrU16 [10]uint16 `groot:"ArrU16[10]"` 192 ArrU32 [10]uint32 `groot:"ArrU32[10]"` 193 ArrU64 [10]uint64 `groot:"ArrU64[10]"` 194 ArrF32 [10]float32 `groot:"ArrF32[10]"` 195 ArrF64 [10]float64 `groot:"ArrF64[10]"` 196 ArrD16 [10]root.Float16 `groot:"ArrD16[10]"` 197 ArrD32 [10]root.Double32 `groot:"ArrD32[10]"` 198 N int32 `groot:"N"` 199 SliBs []bool `groot:"SliBs[N]"` 200 SliI8 []int8 `groot:"SliI8[N]"` 201 SliI16 []int16 `groot:"SliI16[N]"` 202 SliI32 []int32 `groot:"SliI32[N]"` 203 SliI64 []int64 `groot:"SliI64[N]"` 204 SliU8 []uint8 `groot:"SliU8[N]"` 205 SliU16 []uint16 `groot:"SliU16[N]"` 206 SliU32 []uint32 `groot:"SliU32[N]"` 207 SliU64 []uint64 `groot:"SliU64[N]"` 208 SliF32 []float32 `groot:"SliF32[N]"` 209 SliF64 []float64 `groot:"SliF64[N]"` 210 SliD16 []root.Float16 `groot:"SliD16[N]"` 211 SliD32 []root.Double32 `groot:"SliD32[N]"` 212 } 213 214 func (ScannerData) want(i int64) (data ScannerData) { 215 data.B = i%2 == 0 216 data.Str = fmt.Sprintf("str-%d", i) 217 data.I8 = int8(-i) 218 data.I16 = int16(-i) 219 data.I32 = int32(-i) 220 data.I64 = int64(-i) 221 data.U8 = uint8(i) 222 data.U16 = uint16(i) 223 data.U32 = uint32(i) 224 data.U64 = uint64(i) 225 data.F32 = float32(i) 226 data.F64 = float64(i) 227 data.D16 = root.Float16(i) 228 data.D32 = root.Double32(i) 229 for ii := range data.ArrI32 { 230 data.ArrBs[ii] = ii == int(i) 231 data.ArrI8[ii] = int8(-i) 232 data.ArrI16[ii] = int16(-i) 233 data.ArrI32[ii] = int32(-i) 234 data.ArrI64[ii] = int64(-i) 235 data.ArrU8[ii] = uint8(i) 236 data.ArrU16[ii] = uint16(i) 237 data.ArrU32[ii] = uint32(i) 238 data.ArrU64[ii] = uint64(i) 239 data.ArrF32[ii] = float32(i) 240 data.ArrF64[ii] = float64(i) 241 data.ArrD16[ii] = root.Float16(i) 242 data.ArrD32[ii] = root.Double32(i) 243 } 244 data.N = int32(i) % 10 245 data.SliBs = make([]bool, int(data.N)) 246 data.SliI8 = make([]int8, int(data.N)) 247 data.SliI16 = make([]int16, int(data.N)) 248 data.SliI32 = make([]int32, int(data.N)) 249 data.SliI64 = make([]int64, int(data.N)) 250 data.SliU8 = make([]uint8, int(data.N)) 251 data.SliU16 = make([]uint16, int(data.N)) 252 data.SliU32 = make([]uint32, int(data.N)) 253 data.SliU64 = make([]uint64, int(data.N)) 254 data.SliF32 = make([]float32, int(data.N)) 255 data.SliF64 = make([]float64, int(data.N)) 256 data.SliD16 = make([]root.Float16, int(data.N)) 257 data.SliD32 = make([]root.Double32, int(data.N)) 258 for ii := range int(data.N) { 259 data.SliBs[ii] = (ii + 1) == int(i) 260 data.SliI8[ii] = int8(-i) 261 data.SliI16[ii] = int16(-i) 262 data.SliI32[ii] = int32(-i) 263 data.SliI64[ii] = int64(-i) 264 data.SliU8[ii] = uint8(i) 265 data.SliU16[ii] = uint16(i) 266 data.SliU32[ii] = uint32(i) 267 data.SliU64[ii] = uint64(i) 268 data.SliF32[ii] = float32(i) 269 data.SliF64[ii] = float64(i) 270 data.SliD16[ii] = root.Float16(i) 271 data.SliD32[ii] = root.Double32(i) 272 } 273 return data 274 } 275 276 func TestReaderStruct(t *testing.T) { 277 files := []string{ 278 "../testdata/x-flat-tree.root", 279 rtests.XrdRemote("testdata/x-flat-tree.root"), 280 } 281 for i := range files { 282 fname := files[i] 283 t.Run(fname, func(t *testing.T) { 284 t.Parallel() 285 286 f, err := riofs.Open(fname) 287 if err != nil { 288 t.Fatal(err.Error()) 289 } 290 defer f.Close() 291 292 obj, err := f.Get("tree") 293 if err != nil { 294 t.Fatal(err) 295 } 296 tree := obj.(Tree) 297 298 var ( 299 want = ScannerData{}.want 300 data ScannerData 301 ) 302 r, err := NewReader(tree, ReadVarsFromStruct(&data)) 303 if err != nil { 304 t.Fatal(err) 305 } 306 defer r.Close() 307 err = r.Read(func(ctx RCtx) error { 308 if got, want := data, want(ctx.Entry); !reflect.DeepEqual(got, want) { 309 return fmt.Errorf( 310 "entry[%d]:\ngot= %#v\nwant=%#v\n", 311 ctx.Entry, got, want, 312 ) 313 } 314 return nil 315 }) 316 if err != nil && err != io.EOF { 317 t.Fatal(err) 318 } 319 }) 320 } 321 } 322 323 func TestReaderWithBufferEvent(t *testing.T) { 324 type Event struct { 325 B bool `groot:"B"` 326 Str string `groot:"Str"` 327 I8 int8 `groot:"I8"` 328 I16 int16 `groot:"I16"` 329 I32 int32 `groot:"I32"` 330 I64 int64 `groot:"I64"` 331 U8 uint8 `groot:"U8"` 332 U16 uint16 `groot:"U16"` 333 U32 uint32 `groot:"U32"` 334 U64 uint64 `groot:"U64"` 335 F32 float32 `groot:"F32"` 336 F64 float64 `groot:"F64"` 337 ArrBs [10]bool `groot:"ArrBs[10]"` 338 ArrI8 [10]int8 `groot:"ArrI8[10]"` 339 ArrI16 [10]int16 `groot:"ArrI16[10]"` 340 ArrI32 [10]int32 `groot:"ArrI32[10]"` 341 ArrI64 [10]int64 `groot:"ArrI64[10]"` 342 ArrU8 [10]uint8 `groot:"ArrU8[10]"` 343 ArrU16 [10]uint16 `groot:"ArrU16[10]"` 344 ArrU32 [10]uint32 `groot:"ArrU32[10]"` 345 ArrU64 [10]uint64 `groot:"ArrU64[10]"` 346 ArrF32 [10]float32 `groot:"ArrF32[10]"` 347 ArrF64 [10]float64 `groot:"ArrF64[10]"` 348 } 349 wantEvent := func(i int64) (evt Event) { 350 evt.B = i%2 == 0 351 evt.Str = fmt.Sprintf("str-%d", i) 352 evt.I8 = int8(-i) 353 evt.I16 = int16(-i) 354 evt.I32 = int32(-i) 355 evt.I64 = int64(-i) 356 evt.U8 = uint8(i) 357 evt.U16 = uint16(i) 358 evt.U32 = uint32(i) 359 evt.U64 = uint64(i) 360 evt.F32 = float32(i) 361 evt.F64 = float64(i) 362 for ii := range evt.ArrI32 { 363 evt.ArrBs[ii] = ii == int(i) 364 evt.ArrI8[ii] = int8(-i) 365 evt.ArrI16[ii] = int16(-i) 366 evt.ArrI32[ii] = int32(-i) 367 evt.ArrI64[ii] = int64(-i) 368 evt.ArrU8[ii] = uint8(i) 369 evt.ArrU16[ii] = uint16(i) 370 evt.ArrU32[ii] = uint32(i) 371 evt.ArrU64[ii] = uint64(i) 372 evt.ArrF32[ii] = float32(i) 373 evt.ArrF64[ii] = float64(i) 374 } 375 return evt 376 } 377 378 files := []string{ 379 "../testdata/x-flat-bufevt.root", 380 } 381 for i := range files { 382 fname := files[i] 383 t.Run(fname, func(t *testing.T) { 384 t.Parallel() 385 386 f, err := riofs.Open(fname) 387 if err != nil { 388 t.Fatal(err.Error()) 389 } 390 defer f.Close() 391 392 obj, err := f.Get("tree") 393 if err != nil { 394 t.Fatal(err) 395 } 396 tree := obj.(Tree) 397 398 var ( 399 want = wantEvent 400 data Event 401 ) 402 r, err := NewReader(tree, []ReadVar{{Name: "Event", Value: &data}}) 403 if err != nil { 404 t.Fatal(err) 405 } 406 defer r.Close() 407 err = r.Read(func(ctx RCtx) error { 408 if got, want := data, want(ctx.Entry); !reflect.DeepEqual(got, want) { 409 return fmt.Errorf( 410 "entry[%d]:\ngot= %#v\nwant=%#v\n", 411 ctx.Entry, got, want, 412 ) 413 } 414 return nil 415 }) 416 if err != nil && err != io.EOF { 417 t.Fatal(err) 418 } 419 }) 420 } 421 } 422 423 func TestReaderVars(t *testing.T) { 424 files := []string{ 425 "../testdata/x-flat-tree.root", 426 rtests.XrdRemote("testdata/x-flat-tree.root"), 427 } 428 for i := range files { 429 fname := files[i] 430 t.Run(fname, func(t *testing.T) { 431 t.Parallel() 432 433 f, err := riofs.Open(fname) 434 if err != nil { 435 t.Fatal(err.Error()) 436 } 437 defer f.Close() 438 439 obj, err := f.Get("tree") 440 if err != nil { 441 t.Fatal(err) 442 } 443 444 tree := obj.(Tree) 445 446 want := ScannerData{}.want 447 448 var ( 449 data ScannerData 450 rvars = ReadVarsFromStruct(&data) 451 ) 452 r, err := NewReader(tree, rvars) 453 if err != nil { 454 t.Fatal(err) 455 } 456 defer r.Close() 457 458 err = r.Read(func(ctx RCtx) error { 459 if got, want := data, want(ctx.Entry); !reflect.DeepEqual(got, want) { 460 return fmt.Errorf( 461 "entry[%d]:\ngot= %#v\nwant=%#v\n", 462 ctx.Entry, got, want, 463 ) 464 } 465 return nil 466 }) 467 if err != nil && err != io.EOF { 468 t.Fatal(err) 469 } 470 }) 471 } 472 } 473 474 func TestReaderVarsMultipleTimes(t *testing.T) { 475 files := []string{ 476 "../testdata/mc_105986.ZZ.root", 477 rtests.XrdRemote("testdata/mc_105986.ZZ.root"), 478 } 479 for i := range files { 480 fname := files[i] 481 t.Run(fname, func(t *testing.T) { 482 t.Parallel() 483 484 f, err := riofs.Open(fname) 485 if err != nil { 486 t.Skip(err) 487 } 488 489 obj, err := f.Get("mini") 490 if err != nil { 491 t.Fatal(err) 492 } 493 tree := obj.(Tree) 494 495 for range 2 { 496 var ( 497 data []float32 498 rvars = []ReadVar{ 499 {Name: "lep_pt", Value: &data}, 500 } 501 ) 502 r, err := NewReader(tree, rvars) 503 if err != nil { 504 t.Fatal(err) 505 } 506 defer r.Close() 507 508 err = r.Read(func(ctx RCtx) error { 509 return nil 510 }) 511 if err != nil { 512 t.Error(err) 513 } 514 } 515 }) 516 } 517 } 518 519 func TestReaderStructWithCounterLeaf(t *testing.T) { 520 files := []string{ 521 "../testdata/x-flat-tree.root", 522 rtests.XrdRemote("testdata/x-flat-tree.root"), 523 } 524 for i := range files { 525 fname := files[i] 526 t.Run(fname, func(t *testing.T) { 527 t.Parallel() 528 529 f, err := riofs.Open(fname) 530 if err != nil { 531 t.Fatal(err.Error()) 532 } 533 defer f.Close() 534 535 obj, err := f.Get("tree") 536 if err != nil { 537 t.Fatal(err) 538 } 539 540 tree := obj.(Tree) 541 542 type Data struct { 543 Sli []int32 `groot:"SliI32"` 544 } 545 var data Data 546 547 want := func(i int64) Data { 548 var data Data 549 n := int32(i) % 10 550 data.Sli = make([]int32, int(n)) 551 for ii := range int(n) { 552 data.Sli[ii] = int32(-i) 553 } 554 return data 555 } 556 557 r, err := NewReader(tree, ReadVarsFromStruct(&data)) 558 if err != nil { 559 t.Fatal(err) 560 } 561 defer r.Close() 562 563 err = r.Read(func(ctx RCtx) error { 564 if got, want := data, want(ctx.Entry); !reflect.DeepEqual(got, want) { 565 return fmt.Errorf( 566 "entry[%d]:\ngot= %#v\nwant=%#v\n", 567 ctx.Entry, got, want, 568 ) 569 } 570 return nil 571 }) 572 if err != nil && err != io.EOF { 573 t.Fatal(err) 574 } 575 }) 576 } 577 } 578 579 func TestReaderVarsWithCounterLeaf(t *testing.T) { 580 files := []string{ 581 "../testdata/x-flat-tree.root", 582 rtests.XrdRemote("testdata/x-flat-tree.root"), 583 } 584 for i := range files { 585 fname := files[i] 586 t.Run(fname, func(t *testing.T) { 587 t.Parallel() 588 589 f, err := riofs.Open(fname) 590 if err != nil { 591 t.Fatal(err.Error()) 592 } 593 defer f.Close() 594 595 obj, err := f.Get("tree") 596 if err != nil { 597 t.Fatal(err) 598 } 599 600 tree := obj.(Tree) 601 602 want := func(i int64) []int32 { 603 n := int32(i) % 10 604 data := make([]int32, int(n)) 605 for ii := range int(n) { 606 data[ii] = int32(-i) 607 } 608 return data 609 } 610 611 var ( 612 data []int32 613 rvars = []ReadVar{ 614 {Name: "SliI32", Value: &data}, 615 } 616 ) 617 r, err := NewReader(tree, rvars) 618 if err != nil { 619 t.Fatal(err) 620 } 621 defer r.Close() 622 623 err = r.Read(func(ctx RCtx) error { 624 if got, want := data, want(ctx.Entry); !reflect.DeepEqual(got, want) { 625 return fmt.Errorf( 626 "entry[%d]:\ngot= %#v\nwant=%#v\n", 627 ctx.Entry, got, want, 628 ) 629 } 630 return nil 631 }) 632 if err != nil && err != io.EOF { 633 t.Fatal(err) 634 } 635 }) 636 } 637 } 638 639 func TestScannerStructWithStdVectorBool(t *testing.T) { 640 files, err := filepath.Glob("../testdata/stdvec-bool-*.root") 641 if err != nil { 642 t.Fatal(err) 643 } 644 645 for i := range files { 646 fname := files[i] 647 t.Run(fname, func(t *testing.T) { 648 t.Parallel() 649 650 f, err := riofs.Open(fname) 651 if err != nil { 652 t.Fatal(err.Error()) 653 } 654 defer f.Close() 655 656 obj, err := f.Get("tree") 657 if err != nil { 658 t.Fatal(err) 659 } 660 tree := obj.(Tree) 661 662 type Data struct { 663 Bool bool `groot:"Bool"` 664 ArrBool [10]bool `groot:"ArrayBool"` 665 N int32 `groot:"N"` 666 SliBool []bool `groot:"SliceBool[N]"` 667 StlBool []bool `groot:"StlVecBool"` 668 } 669 type Event struct { 670 Data Data `groot:"evt"` 671 } 672 673 want := func(i int64) Event { 674 var data Data 675 data.Bool = i%2 == 0 676 for ii := range data.ArrBool { 677 data.ArrBool[ii] = i%2 == 0 678 } 679 data.N = int32(i) % 10 680 switch i { 681 case 0: 682 data.SliBool = nil 683 data.StlBool = nil 684 default: 685 data.SliBool = make([]bool, int(data.N)) 686 data.StlBool = make([]bool, int(data.N)) 687 } 688 for ii := range int(data.N) { 689 data.SliBool[ii] = i%2 == 0 690 data.StlBool[ii] = i%2 == 0 691 } 692 return Event{data} 693 } 694 695 var data Event 696 r, err := NewReader(tree, ReadVarsFromStruct(&data)) 697 if err != nil { 698 t.Fatal(err) 699 } 700 defer r.Close() 701 702 err = r.Read(func(ctx RCtx) error { 703 if got, want := data, want(ctx.Entry); !reflect.DeepEqual(got, want) { 704 return fmt.Errorf( 705 "entry[%d]:\ngot= %#v\nwant=%#v\n", 706 ctx.Entry, got, want, 707 ) 708 } 709 return nil 710 711 }) 712 if err != nil && err != io.EOF { 713 t.Fatal(err) 714 } 715 }) 716 } 717 } 718 719 func TestNewReadVarsLeaves(t *testing.T) { 720 f, err := riofs.Open("../testdata/leaves.root") 721 if err != nil { 722 t.Fatal(err) 723 } 724 defer f.Close() 725 726 o, err := f.Get("tree") 727 if err != nil { 728 t.Fatal(err) 729 } 730 731 tree := o.(Tree) 732 733 vars := NewReadVars(tree) 734 want := []ReadVar{ 735 {Name: "B", Leaf: "B", Value: new(bool)}, 736 {Name: "Str", Leaf: "Str", Value: new(string)}, 737 {Name: "I8", Leaf: "I8", Value: new(int8)}, 738 {Name: "I16", Leaf: "I16", Value: new(int16)}, 739 {Name: "I32", Leaf: "I32", Value: new(int32)}, 740 {Name: "I64", Leaf: "I64", Value: new(int64)}, 741 {Name: "G64", Leaf: "G64", Value: new(int64)}, 742 {Name: "U8", Leaf: "U8", Value: new(uint8)}, 743 {Name: "U16", Leaf: "U16", Value: new(uint16)}, 744 {Name: "U32", Leaf: "U32", Value: new(uint32)}, 745 {Name: "U64", Leaf: "U64", Value: new(uint64)}, 746 {Name: "UGG", Leaf: "UGG", Value: new(uint64)}, 747 {Name: "F32", Leaf: "F32", Value: new(float32)}, 748 {Name: "F64", Leaf: "F64", Value: new(float64)}, 749 {Name: "D16", Leaf: "D16", Value: new(root.Float16)}, 750 {Name: "D32", Leaf: "D32", Value: new(root.Double32)}, 751 // arrays 752 {Name: "ArrBs", Leaf: "ArrBs", Value: new([10]bool)}, 753 {Name: "ArrI8", Leaf: "ArrI8", Value: new([10]int8)}, 754 {Name: "ArrI16", Leaf: "ArrI16", Value: new([10]int16)}, 755 {Name: "ArrI32", Leaf: "ArrI32", Value: new([10]int32)}, 756 {Name: "ArrI64", Leaf: "ArrI64", Value: new([10]int64)}, 757 {Name: "ArrG64", Leaf: "ArrG64", Value: new([10]int64)}, 758 {Name: "ArrU8", Leaf: "ArrU8", Value: new([10]uint8)}, 759 {Name: "ArrU16", Leaf: "ArrU16", Value: new([10]uint16)}, 760 {Name: "ArrU32", Leaf: "ArrU32", Value: new([10]uint32)}, 761 {Name: "ArrU64", Leaf: "ArrU64", Value: new([10]uint64)}, 762 {Name: "ArrUGG", Leaf: "ArrUGG", Value: new([10]uint64)}, 763 {Name: "ArrF32", Leaf: "ArrF32", Value: new([10]float32)}, 764 {Name: "ArrF64", Leaf: "ArrF64", Value: new([10]float64)}, 765 {Name: "ArrD16", Leaf: "ArrD16", Value: new([10]root.Float16)}, 766 {Name: "ArrD32", Leaf: "ArrD32", Value: new([10]root.Double32)}, 767 // slices 768 {Name: "N", Leaf: "N", Value: new(int32)}, 769 {Name: "SliBs", Leaf: "SliBs", Value: new([]bool)}, 770 {Name: "SliI8", Leaf: "SliI8", Value: new([]int8)}, 771 {Name: "SliI16", Leaf: "SliI16", Value: new([]int16)}, 772 {Name: "SliI32", Leaf: "SliI32", Value: new([]int32)}, 773 {Name: "SliI64", Leaf: "SliI64", Value: new([]int64)}, 774 {Name: "SliG64", Leaf: "SliG64", Value: new([]int64)}, 775 {Name: "SliU8", Leaf: "SliU8", Value: new([]uint8)}, 776 {Name: "SliU16", Leaf: "SliU16", Value: new([]uint16)}, 777 {Name: "SliU32", Leaf: "SliU32", Value: new([]uint32)}, 778 {Name: "SliU64", Leaf: "SliU64", Value: new([]uint64)}, 779 {Name: "SliUGG", Leaf: "SliUGG", Value: new([]uint64)}, 780 {Name: "SliF32", Leaf: "SliF32", Value: new([]float32)}, 781 {Name: "SliF64", Leaf: "SliF64", Value: new([]float64)}, 782 {Name: "SliD16", Leaf: "SliD16", Value: new([]root.Float16)}, 783 {Name: "SliD32", Leaf: "SliD32", Value: new([]root.Double32)}, 784 } 785 786 n := min(len(vars), len(want)) 787 788 for i := range n { 789 got := vars[i] 790 if got.Name != want[i].Name { 791 t.Fatalf("invalid read-var name[%d]: got=%q, want=%q", i, got.Name, want[i].Name) 792 } 793 if got.Leaf != want[i].Leaf { 794 t.Fatalf("invalid read-var (name=%q) leaf-name[%d]: got=%q, want=%q", got.Name, i, got.Leaf, want[i].Leaf) 795 } 796 if got, want := reflect.TypeOf(got.Value), reflect.TypeOf(want[i].Value); got != want { 797 t.Fatalf("invalid read-var (name=%q) type[%d]: got=%v, want=%v", vars[i].Name, i, got, want) 798 } 799 } 800 801 if len(want) != len(vars) { 802 t.Fatalf("invalid lengths. got=%d, want=%d", len(vars), len(want)) 803 } 804 } 805 806 func TestG4LikeTree(t *testing.T) { 807 t.Parallel() 808 fname := rtests.XrdRemote("testdata/g4-like.root") 809 810 f, err := riofs.Open(fname) 811 if err != nil { 812 t.Fatal(err.Error()) 813 } 814 defer f.Close() 815 816 obj, err := f.Get("mytree") 817 if err != nil { 818 t.Fatal(err) 819 } 820 821 tree := obj.(Tree) 822 823 type EventData struct { 824 I32 int32 `groot:"i32"` 825 F64 float64 `groot:"f64"` 826 Sli []float64 `groot:"slif64"` 827 } 828 829 want := func(i int64) (data EventData) { 830 data.I32 = int32(i + 1) 831 data.F64 = float64(i + 1) 832 data.Sli = make([]float64, i) 833 for ii := range data.Sli { 834 data.Sli[ii] = float64(ii) + float64(i) 835 } 836 return data 837 } 838 839 data := EventData{ 840 Sli: make([]float64, 0), 841 } 842 rvars := []ReadVar{ 843 {Name: "i32", Value: &data.I32}, 844 {Name: "f64", Value: &data.F64}, 845 {Name: "slif64", Value: &data.Sli}, 846 } 847 r, err := NewReader(tree, rvars) 848 if err != nil { 849 t.Fatal(err) 850 } 851 defer r.Close() 852 853 err = r.Read(func(ctx RCtx) error { 854 if got, want := data, want(ctx.Entry); !reflect.DeepEqual(got, want) { 855 return fmt.Errorf( 856 "entry[%d]:\ngot= %#v\nwant=%#v\n", 857 ctx.Entry, got, want, 858 ) 859 } 860 return nil 861 }) 862 if err != nil && err != io.EOF { 863 t.Fatal(err) 864 } 865 } 866 867 func TestMultiLeafBranchWithReadVars(t *testing.T) { 868 t.Parallel() 869 870 f, err := riofs.Open("../testdata/root_numpy_struct.root") 871 if err != nil { 872 t.Fatalf("%+v", err) 873 } 874 defer f.Close() 875 876 obj, err := f.Get("test") 877 if err != nil { 878 t.Fatalf("%+v", err) 879 } 880 881 tree := obj.(Tree) 882 883 type Data struct { 884 b1l1 int32 885 b1l2 float32 886 b2l1 int32 887 b2l2 float32 888 } 889 890 var ( 891 data Data 892 want = []Data{ 893 {10, 15.5, 20, 781.2}, 894 } 895 ) 896 897 rvars := []ReadVar{ 898 { 899 Name: "branch1", 900 Leaf: "intleaf", 901 Value: &data.b1l1, 902 }, 903 { 904 Name: "branch1", 905 Leaf: "floatleaf", 906 Value: &data.b1l2, 907 }, 908 { 909 Name: "branch2", 910 Leaf: "intleaf", 911 Value: &data.b2l1, 912 }, 913 { 914 Name: "branch2", 915 Leaf: "floatleaf", 916 Value: &data.b2l2, 917 }, 918 } 919 920 r, err := NewReader(tree, rvars) 921 if err != nil { 922 t.Fatalf("could not create reader: %+v", err) 923 } 924 defer r.Close() 925 926 err = r.Read(func(ctx RCtx) error { 927 if got, want := data, want[ctx.Entry]; !reflect.DeepEqual(got, want) { 928 return fmt.Errorf( 929 "entry[%d]:\ngot= %#v\nwant=%#v\n", 930 ctx.Entry, got, want, 931 ) 932 } 933 return nil 934 }) 935 936 if err != nil { 937 t.Fatal(err) 938 } 939 } 940 941 func TestMultiLeafBranchWithTreeReadVars(t *testing.T) { 942 t.Parallel() 943 944 f, err := riofs.Open("../testdata/root_numpy_struct.root") 945 if err != nil { 946 t.Fatalf("%+v", err) 947 } 948 defer f.Close() 949 950 obj, err := f.Get("test") 951 if err != nil { 952 t.Fatalf("%+v", err) 953 } 954 955 tree := obj.(Tree) 956 957 type B struct { 958 L1 int32 `groot:"intleaf"` 959 L2 float32 `groot:"floatleaf"` 960 } 961 962 type Data struct { 963 B1 B `groot:"branch1"` 964 B2 B `groot:"branch2"` 965 } 966 967 var ( 968 data Data 969 want = []Data{ 970 {B{10, 15.5}, B{20, 781.2}}, 971 } 972 ) 973 974 rvars := []ReadVar{ 975 { 976 Name: "branch1", 977 Leaf: "intleaf", 978 Value: &data.B1.L1, 979 }, 980 { 981 Name: "branch1", 982 Leaf: "floatleaf", 983 Value: &data.B1.L2, 984 }, 985 { 986 Name: "branch2", 987 Leaf: "intleaf", 988 Value: &data.B2.L1, 989 }, 990 { 991 Name: "branch2", 992 Leaf: "floatleaf", 993 Value: &data.B2.L2, 994 }, 995 } 996 997 r, err := NewReader(tree, rvars) 998 if err != nil { 999 t.Fatalf("could not create reader: %+v", err) 1000 } 1001 defer r.Close() 1002 1003 err = r.Read(func(ctx RCtx) error { 1004 if got, want := data, want[ctx.Entry]; !reflect.DeepEqual(got, want) { 1005 return fmt.Errorf( 1006 "entry[%d]:\ngot= %#v\nwant=%#v\n", 1007 ctx.Entry, got, want, 1008 ) 1009 } 1010 return nil 1011 }) 1012 if err != nil { 1013 t.Fatal(err) 1014 } 1015 }