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  }