go-hep.org/x/hep@v0.38.1/rio/rio_test.go (about) 1 // Copyright ©2015 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 rio 6 7 import ( 8 "bytes" 9 "compress/flate" 10 "encoding/binary" 11 "encoding/gob" 12 "fmt" 13 "io" 14 "reflect" 15 "testing" 16 ) 17 18 func TestOptions(t *testing.T) { 19 for _, kind := range []struct { 20 kind CompressorKind 21 want CompressorKind 22 }{ 23 {CompressDefault, CompressZlib}, 24 {CompressNone, CompressNone}, 25 {CompressZlib, CompressZlib}, 26 {CompressGzip, CompressGzip}, 27 } { 28 for _, level := range []int{flate.DefaultCompression, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9} { 29 for _, codec := range []int{0, 1, 2} { 30 o := NewOptions(kind.kind, level, codec) 31 if o.CompressorKind() != kind.want { 32 t.Errorf("invalid CompressorKind. want=%v. got=%v", 33 kind.want, o.CompressorKind(), 34 ) 35 } 36 if o.CompressorLevel() != level { 37 t.Errorf("invalid CompressorLevel. want=%v. got=%v", 38 level, o.CompressorLevel(), 39 ) 40 } 41 if o.CompressorCodec() != codec { 42 t.Errorf("invalid CompressorCodec. want=%v. got=%v", 43 codec, o.CompressorCodec(), 44 ) 45 } 46 } 47 } 48 } 49 } 50 51 func TestEmptyRWRecord(t *testing.T) { 52 wrec := rioRecord{ 53 Header: rioHeader{ 54 Len: 1, 55 Frame: recFrame, 56 }, 57 Options: 2, 58 CLen: 3, 59 XLen: 4, 60 Name: "rio-record", 61 } 62 63 buf := new(bytes.Buffer) 64 65 err := gob.NewEncoder(buf).Encode(&wrec) 66 if err != nil { 67 t.Fatalf("error encoding record: %v\n", err) 68 } 69 70 var rrec rioRecord 71 err = gob.NewDecoder(buf).Decode(&rrec) 72 if err != nil { 73 t.Fatalf("error decoding record: %v\n", err) 74 } 75 76 size := rioAlign(buf.Len()) 77 if size != buf.Len() { 78 t.Fatalf("buffer not 4-byte aligned. want=%d. got=%d\n", 79 size, buf.Len(), 80 ) 81 } 82 83 if !reflect.DeepEqual(wrec, rrec) { 84 t.Fatalf("error:\nwrec=%#v\nrrec=%#v\n", wrec, rrec) 85 } 86 } 87 88 func TestReader(t *testing.T) { 89 90 { 91 rbuf := bytes.NewReader(rioMagic[:]) 92 r, err := NewReader(rbuf) 93 if err != nil || r == nil { 94 t.Fatalf("error creating new rio Reader: %v", err) 95 } 96 } 97 { 98 rbuf := new(bytes.Buffer) 99 r, err := NewReader(rbuf) 100 if err == nil || r != nil { 101 t.Fatalf("NewReader should have failed") 102 } 103 } 104 } 105 106 func TestRW(t *testing.T) { 107 const nmax = 100 108 makeles := func(i int) []electron { 109 eles := make([]electron, 0, nmax) 110 for range nmax { 111 eles = append( 112 eles, 113 electron{[4]float64{float64(i), float64(i + 1), float64(i + 2), float64(i + 3)}}, 114 ) 115 } 116 return eles 117 } 118 makemuons := func(i int) []muon { 119 muons := make([]muon, 0, nmax) 120 for range nmax { 121 muons = append( 122 muons, 123 muon{[4]float64{float64(-i), float64(-i - 1), float64(-i - 2), float64(-i - 3)}}, 124 ) 125 } 126 return muons 127 } 128 129 for ii, test := range []struct { 130 lvl int 131 ckind CompressorKind 132 }{ 133 { 134 lvl: 0, 135 ckind: CompressNone, 136 }, 137 { 138 lvl: 1, 139 ckind: CompressNone, 140 }, 141 142 // flate 143 { 144 lvl: flate.NoCompression, 145 ckind: CompressFlate, 146 }, 147 { 148 lvl: flate.DefaultCompression, 149 ckind: CompressFlate, 150 }, 151 { 152 lvl: flate.BestCompression, 153 ckind: CompressFlate, 154 }, 155 { 156 lvl: flate.BestSpeed, 157 ckind: CompressFlate, 158 }, 159 160 // zlib 161 { 162 lvl: flate.NoCompression, 163 ckind: CompressZlib, 164 }, 165 { 166 lvl: flate.DefaultCompression, 167 ckind: CompressZlib, 168 }, 169 { 170 lvl: flate.BestCompression, 171 ckind: CompressZlib, 172 }, 173 { 174 lvl: flate.BestSpeed, 175 ckind: CompressZlib, 176 }, 177 178 // gzip 179 { 180 lvl: flate.NoCompression, 181 ckind: CompressGzip, 182 }, 183 { 184 lvl: flate.DefaultCompression, 185 ckind: CompressGzip, 186 }, 187 { 188 lvl: flate.BestCompression, 189 ckind: CompressGzip, 190 }, 191 { 192 lvl: flate.BestSpeed, 193 ckind: CompressGzip, 194 }, 195 } { 196 wbuf := new(bytes.Buffer) 197 w, err := NewWriter(wbuf) 198 if w == nil || err != nil { 199 t.Fatalf("test[%d]: error creating new rio Writer: %v", ii, err) 200 } 201 202 err = w.SetCompressor(test.ckind, test.lvl) 203 if err != nil { 204 t.Fatalf("test[%d]: error setting compressor (%#v): %v", ii, test, err) 205 } 206 207 wrec := w.Record("data") 208 err = wrec.Connect("event", &event{}) 209 if err != nil { 210 t.Fatalf("test[%d]: error connecting block: %v", ii, err) 211 } 212 wblk := wrec.Block("event") 213 214 for i := range nmax { 215 data := event{ 216 runnbr: int64(i), 217 evtnbr: int64(1000 + i), 218 id: fmt.Sprintf("id-%04d", i), 219 eles: makeles(i), 220 muons: makemuons(i), 221 } 222 if wblk.raw.Version != data.RioVersion() { 223 t.Fatalf("test[%d]: error rio-version. want=%d. got=%d", ii, data.RioVersion(), wblk.raw.Version) 224 } 225 226 err := wblk.Write(&data) 227 if err != nil { 228 t.Fatalf("test[%d]: error writing data[%d]: %v\n", ii, i, err) 229 } 230 231 err = wrec.Write() 232 if err != nil { 233 t.Fatalf("test[%d]: error writing record[%d]: %v\n", ii, i, err) 234 } 235 } 236 err = w.Close() 237 if err != nil { 238 t.Fatalf("test[%d]: error closing writer: %v\n", ii, err) 239 } 240 241 // fmt.Printf("::: kind: %7q lvl: %2d: size=%8d\n", test.ckind, test.lvl, wbuf.Len()) 242 243 r, err := NewReader(wbuf) 244 if err != nil { 245 t.Fatalf("test[%d]: error creating new rio Reader: %v", ii, err) 246 } 247 248 rrec := r.Record("data") 249 err = rrec.Connect("event", &event{}) 250 if err != nil { 251 t.Fatalf("test[%d]: error connecting block: %v", ii, err) 252 } 253 rblk := rrec.Block("event") 254 255 for i := range nmax { 256 err := rrec.Read() 257 if err != nil { 258 t.Fatalf("test[%d]: error loading record[%d]: %v\nbuf: %v\nraw: %#v\n", ii, i, err, 259 wbuf.Bytes(), 260 rblk.raw, 261 ) 262 } 263 264 var data event 265 err = rblk.Read(&data) 266 if err != nil { 267 t.Fatalf("test[%d]: error reading data[%d]: %v\n", ii, i, err) 268 } 269 270 if rblk.raw.Version != data.RioVersion() { 271 t.Fatalf("test[%d]: error rio-version. want=%d. got=%d", ii, data.RioVersion(), rblk.raw.Version) 272 } 273 274 want := event{ 275 runnbr: int64(i), 276 evtnbr: int64(1000 + i), 277 id: fmt.Sprintf("id-%04d", i), 278 eles: makeles(i), 279 muons: makemuons(i), 280 } 281 282 if !reflect.DeepEqual(data, want) { 283 t.Fatalf("test[%d]: error data[%d].\nwant=%#v\ngot =%#v\n", ii, i, want, data) 284 } 285 } 286 287 err = r.Close() 288 if err != nil { 289 t.Fatalf("test[%d]: error closing reading: %v\n", ii, err) 290 } 291 } 292 } 293 294 // event holds data to be serialized 295 type event struct { 296 runnbr int64 297 evtnbr int64 298 id string 299 eles []electron 300 muons []muon 301 } 302 303 func (evt *event) RioMarshal(w io.Writer) error { 304 err := binary.Write(w, Endian, evt.runnbr) 305 if err != nil { 306 return err 307 } 308 309 err = binary.Write(w, Endian, evt.evtnbr) 310 if err != nil { 311 return err 312 } 313 314 err = binary.Write(w, Endian, int64(len(evt.eles))) 315 if err != nil { 316 return err 317 } 318 for _, ele := range evt.eles { 319 err = ele.RioMarshal(w) 320 if err != nil { 321 return err 322 } 323 } 324 325 err = binary.Write(w, Endian, int64(len(evt.muons))) 326 if err != nil { 327 return err 328 } 329 for _, muon := range evt.muons { 330 err = muon.RioMarshal(w) 331 if err != nil { 332 return err 333 } 334 } 335 336 err = binary.Write(w, Endian, int64(len(evt.id))) 337 if err != nil { 338 return err 339 } 340 341 err = binary.Write(w, Endian, []byte(evt.id)) 342 if err != nil { 343 return err 344 } 345 346 return err 347 } 348 349 func (evt *event) RioUnmarshal(r io.Reader) error { 350 err := binary.Read(r, Endian, &evt.runnbr) 351 if err != nil { 352 return err 353 } 354 355 err = binary.Read(r, Endian, &evt.evtnbr) 356 if err != nil { 357 return err 358 } 359 360 neles := int64(0) 361 err = binary.Read(r, Endian, &neles) 362 if err != nil { 363 return err 364 } 365 366 evt.eles = make([]electron, int(neles)) 367 for i := range evt.eles { 368 ele := &evt.eles[i] 369 err = ele.RioUnmarshal(r) 370 if err != nil { 371 return err 372 } 373 } 374 375 nmuons := int64(0) 376 err = binary.Read(r, Endian, &nmuons) 377 if err != nil { 378 return err 379 } 380 381 evt.muons = make([]muon, int(nmuons)) 382 for i := range evt.muons { 383 muon := &evt.muons[i] 384 err = muon.RioUnmarshal(r) 385 if err != nil { 386 return err 387 } 388 } 389 390 var nid int64 391 err = binary.Read(r, Endian, &nid) 392 if err != nil { 393 return err 394 } 395 396 bid := make([]byte, int(nid)) 397 err = binary.Read(r, Endian, &bid) 398 if err != nil { 399 return err 400 } 401 evt.id = string(bid) 402 403 return err 404 } 405 406 func (evt *event) RioVersion() Version { 407 return Version(42) 408 } 409 410 type electron struct { 411 p4 [4]float64 412 } 413 414 func newElectron(px, py, pz, e float64) electron { 415 return electron{[4]float64{px, py, pz, e}} 416 } 417 418 func (ele *electron) RioMarshal(w io.Writer) error { 419 return binary.Write(w, Endian, ele.p4) 420 } 421 422 func (ele *electron) RioUnmarshal(r io.Reader) error { 423 return binary.Read(r, Endian, &ele.p4) 424 } 425 426 type muon struct { 427 p4 [4]float64 428 } 429 430 func newMuon(px, py, pz, e float64) muon { 431 return muon{[4]float64{px, py, pz, e}} 432 } 433 434 func (muon *muon) RioMarshal(w io.Writer) error { 435 return binary.Write(w, Endian, muon.p4) 436 } 437 438 func (muon *muon) RioUnmarshal(r io.Reader) error { 439 return binary.Read(r, Endian, &muon.p4) 440 }