go-hep.org/x/hep@v0.40.0/groot/rbase/rw_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 rbase 6 7 import ( 8 "io" 9 "os" 10 "reflect" 11 "strings" 12 "testing" 13 "time" 14 15 "go-hep.org/x/hep/groot/internal/rtests" 16 "go-hep.org/x/hep/groot/rbytes" 17 "go-hep.org/x/hep/groot/rtypes" 18 ) 19 20 func TestWRBuffer(t *testing.T) { 21 for _, tc := range []struct { 22 name string 23 want rtests.ROOTer 24 }{ 25 { 26 name: "TObject", 27 want: &Object{ID: 0x0, Bits: 0x3000000}, 28 }, 29 { 30 name: "TObject", 31 want: &Object{ID: 0x1, Bits: 0x3000001}, 32 }, 33 { 34 name: "TUUID", 35 want: &UUID{ 36 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 37 10, 11, 12, 13, 14, 15, 38 }, 39 }, 40 { 41 name: "TNamed", 42 want: &Named{obj: Object{ID: 0x0, Bits: 0x3000000}, name: "my-name", title: "my-title"}, 43 }, 44 { 45 name: "TNamed", 46 want: &Named{ 47 obj: Object{ID: 0x0, Bits: 0x3000000}, 48 name: "edmTriggerResults_TriggerResults__HLT.present", title: "edmTriggerResults_TriggerResults__HLT.present", 49 }, 50 }, 51 { 52 name: "TNamed", 53 want: &Named{ 54 obj: Object{ID: 0x0, Bits: 0x3500000}, 55 name: "edmTriggerResults_TriggerResults__HLT.present", title: "edmTriggerResults_TriggerResults__HLT.present", 56 }, 57 }, 58 { 59 name: "TNamed", 60 want: &Named{ 61 obj: Object{ID: 0x0, Bits: 0x3000000}, 62 name: strings.Repeat("*", 256), 63 title: "my-title", 64 }, 65 }, 66 { 67 name: "TObjString", 68 want: &ObjString{ 69 obj: Object{ID: 0x0, Bits: 0x3000008}, 70 str: "tobjstring-string", 71 }, 72 }, 73 { 74 name: "GoString", 75 want: NewString("go-string"), 76 }, 77 { 78 name: "GoString-empty", 79 want: NewString(""), 80 }, 81 { 82 name: "GoString-large", 83 want: NewString(strings.Repeat("*", 1024)), // len(str) > 255 84 }, 85 { 86 name: "TProcessID", 87 want: &ProcessID{ 88 named: Named{obj: Object{ID: 0x0, Bits: 0x3000000}, name: "my-name", title: "my-title"}, 89 }, 90 }, 91 { 92 name: "TRef", 93 want: &Ref{ 94 obj: Object{ID: 0x0, Bits: 0x3000000}, 95 }, 96 }, 97 { 98 name: "TDatime", 99 want: func() *Datime { 100 dt := Datime(time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)) 101 return &dt 102 }(), 103 }, 104 { 105 name: "TAttPad", 106 want: &AttPad{ 107 fLeftMargin: 1, 108 fRightMargin: 2, 109 fBottomMargin: 3, 110 fTopMargin: 4, 111 fXfile: 5, 112 fYfile: 6, 113 fAfile: 7, 114 fXstat: 8, 115 fYstat: 9, 116 fAstat: 10, 117 fFrameFillColor: 11, 118 fFrameLineColor: 12, 119 fFrameFillStyle: 13, 120 fFrameLineStyle: 14, 121 fFrameLineWidth: 15, 122 fFrameBorderSize: 16, 123 fFrameBorderMode: 17, 124 }, 125 }, 126 } { 127 t.Run(tc.name, func(t *testing.T) { 128 { 129 wbuf := rbytes.NewWBuffer(nil, nil, 0, nil) 130 wbuf.SetErr(io.EOF) 131 _, err := tc.want.MarshalROOT(wbuf) 132 if err == nil { 133 t.Fatalf("expected an error") 134 } 135 if err != io.EOF { 136 t.Fatalf("got=%v, want=%v", err, io.EOF) 137 } 138 } 139 wbuf := rbytes.NewWBuffer(nil, nil, 0, nil) 140 _, err := tc.want.MarshalROOT(wbuf) 141 if err != nil { 142 t.Fatalf("could not marshal ROOT: %v", err) 143 } 144 145 rbuf := rbytes.NewRBuffer(wbuf.Bytes(), nil, 0, nil) 146 class := tc.want.Class() 147 obj := rtypes.Factory.Get(class)().Interface().(rbytes.Unmarshaler) 148 { 149 rbuf.SetErr(io.EOF) 150 err = obj.UnmarshalROOT(rbuf) 151 if err == nil { 152 t.Fatalf("expected an error") 153 } 154 if err != io.EOF { 155 t.Fatalf("got=%v, want=%v", err, io.EOF) 156 } 157 rbuf.SetErr(nil) 158 } 159 err = obj.UnmarshalROOT(rbuf) 160 if err != nil { 161 t.Fatalf("could not unmarshal ROOT: %v", err) 162 } 163 164 if !reflect.DeepEqual(obj, tc.want) { 165 t.Fatalf("error\ngot= %+v (%T)\nwant=%+v (%T)\n", obj, obj, tc.want, tc.want) 166 } 167 }) 168 } 169 } 170 171 func TestWriteWBuffer(t *testing.T) { 172 for _, test := range rwBufferCases { 173 t.Run("write-buffer="+test.file, func(t *testing.T) { 174 testWriteWBuffer(t, test.name, test.file, test.want) 175 }) 176 } 177 } 178 179 func testWriteWBuffer(t *testing.T, name, file string, want any) { 180 rdata, err := os.ReadFile(file) 181 if err != nil { 182 t.Fatal(err) 183 } 184 185 { 186 wbuf := rbytes.NewWBuffer(nil, nil, 0, nil) 187 wbuf.SetErr(io.EOF) 188 _, err := want.(rbytes.Marshaler).MarshalROOT(wbuf) 189 if err == nil { 190 t.Fatalf("expected an error") 191 } 192 if err != io.EOF { 193 t.Fatalf("got=%v, want=%v", err, io.EOF) 194 } 195 } 196 197 w := rbytes.NewWBuffer(nil, nil, 0, nil) 198 _, err = want.(rbytes.Marshaler).MarshalROOT(w) 199 if err != nil { 200 t.Fatal(err) 201 } 202 wdata := w.Bytes() 203 204 r := rbytes.NewRBuffer(wdata, nil, 0, nil) 205 obj := rtypes.Factory.Get(name)().Interface().(rbytes.Unmarshaler) 206 { 207 r.SetErr(io.EOF) 208 err = obj.UnmarshalROOT(r) 209 if err == nil { 210 t.Fatalf("expected an error") 211 } 212 if err != io.EOF { 213 t.Fatalf("got=%v, want=%v", err, io.EOF) 214 } 215 r.SetErr(nil) 216 } 217 err = obj.UnmarshalROOT(r) 218 if err != nil { 219 t.Fatal(err) 220 } 221 222 err = os.WriteFile(file+".new", wdata, 0644) 223 if err != nil { 224 t.Fatal(err) 225 } 226 227 if !reflect.DeepEqual(obj, want) { 228 t.Fatalf("error: %q\ngot= %+v\nwant=%+v\ngot= %+v\nwant=%+v", file, wdata, rdata, obj, want) 229 } 230 231 os.Remove(file + ".new") 232 } 233 234 func TestReadRBuffer(t *testing.T) { 235 for _, test := range rwBufferCases { 236 file := test.file 237 if file == "" { 238 file = "../testdata/" + strings.ToLower(test.name) + ".dat" 239 } 240 t.Run("read-buffer="+file, func(t *testing.T) { 241 testReadRBuffer(t, test.name, file, test.want) 242 }) 243 } 244 } 245 246 func testReadRBuffer(t *testing.T, name, file string, want any) { 247 data, err := os.ReadFile(file) 248 if err != nil { 249 t.Fatal(err) 250 } 251 252 r := rbytes.NewRBuffer(data, nil, 0, nil) 253 obj := rtypes.Factory.Get(name)().Interface().(rbytes.Unmarshaler) 254 err = obj.UnmarshalROOT(r) 255 if err != nil { 256 t.Fatal(err) 257 } 258 259 if !reflect.DeepEqual(obj, want) { 260 t.Fatalf("error: %q\ngot= %#v\nwant=%#v\n", file, obj, want) 261 } 262 } 263 264 var rwBufferCases = []struct { 265 name string 266 file string 267 want rbytes.Unmarshaler 268 }{ 269 { 270 name: "TObject", 271 file: "../testdata/tobject.dat", 272 want: &Object{ID: 0x0, Bits: 0x3000000}, 273 }, 274 { 275 name: "TNamed", 276 file: "../testdata/tnamed.dat", 277 want: &Named{obj: Object{ID: 0x0, Bits: 0x3000000}, name: "my-name", title: "my-title"}, 278 }, 279 { 280 name: "TNamed", 281 file: "../testdata/tnamed-cmssw.dat", 282 want: &Named{ 283 obj: Object{ID: 0x0, Bits: 0x3000000}, 284 name: "edmTriggerResults_TriggerResults__HLT.present", title: "edmTriggerResults_TriggerResults__HLT.present", 285 }, 286 }, 287 { 288 name: "TNamed", 289 file: "../testdata/tnamed-cmssw-2.dat", 290 want: &Named{ 291 obj: Object{ID: 0x0, Bits: 0x3500000}, 292 name: "edmTriggerResults_TriggerResults__HLT.present", title: "edmTriggerResults_TriggerResults__HLT.present", 293 }, 294 }, 295 { 296 name: "TNamed", 297 file: "../testdata/tnamed-long-string.dat", 298 want: &Named{ 299 obj: Object{ID: 0x0, Bits: 0x3000000}, 300 name: strings.Repeat("*", 256), 301 title: "my-title", 302 }, 303 }, 304 { 305 name: "TObjString", 306 file: "../testdata/tobjstring.dat", 307 want: &ObjString{ 308 obj: Object{ID: 0x0, Bits: 0x3000008}, 309 str: "tobjstring-string", 310 }, 311 }, 312 } 313 314 func TestUUIDv1(t *testing.T) { 315 uuid := UUID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) 316 wbuf := rbytes.NewWBuffer(nil, nil, 0, nil) 317 _, err := wbuf.Write(uuid[:]) 318 if err != nil { 319 t.Fatalf("could not serialize v1: %+v", err) 320 } 321 322 var ( 323 got UUID 324 want = uuid 325 ) 326 rbuf := rbytes.NewRBuffer(wbuf.Bytes(), nil, 0, nil) 327 err = got.UnmarshalROOTv1(rbuf) 328 if err != nil { 329 t.Fatalf("could not unserialize v1: %+v", err) 330 } 331 332 if !reflect.DeepEqual(got, want) { 333 t.Fatalf("invalid UUID-v1 round-trip:\ngot= %v\nwant=%v\n", got, want) 334 } 335 }