go-hep.org/x/hep@v0.38.1/groot/rcmd/dump_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 rcmd_test 6 7 import ( 8 "os" 9 "strings" 10 "testing" 11 12 "github.com/google/go-cmp/cmp" 13 "go-hep.org/x/hep/groot/rcmd" 14 ) 15 16 func TestDump(t *testing.T) { 17 const deep = true 18 loadRef := func(fname string) string { 19 t.Helper() 20 raw, err := os.ReadFile(fname) 21 if err != nil { 22 t.Fatalf("could not load reference file %q: %+v", fname, err) 23 } 24 return string(raw) 25 } 26 27 for _, tc := range []struct { 28 name string 29 want string 30 }{ 31 { 32 name: "../testdata/simple.root", 33 want: `key[000]: tree;1 "fake data" (TTree) 34 [000][one]: 1 35 [000][two]: 1.1 36 [000][three]: uno 37 [001][one]: 2 38 [001][two]: 2.2 39 [001][three]: dos 40 [002][one]: 3 41 [002][two]: 3.3 42 [002][three]: tres 43 [003][one]: 4 44 [003][two]: 4.4 45 [003][three]: quatro 46 `, 47 }, 48 { 49 name: "../testdata/root_numpy_struct.root", 50 want: `key[000]: test;1 "identical leaf names in different branches" (TTree) 51 [000][branch1.intleaf]: 10 52 [000][branch1.floatleaf]: 15.5 53 [000][branch2.intleaf]: 20 54 [000][branch2.floatleaf]: 781.2 55 `, 56 }, 57 { 58 name: "../testdata/tntuple.root", 59 want: `key[000]: ntup;1 "my ntuple title" (TNtuple) 60 [000][x]: 0 61 [000][y]: 0.5 62 [001][x]: 1 63 [001][y]: 1.5 64 [002][x]: 2 65 [002][y]: 2.5 66 [003][x]: 3 67 [003][y]: 3.5 68 [004][x]: 4 69 [004][y]: 4.5 70 [005][x]: 5 71 [005][y]: 5.5 72 [006][x]: 6 73 [006][y]: 6.5 74 [007][x]: 7 75 [007][y]: 7.5 76 [008][x]: 8 77 [008][y]: 8.5 78 [009][x]: 9 79 [009][y]: 9.5 80 `, 81 }, 82 { 83 name: "../testdata/tntupled.root", 84 want: `key[000]: ntup;1 "my ntuple title" (TNtupleD) 85 [000][x]: 0 86 [000][y]: 0.5 87 [001][x]: 1 88 [001][y]: 1.5 89 [002][x]: 2 90 [002][y]: 2.5 91 [003][x]: 3 92 [003][y]: 3.5 93 [004][x]: 4 94 [004][y]: 4.5 95 [005][x]: 5 96 [005][y]: 5.5 97 [006][x]: 6 98 [006][y]: 6.5 99 [007][x]: 7 100 [007][y]: 7.5 101 [008][x]: 8 102 [008][y]: 8.5 103 [009][x]: 9 104 [009][y]: 9.5 105 `, 106 }, 107 { 108 name: "../testdata/padding.root", 109 want: `key[000]: tree;1 "tree w/ & w/o padding" (TTree) 110 [000][pad.x1]: 0 111 [000][pad.x2]: 548655054794 112 [000][pad.x3]: 0 113 [000][nop.x1]: 0 114 [000][nop.x2]: 0 115 [000][nop.x3]: 0 116 [001][pad.x1]: 1 117 [001][pad.x2]: 72058142692982730 118 [001][pad.x3]: 0 119 [001][nop.x1]: 1 120 [001][nop.x2]: 1 121 [001][nop.x3]: 1 122 [002][pad.x1]: 2 123 [002][pad.x2]: 144115736730910666 124 [002][pad.x3]: 0 125 [002][nop.x1]: 2 126 [002][nop.x2]: 2 127 [002][nop.x3]: 2 128 [003][pad.x1]: 3 129 [003][pad.x2]: 216173330768838602 130 [003][pad.x3]: 0 131 [003][nop.x1]: 3 132 [003][nop.x2]: 3 133 [003][nop.x3]: 3 134 [004][pad.x1]: 4 135 [004][pad.x2]: 288230924806766538 136 [004][pad.x3]: 0 137 [004][nop.x1]: 4 138 [004][nop.x2]: 4 139 [004][nop.x3]: 4 140 `, 141 }, 142 { 143 name: "../testdata/small-flat-tree.root", 144 want: loadRef("testdata/small-flat-tree.root.txt"), 145 }, 146 { 147 name: "../testdata/small-evnt-tree-fullsplit.root", 148 want: loadRef("testdata/small-evnt-tree-fullsplit.root.txt"), 149 }, 150 { 151 name: "../testdata/small-evnt-tree-nosplit.root", 152 want: loadRef("testdata/small-evnt-tree-nosplit.root.txt"), 153 }, 154 { 155 name: "../testdata/leaves.root", 156 want: loadRef("testdata/leaves.root.txt"), 157 }, 158 { 159 name: "../testdata/embedded-std-vector.root", 160 want: `key[000]: modules;1 "Module Tree Analysis" (TTree) 161 [000][hits_n]: 10 162 [000][hits_time_mc]: [12.206399 11.711122 11.73492 12.45704 11.558057 11.56502 11.687759 11.528914 12.893241 11.429288] 163 [001][hits_n]: 11 164 [001][hits_time_mc]: [11.718019 12.985347 12.23121 11.825082 12.405976 15.339471 11.939051 12.935032 13.661691 11.969542 11.893113] 165 [002][hits_n]: 15 166 [002][hits_time_mc]: [12.231329 12.214683 12.194867 12.246092 11.859249 19.35934 12.155213 12.226966 -4.712372 11.851829 11.8806925 11.8204975 11.866335 13.285733 -4.6470475] 167 [003][hits_n]: 9 168 [003][hits_time_mc]: [11.33844 11.725604 12.774131 12.108594 12.192085 12.120591 12.129445 12.18349 11.591005] 169 [004][hits_n]: 13 170 [004][hits_time_mc]: [12.156414 12.641215 11.678816 12.329707 11.578169 12.512748 11.840462 14.120602 11.875188 14.133265 14.105912 14.905052 11.813884] 171 `, 172 }, 173 { 174 // recovered baskets 175 name: "../testdata/uproot/issue21.root", 176 want: loadRef("../testdata/uproot/issue21.root.txt"), 177 }, 178 { 179 name: "../testdata/treeCharExample.root", 180 want: `key[000]: nominal;1 "tree" (TTree) 181 [000][d_fakeEvent]: false 182 [000][d_lep_ECIDS]: [1 110] 183 [001][d_fakeEvent]: false 184 [001][d_lep_ECIDS]: [1 1] 185 [002][d_fakeEvent]: false 186 [002][d_lep_ECIDS]: [110 110] 187 [003][d_fakeEvent]: false 188 [003][d_lep_ECIDS]: [1 110] 189 [004][d_fakeEvent]: false 190 [004][d_lep_ECIDS]: [1 110] 191 [005][d_fakeEvent]: false 192 [005][d_lep_ECIDS]: [110 110] 193 [006][d_fakeEvent]: false 194 [006][d_lep_ECIDS]: [1 0] 195 [007][d_fakeEvent]: false 196 [007][d_lep_ECIDS]: [1 110] 197 [008][d_fakeEvent]: false 198 [008][d_lep_ECIDS]: [1 1] 199 [009][d_fakeEvent]: false 200 [009][d_lep_ECIDS]: [1 1] 201 `, 202 }, 203 { 204 // no embedded streamer for std::string 205 name: "../testdata/no-streamer-string.root", 206 want: loadRef("testdata/no-streamer-string.root.txt"), 207 }, 208 { 209 // 'This' streamer of vector<vector<double>> 210 name: "../testdata/vec-vec-double.root", 211 want: `key[000]: t;1 "" (TTree) 212 [000][x]: [] 213 [001][x]: [[] []] 214 [002][x]: [[10] [] [10 20]] 215 [003][x]: [[20 -21 -22]] 216 [004][x]: [[200] [-201] [202]] 217 `, 218 }, 219 { 220 // Geant4 w/ recover baskets 221 name: "../testdata/g4-like.root", 222 want: `key[000]: mytree;1 "my title" (TTree) 223 [000][i32]: 1 224 [000][f64]: 1 225 [000][slif64]: [] 226 [001][i32]: 2 227 [001][f64]: 2 228 [001][slif64]: [1] 229 [002][i32]: 3 230 [002][f64]: 3 231 [002][slif64]: [2 3] 232 [003][i32]: 4 233 [003][f64]: 4 234 [003][slif64]: [3 4 5] 235 [004][i32]: 5 236 [004][f64]: 5 237 [004][slif64]: [4 5 6 7] 238 `, 239 }, 240 { 241 // std::bitset<N>, std::vector<std::bitset<N>> 242 name: "../testdata/std-bitset.root", 243 want: `key[000]: tree;1 "my tree title" (TTree) 244 [000][evt]: {[0 0 0 1 0 0 0 1] [[1 1 1 0 1 1 1 0]]} 245 [001][evt]: {[1 0 0 1 1 0 0 1] [[0 0 0 1 0 0 0 1] [1 1 1 0 1 1 1 0]]} 246 [002][evt]: {[0 1 1 0 0 1 1 0] [[1 0 0 1 1 0 0 1] [0 1 1 0 0 1 1 0] [1 1 0 0 1 1 0 0]]} 247 `, 248 }, 249 { 250 // std-map w/ split-level=0, mbr-wise 251 name: "../testdata/std-map-split0.root", 252 want: loadRef("testdata/std-map-split0.root.txt"), 253 }, 254 { 255 // std-map w/ split-level=1, mbr-wise 256 name: "../testdata/std-map-split1.root", 257 want: loadRef("testdata/std-map-split1.root.txt"), 258 }, 259 { 260 // std::map, std::set, std::list, std::deque, std::unordered_map, std::unordered_set, TString 261 name: "../testdata/std-containers-split00.root", 262 want: loadRef("testdata/std-containers-split00.root.txt"), 263 }, 264 { 265 // n-dim arrays 266 // FIXME(sbinet): arrays of Float16_t and Double32_t are flatten. 267 // This is because of: 268 // https://sft.its.cern.ch/jira/browse/ROOT-10149 269 name: "../testdata/ndim.root", 270 want: loadRef("testdata/ndim.root.txt"), 271 }, 272 { 273 // slices of n-dim arrays 274 // FIXME(sbinet): arrays of Float16_t and Double32_t are flatten. 275 // This is because of: 276 // https://sft.its.cern.ch/jira/browse/ROOT-10149 277 name: "../testdata/ndim-slice.root", 278 want: loadRef("testdata/ndim-slice.root.txt"), 279 }, 280 { 281 name: "../testdata/tformula.root", 282 want: `key[000]: func1;1 "[0] + [1]*x" (TF1) => "TF1{Formula: TFormula{[p0]+[p1]*x}}" 283 key[001]: func2;1 "func2" (TF1) => "TF1{Params: TF1Parameters{Values: [10 20], Names: [p0 p1]}}" 284 key[002]: func3;1 "func3" (TF1) => "TF1{Params: TF1Parameters{Values: [1 -0.3 0 1], Names: [p0 p1 p2 p3]}}" 285 key[003]: func4;1 "func4" (TF1) => "TF1{Params: TF1Parameters{Values: [0 0 0 0 0 0], Names: [p0 p1 p2 p3 p4 p5]}}" 286 key[004]: fconv;1 "" (TF1Convolution) => "TF1Convolution{Func1: TF1{Formula: TFormula{exp([Constant]+[Slope]*x)}}, Func2: TF1{Formula: TFormula{[Constant]*exp(-0.5*((x-[Mean])/[Sigma])*((x-[Mean])/[Sigma]))}}}" 287 key[005]: fnorm;1 "" (TF1NormSum) => "TF1Convolution{Funcs: []{TF1{Formula: TFormula{[p0]+[p1]*x}}, TF1{Params: TF1Parameters{Values: [10 20], Names: [p0 p1]}}}, Coeffs: [10 20]}" 288 `, 289 }, 290 { 291 name: "../testdata/tconfidence-level.root", 292 want: `key[000]: clvl;1 "output for TLimit functions" (TConfidenceLevel) => ignoring key of type *rhist.ConfidenceLevel 293 key[001]: limit;1 "object title" (TLimit) => ignoring key of type *rhist.Limit 294 key[002]: dsrc;1 "input for TLimit routines" (TLimitDataSource) => ignoring key of type *rhist.LimitDataSource 295 key[003]: eff;1 "efficiency" (TEfficiency) => ignoring key of type *rhist.Efficiency 296 `, 297 }, 298 { 299 name: "../testdata/pod.root", 300 want: loadRef("testdata/pod.root.txt"), 301 }, 302 { 303 name: "../testdata/pod-advanced.root", 304 want: loadRef("testdata/pod-advanced.root.txt"), 305 }, 306 { 307 name: "../testdata/uproot/uproot-issue-172.root", 308 want: loadRef("testdata/uproot-issue-172.root.txt"), 309 }, 310 { 311 name: "../testdata/tdatime.root", 312 want: `key[000]: tda;1 "object title" (TDatime) => "2006-01-02 15:04:05 +0000 UTC" 313 key[001]: foo;1 "" (TFoo) => &{{0 50331648} 2006-01-02 15:04:05 +0000 UTC} 314 key[002]: bar;1 "" (TBar) => &{{0 50331648} 2006-01-02 15:04:05 +0000 UTC [49 50 51 52 53 0]} 315 key[003]: dat;1 "object title" (Date) => &{2006-01-02 15:04:05 +0000 UTC [49 50 51 52 53 0]} 316 key[004]: tree;1 "my tree title" (TTree) 317 [000][b0]: 2006-01-02 15:04:05 +0000 UTC 318 [000][b1]: {{0 50331648} 2006-01-02 15:04:05 +0000 UTC} 319 [000][b2]: {{0 50331648} 2006-01-02 15:04:05 +0000 UTC [49 50 51 52 53 0]} 320 [000][b3]: {2006-01-02 15:04:05 +0000 UTC [49 50 51 52 53 0]} 321 [001][b0]: 2006-01-03 15:04:05 +0000 UTC 322 [001][b1]: {{0 50331648} 2006-01-03 15:04:05 +0000 UTC} 323 [001][b2]: {{0 50331648} 2006-01-03 15:04:05 +0000 UTC [49 50 51 52 53 0]} 324 [001][b3]: {2006-01-03 15:04:05 +0000 UTC [49 50 51 52 53 0]} 325 `, 326 }, 327 { 328 name: "../testdata/tgme.root", 329 want: loadRef("testdata/tgme.root.txt"), 330 }, 331 { 332 // ROOT::VecOps::RVec<T> 333 name: "../testdata/rvec.root", 334 want: loadRef("testdata/rvec.root.txt"), 335 }, 336 { 337 name: "../testdata/tcanvas.root", 338 want: loadRef("testdata/tcanvas.root.txt"), 339 }, 340 } { 341 t.Run(tc.name, func(t *testing.T) { 342 got := new(strings.Builder) 343 err := rcmd.Dump(got, tc.name, deep, nil) 344 if err != nil { 345 t.Fatalf("could not run root-dump: %+v", err) 346 } 347 348 if got, want := got.String(), tc.want; got != want { 349 diff := cmp.Diff(want, got) 350 t.Fatalf("invalid root-dump output: -- (-ref +got)\n%s", diff) 351 } 352 }) 353 } 354 } 355 356 func BenchmarkDump(b *testing.B) { 357 const deep = true 358 out := new(strings.Builder) 359 for i := 0; i < b.N; i++ { 360 b.StopTimer() 361 out.Reset() 362 b.StartTimer() 363 // big-file.root is: rtests.XrdRemote("testdata/SMHiggsToZZTo4L.root") 364 err := rcmd.Dump(out, "../testdata/big-file.root", deep, nil) 365 if err != nil { 366 b.Fatal(err) 367 } 368 } 369 }