go-hep.org/x/hep@v0.38.1/groot/rbytes/wbuffer_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 rbytes
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"reflect"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  func TestWBufferGrow(t *testing.T) {
    16  	buf := new(WBuffer)
    17  	if len(buf.w.p) != 0 {
    18  		t.Fatalf("got=%d, want 0-size buffer", len(buf.w.p))
    19  	}
    20  
    21  	buf.w.grow(8)
    22  	if got, want := len(buf.w.p), 8; got != want {
    23  		t.Fatalf("got=%d, want=%d buffer len-size", got, want)
    24  	}
    25  
    26  	buf.w.grow(8)
    27  	if got, want := len(buf.w.p), 2*8; got != want {
    28  		t.Fatalf("got=%d, want=%d buffer len-size", got, want)
    29  	}
    30  
    31  	buf.w.grow(1)
    32  	if got, want := len(buf.w.p), 2*8+1; got != want {
    33  		t.Fatalf("got=%d, want=%d buffer len-size", got, want)
    34  	}
    35  
    36  	buf.w.grow(0)
    37  	if got, want := len(buf.w.p), 2*8+1; got != want {
    38  		t.Fatalf("got=%d, want=%d buffer len-size", got, want)
    39  	}
    40  	if got, want := cap(buf.w.p), 8*1024; got != want {
    41  		t.Fatalf("got=%d, want=%d buffer cap-size", got, want)
    42  	}
    43  
    44  	const n = 10 * 1024
    45  	buf.w.grow(n)
    46  	if got, want := len(buf.w.p), 2*8+1+n; got != want {
    47  		t.Fatalf("got=%d, want=%d buffer len-size", got, want)
    48  	}
    49  	if got, want := cap(buf.w.p), 8*4*1024; got != want {
    50  		t.Fatalf("got=%d, want=%d buffer cap-size", got, want)
    51  	}
    52  
    53  	defer func() {
    54  		e := recover()
    55  		if e == nil {
    56  			t.Fatalf("expected a panic")
    57  		}
    58  	}()
    59  
    60  	buf.w.grow(-1)
    61  }
    62  
    63  func TestWBuffer_WriteBool(t *testing.T) {
    64  	wbuf := NewWBuffer(nil, nil, 0, nil)
    65  	want := true
    66  	wbuf.WriteBool(want)
    67  	rbuf := NewRBuffer(wbuf.w.p, nil, 0, nil)
    68  	got := rbuf.ReadBool()
    69  	if got != want {
    70  		t.Fatalf("Invalid value. got:%v, want:%v", got, want)
    71  	}
    72  }
    73  
    74  func TestWBuffer_WriteString(t *testing.T) {
    75  	for _, i := range []int{0, 1, 2, 8, 16, 32, 64, 128, 253, 254, 255, 256, 512} {
    76  		t.Run(fmt.Sprintf("str-%03d", i), func(t *testing.T) {
    77  			wbuf := NewWBuffer(nil, nil, 0, nil)
    78  			want := strings.Repeat("=", i)
    79  			wbuf.WriteString(want)
    80  			rbuf := NewRBuffer(wbuf.w.p, nil, 0, nil)
    81  			got := rbuf.ReadString()
    82  			if got != want {
    83  				t.Fatalf("Invalid value for len=%d.\ngot: %q\nwant:%q", i, got, want)
    84  			}
    85  		})
    86  	}
    87  }
    88  
    89  func TestWBuffer_WriteCString(t *testing.T) {
    90  	wbuf := NewWBuffer(nil, nil, 0, nil)
    91  	want := "hello"
    92  	cstr := string(append([]byte(want), 0))
    93  	wbuf.WriteCString(cstr)
    94  	rbuf := NewRBuffer(wbuf.w.p, nil, 0, nil)
    95  
    96  	got := rbuf.ReadCString(len(cstr))
    97  	if want != got {
    98  		t.Fatalf("got=%q, want=%q", got, want)
    99  	}
   100  }
   101  
   102  func TestWBufferEmpty(t *testing.T) {
   103  	wbuf := new(WBuffer)
   104  	wbuf.WriteString(string([]byte{1, 2, 3, 4, 5}))
   105  	if wbuf.Err() != nil {
   106  		t.Fatalf("err: %v, buf=%v", wbuf.Err(), wbuf.w.p)
   107  	}
   108  }
   109  
   110  func TestWBuffer_Write(t *testing.T) {
   111  	for _, tc := range []struct {
   112  		name string
   113  		want any
   114  		wfct func(*WBuffer, any)
   115  		rfct func(*RBuffer) any
   116  		cmp  func(a, b any) bool
   117  	}{
   118  		{
   119  			name: "bool-true",
   120  			want: true,
   121  			wfct: func(w *WBuffer, v any) {
   122  				w.WriteBool(v.(bool))
   123  			},
   124  			rfct: func(r *RBuffer) any {
   125  				return r.ReadBool()
   126  			},
   127  		},
   128  		{
   129  			name: "bool-false",
   130  			want: false,
   131  			wfct: func(w *WBuffer, v any) {
   132  				w.WriteBool(v.(bool))
   133  			},
   134  			rfct: func(r *RBuffer) any {
   135  				return r.ReadBool()
   136  			},
   137  		},
   138  		{
   139  			name: "int8",
   140  			want: int8(42),
   141  			wfct: func(w *WBuffer, v any) {
   142  				w.WriteI8(v.(int8))
   143  			},
   144  			rfct: func(r *RBuffer) any {
   145  				return r.ReadI8()
   146  			},
   147  		},
   148  		{
   149  			name: "int16",
   150  			want: int16(42),
   151  			wfct: func(w *WBuffer, v any) {
   152  				w.WriteI16(v.(int16))
   153  			},
   154  			rfct: func(r *RBuffer) any {
   155  				return r.ReadI16()
   156  			},
   157  		},
   158  		{
   159  			name: "int32",
   160  			want: int32(42),
   161  			wfct: func(w *WBuffer, v any) {
   162  				w.WriteI32(v.(int32))
   163  			},
   164  			rfct: func(r *RBuffer) any {
   165  				return r.ReadI32()
   166  			},
   167  		},
   168  		{
   169  			name: "int64",
   170  			want: int64(42),
   171  			wfct: func(w *WBuffer, v any) {
   172  				w.WriteI64(v.(int64))
   173  			},
   174  			rfct: func(r *RBuffer) any {
   175  				return r.ReadI64()
   176  			},
   177  		},
   178  		{
   179  			name: "uint8",
   180  			want: uint8(42),
   181  			wfct: func(w *WBuffer, v any) {
   182  				w.WriteU8(v.(uint8))
   183  			},
   184  			rfct: func(r *RBuffer) any {
   185  				return r.ReadU8()
   186  			},
   187  		},
   188  		{
   189  			name: "uint16",
   190  			want: uint16(42),
   191  			wfct: func(w *WBuffer, v any) {
   192  				w.WriteU16(v.(uint16))
   193  			},
   194  			rfct: func(r *RBuffer) any {
   195  				return r.ReadU16()
   196  			},
   197  		},
   198  		{
   199  			name: "uint32",
   200  			want: uint32(42),
   201  			wfct: func(w *WBuffer, v any) {
   202  				w.WriteU32(v.(uint32))
   203  			},
   204  			rfct: func(r *RBuffer) any {
   205  				return r.ReadU32()
   206  			},
   207  		},
   208  		{
   209  			name: "uint64",
   210  			want: uint64(42),
   211  			wfct: func(w *WBuffer, v any) {
   212  				w.WriteU64(v.(uint64))
   213  			},
   214  			rfct: func(r *RBuffer) any {
   215  				return r.ReadU64()
   216  			},
   217  		},
   218  		{
   219  			name: "float32",
   220  			want: float32(42),
   221  			wfct: func(w *WBuffer, v any) {
   222  				w.WriteF32(v.(float32))
   223  			},
   224  			rfct: func(r *RBuffer) any {
   225  				return r.ReadF32()
   226  			},
   227  		},
   228  		{
   229  			name: "float32-nan",
   230  			want: float32(math.NaN()),
   231  			wfct: func(w *WBuffer, v any) {
   232  				w.WriteF32(v.(float32))
   233  			},
   234  			rfct: func(r *RBuffer) any {
   235  				return r.ReadF32()
   236  			},
   237  			cmp: func(a, b any) bool {
   238  				return math.IsNaN(float64(a.(float32))) && math.IsNaN(float64(b.(float32)))
   239  			},
   240  		},
   241  		{
   242  			name: "float32-inf",
   243  			want: float32(math.Inf(-1)),
   244  			wfct: func(w *WBuffer, v any) {
   245  				w.WriteF32(v.(float32))
   246  			},
   247  			rfct: func(r *RBuffer) any {
   248  				return r.ReadF32()
   249  			},
   250  			cmp: func(a, b any) bool {
   251  				return math.IsInf(float64(a.(float32)), -1) && math.IsInf(float64(b.(float32)), -1)
   252  			},
   253  		},
   254  		{
   255  			name: "float32+inf",
   256  			want: float32(math.Inf(+1)),
   257  			wfct: func(w *WBuffer, v any) {
   258  				w.WriteF32(v.(float32))
   259  			},
   260  			rfct: func(r *RBuffer) any {
   261  				return r.ReadF32()
   262  			},
   263  			cmp: func(a, b any) bool {
   264  				return math.IsInf(float64(a.(float32)), +1) && math.IsInf(float64(b.(float32)), +1)
   265  			},
   266  		},
   267  		{
   268  			name: "float64",
   269  			want: float64(42),
   270  			wfct: func(w *WBuffer, v any) {
   271  				w.WriteF64(v.(float64))
   272  			},
   273  			rfct: func(r *RBuffer) any {
   274  				return r.ReadF64()
   275  			},
   276  		},
   277  		{
   278  			name: "float64-nan",
   279  			want: math.NaN(),
   280  			wfct: func(w *WBuffer, v any) {
   281  				w.WriteF64(v.(float64))
   282  			},
   283  			rfct: func(r *RBuffer) any {
   284  				return r.ReadF64()
   285  			},
   286  			cmp: func(a, b any) bool {
   287  				return math.IsNaN(a.(float64)) && math.IsNaN(b.(float64))
   288  			},
   289  		},
   290  		{
   291  			name: "float64-inf",
   292  			want: math.Inf(-1),
   293  			wfct: func(w *WBuffer, v any) {
   294  				w.WriteF64(v.(float64))
   295  			},
   296  			rfct: func(r *RBuffer) any {
   297  				return r.ReadF64()
   298  			},
   299  			cmp: func(a, b any) bool {
   300  				return math.IsInf(a.(float64), -1) && math.IsInf(b.(float64), -1)
   301  			},
   302  		},
   303  		{
   304  			name: "float64+inf",
   305  			want: math.Inf(+1),
   306  			wfct: func(w *WBuffer, v any) {
   307  				w.WriteF64(v.(float64))
   308  			},
   309  			rfct: func(r *RBuffer) any {
   310  				return r.ReadF64()
   311  			},
   312  			cmp: func(a, b any) bool {
   313  				return math.IsInf(a.(float64), +1) && math.IsInf(b.(float64), +1)
   314  			},
   315  		},
   316  		{
   317  			name: "cstring-1",
   318  			want: "hello world",
   319  			wfct: func(w *WBuffer, v any) {
   320  				w.WriteCString(v.(string))
   321  			},
   322  			rfct: func(r *RBuffer) any {
   323  				return r.ReadCString(len("hello world"))
   324  			},
   325  		},
   326  		{
   327  			name: "cstring-2",
   328  			want: "hello world",
   329  			wfct: func(w *WBuffer, v any) {
   330  				w.WriteCString(v.(string))
   331  			},
   332  			rfct: func(r *RBuffer) any {
   333  				return r.ReadCString(len("hello world") + 1)
   334  			},
   335  		},
   336  		{
   337  			name: "cstring-3",
   338  			want: "hello world",
   339  			wfct: func(w *WBuffer, v any) {
   340  				w.WriteCString(v.(string))
   341  			},
   342  			rfct: func(r *RBuffer) any {
   343  				return r.ReadCString(len("hello world") + 10)
   344  			},
   345  		},
   346  		{
   347  			name: "cstring-4",
   348  			want: "hello",
   349  			wfct: func(w *WBuffer, v any) {
   350  				w.WriteCString(v.(string))
   351  			},
   352  			rfct: func(r *RBuffer) any {
   353  				return r.ReadCString(len("hello"))
   354  			},
   355  		},
   356  		{
   357  			name: "cstring-5",
   358  			want: string([]byte{1, 2, 3, 4}),
   359  			wfct: func(w *WBuffer, v any) {
   360  				w.WriteCString(v.(string))
   361  			},
   362  			rfct: func(r *RBuffer) any {
   363  				return r.ReadCString(len([]byte{1, 2, 3, 4, 0, 1}))
   364  			},
   365  		},
   366  		{
   367  			name: "std::string-1",
   368  			want: "hello",
   369  			wfct: func(w *WBuffer, v any) {
   370  				w.WriteStdString(v.(string))
   371  			},
   372  			rfct: func(r *RBuffer) any {
   373  				return r.ReadStdString()
   374  			},
   375  		},
   376  		{
   377  			name: "std::string-2",
   378  			want: strings.Repeat("hello", 256),
   379  			wfct: func(w *WBuffer, v any) {
   380  				w.WriteStdString(v.(string))
   381  			},
   382  			rfct: func(r *RBuffer) any {
   383  				return r.ReadStdString()
   384  			},
   385  		},
   386  		{
   387  			name: "static-arr-i32",
   388  			want: []int32{1, 2, 0, 2, 1},
   389  			wfct: func(w *WBuffer, v any) {
   390  				w.WriteStaticArrayI32(v.([]int32))
   391  			},
   392  			rfct: func(r *RBuffer) any {
   393  				return r.ReadStaticArrayI32()
   394  			},
   395  		},
   396  		{
   397  			name: "fast-arr-bool",
   398  			want: []bool{true, false, false, true, false},
   399  			wfct: func(w *WBuffer, v any) {
   400  				w.WriteArrayBool(v.([]bool))
   401  			},
   402  			rfct: func(r *RBuffer) any {
   403  				sli := make([]bool, 5)
   404  				r.ReadArrayBool(sli)
   405  				return sli
   406  			},
   407  		},
   408  		{
   409  			name: "fast-arr-i8",
   410  			want: []int8{1, 2, 0, 2, 1},
   411  			wfct: func(w *WBuffer, v any) {
   412  				w.WriteArrayI8(v.([]int8))
   413  			},
   414  			rfct: func(r *RBuffer) any {
   415  				sli := make([]int8, 5)
   416  				r.ReadArrayI8(sli)
   417  				return sli
   418  			},
   419  		},
   420  		{
   421  			name: "fast-arr-i16",
   422  			want: []int16{1, 2, 0, 2, 1},
   423  			wfct: func(w *WBuffer, v any) {
   424  				w.WriteArrayI16(v.([]int16))
   425  			},
   426  			rfct: func(r *RBuffer) any {
   427  				sli := make([]int16, 5)
   428  				r.ReadArrayI16(sli)
   429  				return sli
   430  			},
   431  		},
   432  		{
   433  			name: "fast-arr-i32",
   434  			want: []int32{1, 2, 0, 2, 1},
   435  			wfct: func(w *WBuffer, v any) {
   436  				w.WriteArrayI32(v.([]int32))
   437  			},
   438  			rfct: func(r *RBuffer) any {
   439  				sli := make([]int32, 5)
   440  				r.ReadArrayI32(sli)
   441  				return sli
   442  			},
   443  		},
   444  		{
   445  			name: "fast-arr-i64",
   446  			want: []int64{1, 2, 0, 2, 1},
   447  			wfct: func(w *WBuffer, v any) {
   448  				w.WriteArrayI64(v.([]int64))
   449  			},
   450  			rfct: func(r *RBuffer) any {
   451  				sli := make([]int64, 5)
   452  				r.ReadArrayI64(sli)
   453  				return sli
   454  			},
   455  		},
   456  		{
   457  			name: "fast-arr-u8",
   458  			want: []uint8{1, 2, 0, 2, 1},
   459  			wfct: func(w *WBuffer, v any) {
   460  				w.WriteArrayU8(v.([]uint8))
   461  			},
   462  			rfct: func(r *RBuffer) any {
   463  				sli := make([]uint8, 5)
   464  				r.ReadArrayU8(sli)
   465  				return sli
   466  			},
   467  		},
   468  		{
   469  			name: "fast-arr-u16",
   470  			want: []uint16{1, 2, 0, 2, 1},
   471  			wfct: func(w *WBuffer, v any) {
   472  				w.WriteArrayU16(v.([]uint16))
   473  			},
   474  			rfct: func(r *RBuffer) any {
   475  				sli := make([]uint16, 5)
   476  				r.ReadArrayU16(sli)
   477  				return sli
   478  			},
   479  		},
   480  		{
   481  			name: "fast-arr-u32",
   482  			want: []uint32{1, 2, 0, 2, 1},
   483  			wfct: func(w *WBuffer, v any) {
   484  				w.WriteArrayU32(v.([]uint32))
   485  			},
   486  			rfct: func(r *RBuffer) any {
   487  				sli := make([]uint32, 5)
   488  				r.ReadArrayU32(sli)
   489  				return sli
   490  			},
   491  		},
   492  		{
   493  			name: "fast-arr-u64",
   494  			want: []uint64{1, 2, 0, 2, 1},
   495  			wfct: func(w *WBuffer, v any) {
   496  				w.WriteArrayU64(v.([]uint64))
   497  			},
   498  			rfct: func(r *RBuffer) any {
   499  				sli := make([]uint64, 5)
   500  				r.ReadArrayU64(sli)
   501  				return sli
   502  			},
   503  		},
   504  		{
   505  			name: "fast-arr-f32",
   506  			want: []float32{1, 2, 0, 2, 1},
   507  			wfct: func(w *WBuffer, v any) {
   508  				w.WriteArrayF32(v.([]float32))
   509  			},
   510  			rfct: func(r *RBuffer) any {
   511  				sli := make([]float32, 5)
   512  				r.ReadArrayF32(sli)
   513  				return sli
   514  			},
   515  		},
   516  		{
   517  			name: "fast-arr-f32-nan+inf-inf",
   518  			want: []float32{1, float32(math.Inf(+1)), 0, float32(math.NaN()), float32(math.Inf(-1))},
   519  			wfct: func(w *WBuffer, v any) {
   520  				w.WriteArrayF32(v.([]float32))
   521  			},
   522  			rfct: func(r *RBuffer) any {
   523  				sli := make([]float32, 5)
   524  				r.ReadArrayF32(sli)
   525  				return sli
   526  			},
   527  			cmp: func(a, b any) bool {
   528  				aa := a.([]float32)
   529  				bb := b.([]float32)
   530  				if len(aa) != len(bb) {
   531  					return false
   532  				}
   533  				for i := range aa {
   534  					va := float64(aa[i])
   535  					vb := float64(bb[i])
   536  					switch {
   537  					case math.IsNaN(va):
   538  						if !math.IsNaN(vb) {
   539  							return false
   540  						}
   541  					case math.IsNaN(vb):
   542  						if !math.IsNaN(va) {
   543  							return false
   544  						}
   545  					case math.IsInf(va, -1):
   546  						if !math.IsInf(vb, -1) {
   547  							return false
   548  						}
   549  					case math.IsInf(vb, -1):
   550  						if !math.IsInf(va, -1) {
   551  							return false
   552  						}
   553  					case math.IsInf(va, +1):
   554  						if !math.IsInf(vb, +1) {
   555  							return false
   556  						}
   557  					case math.IsInf(vb, +1):
   558  						if !math.IsInf(va, +1) {
   559  							return false
   560  						}
   561  					case va != vb:
   562  						return false
   563  					}
   564  				}
   565  				return true
   566  			},
   567  		},
   568  		{
   569  			name: "fast-arr-f64",
   570  			want: []float64{1, 2, 0, 2, 1},
   571  			wfct: func(w *WBuffer, v any) {
   572  				w.WriteArrayF64(v.([]float64))
   573  			},
   574  			rfct: func(r *RBuffer) any {
   575  				sli := make([]float64, 5)
   576  				r.ReadArrayF64(sli)
   577  				return sli
   578  			},
   579  		},
   580  		{
   581  			name: "fast-arr-f64-nan+inf-inf",
   582  			want: []float64{1, math.Inf(+1), 0, math.NaN(), math.Inf(-1)},
   583  			wfct: func(w *WBuffer, v any) {
   584  				w.WriteArrayF64(v.([]float64))
   585  			},
   586  			rfct: func(r *RBuffer) any {
   587  				sli := make([]float64, 5)
   588  				r.ReadArrayF64(sli)
   589  				return sli
   590  			},
   591  			cmp: func(a, b any) bool {
   592  				aa := a.([]float64)
   593  				bb := b.([]float64)
   594  				if len(aa) != len(bb) {
   595  					return false
   596  				}
   597  				for i := range aa {
   598  					va := aa[i]
   599  					vb := bb[i]
   600  					switch {
   601  					case math.IsNaN(va):
   602  						if !math.IsNaN(vb) {
   603  							return false
   604  						}
   605  					case math.IsNaN(vb):
   606  						if !math.IsNaN(va) {
   607  							return false
   608  						}
   609  					case math.IsInf(va, -1):
   610  						if !math.IsInf(vb, -1) {
   611  							return false
   612  						}
   613  					case math.IsInf(vb, -1):
   614  						if !math.IsInf(va, -1) {
   615  							return false
   616  						}
   617  					case math.IsInf(va, +1):
   618  						if !math.IsInf(vb, +1) {
   619  							return false
   620  						}
   621  					case math.IsInf(vb, +1):
   622  						if !math.IsInf(va, +1) {
   623  							return false
   624  						}
   625  					case va != vb:
   626  						return false
   627  					}
   628  				}
   629  				return true
   630  			},
   631  		},
   632  		{
   633  			name: "fast-arr-str",
   634  			want: []string{"hello", "world"},
   635  			wfct: func(w *WBuffer, v any) {
   636  				w.WriteArrayString(v.([]string))
   637  			},
   638  			rfct: func(r *RBuffer) any {
   639  				sli := make([]string, 2)
   640  				r.ReadArrayString(sli)
   641  				return sli
   642  			},
   643  		},
   644  	} {
   645  		t.Run(tc.name, func(t *testing.T) {
   646  			wbuf := NewWBuffer(nil, nil, 0, nil)
   647  			tc.wfct(wbuf, tc.want)
   648  			if wbuf.Err() != nil {
   649  				t.Fatalf("error writing to buffer: %v", wbuf.Err())
   650  			}
   651  			rbuf := NewRBuffer(wbuf.w.p, nil, 0, nil)
   652  			if rbuf.Err() != nil {
   653  				t.Fatalf("error reading from buffer: %v", rbuf.Err())
   654  			}
   655  			got := tc.rfct(rbuf)
   656  			cmp := reflect.DeepEqual
   657  			if tc.cmp != nil {
   658  				cmp = tc.cmp
   659  			}
   660  			if !cmp(tc.want, got) {
   661  				t.Fatalf("error.\ngot = %v (%T)\nwant= %v (%T)", got, got, tc.want, tc.want)
   662  			}
   663  		})
   664  	}
   665  }