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  }