go-hep.org/x/hep@v0.38.1/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 test := test 237 file := test.file 238 if file == "" { 239 file = "../testdata/" + strings.ToLower(test.name) + ".dat" 240 } 241 t.Run("read-buffer="+file, func(t *testing.T) { 242 testReadRBuffer(t, test.name, file, test.want) 243 }) 244 } 245 } 246 247 func testReadRBuffer(t *testing.T, name, file string, want any) { 248 data, err := os.ReadFile(file) 249 if err != nil { 250 t.Fatal(err) 251 } 252 253 r := rbytes.NewRBuffer(data, nil, 0, nil) 254 obj := rtypes.Factory.Get(name)().Interface().(rbytes.Unmarshaler) 255 err = obj.UnmarshalROOT(r) 256 if err != nil { 257 t.Fatal(err) 258 } 259 260 if !reflect.DeepEqual(obj, want) { 261 t.Fatalf("error: %q\ngot= %#v\nwant=%#v\n", file, obj, want) 262 } 263 } 264 265 var rwBufferCases = []struct { 266 name string 267 file string 268 want rbytes.Unmarshaler 269 }{ 270 { 271 name: "TObject", 272 file: "../testdata/tobject.dat", 273 want: &Object{ID: 0x0, Bits: 0x3000000}, 274 }, 275 { 276 name: "TNamed", 277 file: "../testdata/tnamed.dat", 278 want: &Named{obj: Object{ID: 0x0, Bits: 0x3000000}, name: "my-name", title: "my-title"}, 279 }, 280 { 281 name: "TNamed", 282 file: "../testdata/tnamed-cmssw.dat", 283 want: &Named{ 284 obj: Object{ID: 0x0, Bits: 0x3000000}, 285 name: "edmTriggerResults_TriggerResults__HLT.present", title: "edmTriggerResults_TriggerResults__HLT.present", 286 }, 287 }, 288 { 289 name: "TNamed", 290 file: "../testdata/tnamed-cmssw-2.dat", 291 want: &Named{ 292 obj: Object{ID: 0x0, Bits: 0x3500000}, 293 name: "edmTriggerResults_TriggerResults__HLT.present", title: "edmTriggerResults_TriggerResults__HLT.present", 294 }, 295 }, 296 { 297 name: "TNamed", 298 file: "../testdata/tnamed-long-string.dat", 299 want: &Named{ 300 obj: Object{ID: 0x0, Bits: 0x3000000}, 301 name: strings.Repeat("*", 256), 302 title: "my-title", 303 }, 304 }, 305 { 306 name: "TObjString", 307 file: "../testdata/tobjstring.dat", 308 want: &ObjString{ 309 obj: Object{ID: 0x0, Bits: 0x3000008}, 310 str: "tobjstring-string", 311 }, 312 }, 313 } 314 315 func TestUUIDv1(t *testing.T) { 316 uuid := UUID([16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}) 317 wbuf := rbytes.NewWBuffer(nil, nil, 0, nil) 318 _, err := wbuf.Write(uuid[:]) 319 if err != nil { 320 t.Fatalf("could not serialize v1: %+v", err) 321 } 322 323 var ( 324 got UUID 325 want = uuid 326 ) 327 rbuf := rbytes.NewRBuffer(wbuf.Bytes(), nil, 0, nil) 328 err = got.UnmarshalROOTv1(rbuf) 329 if err != nil { 330 t.Fatalf("could not unserialize v1: %+v", err) 331 } 332 333 if !reflect.DeepEqual(got, want) { 334 t.Fatalf("invalid UUID-v1 round-trip:\ngot= %v\nwant=%v\n", got, want) 335 } 336 }