go-hep.org/x/hep@v0.38.1/groot/rtree/join_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 "reflect" 10 "testing" 11 12 "go-hep.org/x/hep/groot/riofs" 13 ) 14 15 func TestJoin(t *testing.T) { 16 loadTree := func(fname, tname string) (Tree, func() error) { 17 f, err := riofs.Open(fname) 18 if err != nil { 19 t.Fatalf("could not open %q: %+v", fname, err) 20 } 21 o, err := riofs.Dir(f).Get(tname) 22 if err != nil { 23 t.Fatalf("could not get tree %q from %q: %+v", tname, fname, err) 24 } 25 26 return o.(Tree), f.Close 27 } 28 chk := func(f func() error) { 29 err := f() 30 if err != nil { 31 t.Fatal(err) 32 } 33 } 34 35 j1, close1 := loadTree("../testdata/join1.root", "j1") 36 defer chk(close1) 37 38 j2, close2 := loadTree("../testdata/join2.root", "j2") 39 defer chk(close2) 40 41 j3, close3 := loadTree("../testdata/join3.root", "j3") 42 defer chk(close3) 43 44 j41, close41 := loadTree("../testdata/join4.root", "j41") 45 defer chk(close41) 46 47 j42, close42 := loadTree("../testdata/join4.root", "j42") 48 defer chk(close42) 49 50 for _, tc := range []struct { 51 test string 52 trees []Tree 53 name string 54 title string 55 nevts int64 56 rvars []ReadVar 57 brs []string 58 brOK string 59 brNOT string 60 lvs []string 61 lvOK string 62 lvNOT string 63 err error 64 }{ 65 { 66 test: "empty", 67 trees: nil, 68 err: fmt.Errorf("rtree: no trees to join"), 69 }, 70 { 71 test: "entries-differ-j1-j41", 72 trees: []Tree{j1, j41}, 73 err: fmt.Errorf("rtree: invalid number of entries in tree j41 (got=11, want=10)"), 74 }, 75 { 76 test: "entries-differ-j41-j1", 77 trees: []Tree{j41, j1}, 78 err: fmt.Errorf("rtree: invalid number of entries in tree j1 (got=10, want=11)"), 79 }, 80 { 81 test: "branch-collision-1-same-type", 82 trees: []Tree{j2, j42}, 83 err: fmt.Errorf("rtree: trees j2 and j42 both have a branch named b22"), 84 }, 85 { 86 test: "branch-collision-2-same-type", 87 trees: []Tree{j42, j2}, 88 err: fmt.Errorf("rtree: trees j42 and j2 both have a branch named b22"), 89 }, 90 { 91 test: "branch-collision-1-diff-type", 92 trees: []Tree{j1, j42}, 93 err: fmt.Errorf("rtree: trees j1 and j42 both have a branch named b11"), 94 }, 95 { 96 test: "branch-collision-2-diff-type", 97 trees: []Tree{j42, j1}, 98 err: fmt.Errorf("rtree: trees j42 and j1 both have a branch named b11"), 99 }, 100 { 101 test: "join-j1", 102 trees: []Tree{j1}, 103 nevts: 10, 104 name: "join_j1", 105 title: "j1-tree", 106 rvars: []ReadVar{ 107 {Name: "b10", Leaf: "b10", Value: new(float64)}, 108 {Name: "b11", Leaf: "b11", Value: new(int64)}, 109 {Name: "b12", Leaf: "b12", Value: new(string)}, 110 }, 111 brs: []string{ 112 "b10", "b11", "b12", 113 }, 114 brOK: "b10", 115 brNOT: "b40", 116 lvs: []string{ 117 "b10", "b11", "b12", 118 }, 119 lvOK: "b10", 120 lvNOT: "b40", 121 }, 122 { 123 test: "join-j2", 124 trees: []Tree{j2}, 125 nevts: 10, 126 name: "join_j2", 127 title: "j2-tree", 128 rvars: []ReadVar{ 129 {Name: "b20", Leaf: "b20", Value: new(float64)}, 130 {Name: "b21", Leaf: "b21", Value: new(int64)}, 131 {Name: "b22", Leaf: "b22", Value: new(string)}, 132 }, 133 brs: []string{ 134 "b20", "b21", "b22", 135 }, 136 brOK: "b20", 137 brNOT: "b40", 138 lvs: []string{ 139 "b20", "b21", "b22", 140 }, 141 lvOK: "b20", 142 lvNOT: "b40", 143 }, 144 { 145 test: "join-j3", 146 trees: []Tree{j3}, 147 nevts: 10, 148 name: "join_j3", 149 title: "j3-tree", 150 rvars: []ReadVar{ 151 {Name: "b30", Leaf: "b30", Value: new(float64)}, 152 {Name: "b31", Leaf: "b31", Value: new(int64)}, 153 {Name: "b32", Leaf: "b32", Value: new(string)}, 154 }, 155 brs: []string{ 156 "b30", "b31", "b32", 157 }, 158 brOK: "b30", 159 brNOT: "b40", 160 lvs: []string{ 161 "b30", "b31", "b32", 162 }, 163 lvOK: "b30", 164 lvNOT: "b40", 165 }, 166 { 167 test: "join-j1-j2-j3", 168 trees: []Tree{j1, j2, j3}, 169 nevts: 10, 170 name: "join_j1_j2_j3", 171 title: "j1-tree, j2-tree, j3-tree", 172 rvars: []ReadVar{ 173 {Name: "b10", Leaf: "b10", Value: new(float64)}, 174 {Name: "b11", Leaf: "b11", Value: new(int64)}, 175 {Name: "b12", Leaf: "b12", Value: new(string)}, 176 {Name: "b20", Leaf: "b20", Value: new(float64)}, 177 {Name: "b21", Leaf: "b21", Value: new(int64)}, 178 {Name: "b22", Leaf: "b22", Value: new(string)}, 179 {Name: "b30", Leaf: "b30", Value: new(float64)}, 180 {Name: "b31", Leaf: "b31", Value: new(int64)}, 181 {Name: "b32", Leaf: "b32", Value: new(string)}, 182 }, 183 brs: []string{ 184 "b10", "b11", "b12", 185 "b20", "b21", "b22", 186 "b30", "b31", "b32", 187 }, 188 brOK: "b10", 189 brNOT: "b40", 190 lvs: []string{ 191 "b10", "b11", "b12", 192 "b20", "b21", "b22", 193 "b30", "b31", "b32", 194 }, 195 lvOK: "b10", 196 lvNOT: "b40", 197 }, 198 { 199 test: "join-j1-j2", 200 trees: []Tree{j1, j2}, 201 nevts: 10, 202 name: "join_j1_j2", 203 title: "j1-tree, j2-tree", 204 rvars: []ReadVar{ 205 {Name: "b10", Leaf: "b10", Value: new(float64)}, 206 {Name: "b11", Leaf: "b11", Value: new(int64)}, 207 {Name: "b12", Leaf: "b12", Value: new(string)}, 208 {Name: "b20", Leaf: "b20", Value: new(float64)}, 209 {Name: "b21", Leaf: "b21", Value: new(int64)}, 210 {Name: "b22", Leaf: "b22", Value: new(string)}, 211 }, 212 brs: []string{ 213 "b10", "b11", "b12", 214 "b20", "b21", "b22", 215 }, 216 brOK: "b10", 217 brNOT: "b30", 218 lvs: []string{ 219 "b10", "b11", "b12", 220 "b20", "b21", "b22", 221 }, 222 lvOK: "b10", 223 lvNOT: "b30", 224 }, 225 { 226 test: "join-j2-j1", 227 trees: []Tree{j2, j1}, 228 nevts: 10, 229 name: "join_j2_j1", 230 title: "j2-tree, j1-tree", 231 rvars: []ReadVar{ 232 {Name: "b20", Leaf: "b20", Value: new(float64)}, 233 {Name: "b21", Leaf: "b21", Value: new(int64)}, 234 {Name: "b22", Leaf: "b22", Value: new(string)}, 235 {Name: "b10", Leaf: "b10", Value: new(float64)}, 236 {Name: "b11", Leaf: "b11", Value: new(int64)}, 237 {Name: "b12", Leaf: "b12", Value: new(string)}, 238 }, 239 brs: []string{ 240 "b20", "b21", "b22", 241 "b10", "b11", "b12", 242 }, 243 brOK: "b10", 244 brNOT: "b30", 245 lvs: []string{ 246 "b20", "b21", "b22", 247 "b10", "b11", "b12", 248 }, 249 lvOK: "b10", 250 lvNOT: "b30", 251 }, 252 { 253 test: "join-j1-j3", 254 trees: []Tree{j1, j3}, 255 nevts: 10, 256 name: "join_j1_j3", 257 title: "j1-tree, j3-tree", 258 rvars: []ReadVar{ 259 {Name: "b10", Leaf: "b10", Value: new(float64)}, 260 {Name: "b11", Leaf: "b11", Value: new(int64)}, 261 {Name: "b12", Leaf: "b12", Value: new(string)}, 262 {Name: "b30", Leaf: "b30", Value: new(float64)}, 263 {Name: "b31", Leaf: "b31", Value: new(int64)}, 264 {Name: "b32", Leaf: "b32", Value: new(string)}, 265 }, 266 brs: []string{ 267 "b10", "b11", "b12", 268 "b30", "b31", "b32", 269 }, 270 brOK: "b10", 271 brNOT: "b40", 272 lvs: []string{ 273 "b10", "b11", "b12", 274 "b30", "b31", "b32", 275 }, 276 lvOK: "b10", 277 lvNOT: "b40", 278 }, 279 { 280 test: "join-j2-j3", 281 trees: []Tree{j2, j3}, 282 nevts: 10, 283 name: "join_j2_j3", 284 title: "j2-tree, j3-tree", 285 rvars: []ReadVar{ 286 {Name: "b20", Leaf: "b20", Value: new(float64)}, 287 {Name: "b21", Leaf: "b21", Value: new(int64)}, 288 {Name: "b22", Leaf: "b22", Value: new(string)}, 289 {Name: "b30", Leaf: "b30", Value: new(float64)}, 290 {Name: "b31", Leaf: "b31", Value: new(int64)}, 291 {Name: "b32", Leaf: "b32", Value: new(string)}, 292 }, 293 brs: []string{ 294 "b20", "b21", "b22", 295 "b30", "b31", "b32", 296 }, 297 brOK: "b20", 298 brNOT: "b10", 299 lvs: []string{ 300 "b20", "b21", "b22", 301 "b30", "b31", "b32", 302 }, 303 lvOK: "b20", 304 lvNOT: "b10", 305 }, 306 } { 307 t.Run(tc.test, func(t *testing.T) { 308 tree, err := Join(tc.trees...) 309 switch { 310 case err != nil && tc.err != nil: 311 if got, want := err.Error(), tc.err.Error(); got != want { 312 t.Fatalf("invalid error:\ngot= %s\nwant=%s", got, want) 313 } 314 return 315 case err != nil && tc.err == nil: 316 t.Fatalf("could not join trees: %+v", err) 317 case err == nil && tc.err != nil: 318 t.Fatalf("invalid error:\ngot= %v\nwant: %s", err, tc.err.Error()) 319 case err == nil && tc.err == nil: 320 // ok. 321 } 322 323 if got, want := tree.Class(), "TJoin"; got != want { 324 t.Fatalf("invalid class:\ngot= %q\nwant=%q", got, want) 325 } 326 327 if got, want := tree.Name(), tc.name; got != want { 328 t.Fatalf("invalid name:\ngot= %q\nwant=%q", got, want) 329 } 330 331 if got, want := tree.Title(), tc.title; got != want { 332 t.Fatalf("invalid title:\ngot= %q\nwant=%q", got, want) 333 } 334 335 if got, want := tree.Entries(), tc.nevts; got != want { 336 t.Fatalf("invalid entries: got=%d, want=%d", got, want) 337 } 338 { 339 rvars := NewReadVars(tree) 340 n := min(len(rvars), len(tc.rvars)) 341 342 for i := range n { 343 got := rvars[i] 344 want := tc.rvars[i] 345 if got.Name != want.Name { 346 t.Fatalf("invalid rvar-name[%d]: got=%q, want=%q", i, got.Name, want.Name) 347 } 348 if got.Leaf != want.Leaf { 349 t.Fatalf("invalid rvar-leaf[%d]: got=%q, want=%q", i, got.Leaf, want.Leaf) 350 } 351 if got, want := reflect.TypeOf(got.Value), reflect.TypeOf(want.Value); got != want { 352 t.Fatalf("invalid rvar (name=%q) type[%d]: got=%v, want=%v", rvars[i].Name, i, got, want) 353 } 354 } 355 356 if got, want := len(rvars), len(tc.rvars); got != want { 357 t.Fatalf("invalid number of rvars: got=%d, want=%d", got, want) 358 } 359 } 360 { 361 brs := tree.Branches() 362 n := min(len(brs), len(tc.brs)) 363 364 for i := range n { 365 if got, want := brs[i].Name(), tc.brs[i]; got != want { 366 t.Fatalf("invalid branch name[%d]: got=%q, want=%q", i, got, want) 367 } 368 } 369 370 if got, want := len(brs), len(tc.brs); got != want { 371 t.Fatalf("invalid number of branches: got=%d, want=%d", got, want) 372 } 373 374 br := tree.Branch(tc.brOK) 375 if br == nil { 376 t.Fatalf("could not retrieve branch %q", tc.brOK) 377 } 378 if got, want := br.Name(), tc.brOK; got != want { 379 t.Fatalf("invalid name for branch-ok: got=%q, want=%q", got, want) 380 } 381 382 br = tree.Branch(tc.brNOT) 383 if br != nil { 384 t.Fatalf("unexpected branch for branch-not (%s): got=%#v", tc.brNOT, br) 385 } 386 } 387 { 388 lvs := tree.Leaves() 389 n := min(len(lvs), len(tc.lvs)) 390 391 for i := range n { 392 if got, want := lvs[i].Name(), tc.lvs[i]; got != want { 393 t.Fatalf("invalid leaf name[%d]: got=%q, want=%q", i, got, want) 394 } 395 } 396 397 if got, want := len(lvs), len(tc.lvs); got != want { 398 t.Fatalf("invalid number of leaves: got=%d, want=%d", got, want) 399 } 400 401 lv := tree.Leaf(tc.lvOK) 402 if lv == nil { 403 t.Fatalf("could not retrieve leaf %q", tc.lvOK) 404 } 405 if got, want := lv.Name(), tc.lvOK; got != want { 406 t.Fatalf("invalid name for leaf-ok: got=%q, want=%q", got, want) 407 } 408 br := lv.Branch() 409 if br == nil || br.Name() != tc.lvOK { 410 t.Fatalf("invalid leaf-branch: ptr-ok=%v", br != nil) 411 } 412 413 lv = tree.Leaf(tc.lvNOT) 414 if lv != nil { 415 t.Fatalf("unexpected leaf for leaf-not (%s): got=%#v", tc.lvNOT, lv) 416 } 417 } 418 }) 419 } 420 }