github.com/apache/arrow/go/v14@v14.0.1/parquet/internal/utils/bit_reader_test.go (about)

     1  // Licensed to the Apache Software Foundation (ASF) under one
     2  // or more contributor license agreements.  See the NOTICE file
     3  // distributed with this work for additional information
     4  // regarding copyright ownership.  The ASF licenses this file
     5  // to you under the Apache License, Version 2.0 (the
     6  // "License"); you may not use this file except in compliance
     7  // with the License.  You may obtain a copy of the License at
     8  //
     9  // http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  package utils_test
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/binary"
    22  	"fmt"
    23  	"math"
    24  	"math/bits"
    25  	"strconv"
    26  	"testing"
    27  
    28  	"github.com/apache/arrow/go/v14/arrow"
    29  	"github.com/apache/arrow/go/v14/arrow/array"
    30  	"github.com/apache/arrow/go/v14/arrow/bitutil"
    31  	"github.com/apache/arrow/go/v14/arrow/memory"
    32  	"github.com/apache/arrow/go/v14/parquet/internal/utils"
    33  	"github.com/stretchr/testify/assert"
    34  	"github.com/stretchr/testify/suite"
    35  	"golang.org/x/exp/rand"
    36  	"gonum.org/v1/gonum/stat/distuv"
    37  )
    38  
    39  func TestBitWriter(t *testing.T) {
    40  	buf := make([]byte, 8)
    41  	bw := utils.NewBitWriter(utils.NewWriterAtBuffer(buf))
    42  
    43  	for i := 0; i < 8; i++ {
    44  		assert.Nil(t, bw.WriteValue(uint64(i%2), 1))
    45  	}
    46  	bw.Flush(false)
    47  
    48  	assert.Equal(t, byte(0xAA), buf[0])
    49  
    50  	for i := 0; i < 8; i++ {
    51  		switch i {
    52  		case 0, 1, 4, 5:
    53  			assert.Nil(t, bw.WriteValue(0, 1))
    54  		default:
    55  			assert.Nil(t, bw.WriteValue(1, 1))
    56  		}
    57  	}
    58  	bw.Flush(false)
    59  
    60  	assert.Equal(t, byte(0xAA), buf[0])
    61  	assert.Equal(t, byte(0xCC), buf[1])
    62  }
    63  
    64  func TestBitReader(t *testing.T) {
    65  	buf := []byte{0xAA, 0xCC} // 0b10101010 0b11001100
    66  
    67  	reader := utils.NewBitReader(bytes.NewReader(buf))
    68  	for i := 0; i < 8; i++ {
    69  		val, ok := reader.GetValue(1)
    70  		assert.True(t, ok)
    71  		assert.Equalf(t, (i%2) != 0, val != 0, "val: %d, i: %d", val, i)
    72  	}
    73  
    74  	for i := 0; i < 8; i++ {
    75  		val, ok := reader.GetValue(1)
    76  		assert.True(t, ok)
    77  		switch i {
    78  		case 0, 1, 4, 5:
    79  			assert.EqualValues(t, 0, val)
    80  		default:
    81  			assert.EqualValues(t, 1, val)
    82  		}
    83  	}
    84  }
    85  
    86  func TestBitArrayVals(t *testing.T) {
    87  	tests := []struct {
    88  		name  string
    89  		nvals func(uint) int
    90  	}{
    91  		{"1 value", func(uint) int { return 1 }},
    92  		{"2 values", func(uint) int { return 2 }},
    93  		{"larger", func(w uint) int {
    94  			if w < 12 {
    95  				return 1 << w
    96  			}
    97  			return 4096
    98  		}},
    99  		{"1024 values", func(uint) int { return 1024 }},
   100  	}
   101  
   102  	for width := uint(1); width < 32; width++ {
   103  		t.Run(fmt.Sprintf("BitWriter Width %d", width), func(t *testing.T) {
   104  			for _, tt := range tests {
   105  				t.Run(tt.name, func(t *testing.T) {
   106  					var (
   107  						nvals        = tt.nvals(width)
   108  						mod   uint64 = 1
   109  					)
   110  					l := bitutil.BytesForBits(int64(int(width) * nvals))
   111  					assert.Greater(t, l, int64(0))
   112  
   113  					if width != 64 {
   114  						mod = uint64(1) << width
   115  					}
   116  
   117  					buf := make([]byte, l)
   118  					bw := utils.NewBitWriter(utils.NewWriterAtBuffer(buf))
   119  					for i := 0; i < nvals; i++ {
   120  						assert.Nil(t, bw.WriteValue(uint64(i)%mod, width))
   121  					}
   122  					bw.Flush(false)
   123  					assert.Equal(t, l, int64(bw.Written()))
   124  
   125  					br := utils.NewBitReader(bytes.NewReader(buf))
   126  					for i := 0; i < nvals; i++ {
   127  						val, ok := br.GetValue(int(width))
   128  						assert.True(t, ok)
   129  						assert.Equal(t, uint64(i)%mod, val)
   130  					}
   131  				})
   132  			}
   133  		})
   134  	}
   135  }
   136  
   137  func TestMixedValues(t *testing.T) {
   138  	const buflen = 1024
   139  	buf := make([]byte, buflen)
   140  	parity := true
   141  
   142  	bw := utils.NewBitWriter(utils.NewWriterAtBuffer(buf))
   143  	for i := 0; i < buflen; i++ {
   144  		if i%2 == 0 {
   145  			v := uint64(1)
   146  			if !parity {
   147  				v = 0
   148  			}
   149  			assert.Nil(t, bw.WriteValue(v, 1))
   150  			parity = !parity
   151  		} else {
   152  			assert.Nil(t, bw.WriteValue(uint64(i), 10))
   153  		}
   154  	}
   155  	bw.Flush(false)
   156  
   157  	parity = true
   158  	br := utils.NewBitReader(bytes.NewReader(buf))
   159  	for i := 0; i < buflen; i++ {
   160  		if i%2 == 0 {
   161  			val, ok := br.GetValue(1)
   162  			assert.True(t, ok)
   163  			exp := uint64(1)
   164  			if !parity {
   165  				exp = 0
   166  			}
   167  			assert.Equal(t, exp, val)
   168  			parity = !parity
   169  		} else {
   170  			val, ok := br.GetValue(10)
   171  			assert.True(t, ok)
   172  			assert.Equal(t, uint64(i), val)
   173  		}
   174  	}
   175  }
   176  
   177  func TestZigZag(t *testing.T) {
   178  	testvals := []struct {
   179  		val int64
   180  		exp [10]byte
   181  	}{
   182  		{0, [...]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
   183  		{1, [...]byte{2, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
   184  		{1234, [...]byte{164, 19, 0, 0, 0, 0, 0, 0, 0, 0}},
   185  		{-1, [...]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
   186  		{-1234, [...]byte{163, 19, 0, 0, 0, 0, 0, 0, 0, 0}},
   187  		{math.MaxInt32, [...]byte{254, 255, 255, 255, 15, 0, 0, 0, 0, 0}},
   188  		{-math.MaxInt32, [...]byte{253, 255, 255, 255, 15, 0, 0, 0, 0, 0}},
   189  		{math.MinInt32, [...]byte{255, 255, 255, 255, 15, 0, 0, 0, 0, 0}},
   190  		{math.MaxInt64, [...]byte{254, 255, 255, 255, 255, 255, 255, 255, 255, 1}},
   191  		{-math.MaxInt64, [...]byte{253, 255, 255, 255, 255, 255, 255, 255, 255, 1}},
   192  		{math.MinInt64, [...]byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 1}},
   193  	}
   194  
   195  	for _, v := range testvals {
   196  		t.Run(strconv.Itoa(int(v.val)), func(t *testing.T) {
   197  			var buf [binary.MaxVarintLen64]byte
   198  			wrtr := utils.NewBitWriter(utils.NewWriterAtBuffer(buf[:]))
   199  			assert.True(t, wrtr.WriteZigZagVlqInt(v.val))
   200  			wrtr.Flush(false)
   201  
   202  			assert.Equal(t, v.exp, buf)
   203  
   204  			rdr := utils.NewBitReader(bytes.NewReader(buf[:]))
   205  			val, ok := rdr.GetZigZagVlqInt()
   206  			assert.True(t, ok)
   207  			assert.EqualValues(t, v.val, val)
   208  		})
   209  	}
   210  }
   211  
   212  const buflen = 1024
   213  
   214  type RLETestSuite struct {
   215  	suite.Suite
   216  
   217  	expectedBuf []byte
   218  	values      []uint64
   219  }
   220  
   221  type RLERandomSuite struct {
   222  	suite.Suite
   223  }
   224  
   225  func TestRLE(t *testing.T) {
   226  	suite.Run(t, new(RLETestSuite))
   227  }
   228  
   229  func TestRleRandom(t *testing.T) {
   230  	suite.Run(t, new(RLERandomSuite))
   231  }
   232  
   233  func (r *RLETestSuite) ValidateRle(vals []uint64, width int, expected []byte, explen int) {
   234  	const buflen = 64 * 1024
   235  	buf := make([]byte, buflen)
   236  
   237  	r.Run("test encode", func() {
   238  		r.LessOrEqual(explen, buflen)
   239  
   240  		enc := utils.NewRleEncoder(utils.NewWriterAtBuffer(buf), width)
   241  		for _, val := range vals {
   242  			r.NoError(enc.Put(val))
   243  		}
   244  		encoded := enc.Flush()
   245  		if explen != -1 {
   246  			r.Equal(explen, encoded)
   247  		}
   248  
   249  		if expected != nil {
   250  			r.Equal(expected, buf[:encoded])
   251  		}
   252  	})
   253  
   254  	r.Run("decode read", func() {
   255  		dec := utils.NewRleDecoder(bytes.NewReader(buf), width)
   256  		for _, val := range vals {
   257  			v, ok := dec.GetValue()
   258  			r.True(ok)
   259  			r.Equal(val, v)
   260  		}
   261  	})
   262  
   263  	r.Run("decode batch read", func() {
   264  		dec := utils.NewRleDecoder(bytes.NewReader(buf), width)
   265  		check := make([]uint64, len(vals))
   266  		r.Equal(len(vals), dec.GetBatch(check))
   267  		r.Equal(vals, check)
   268  	})
   269  }
   270  
   271  func (r *RLETestSuite) SetupTest() {
   272  	r.expectedBuf = make([]byte, 0, buflen)
   273  	r.values = make([]uint64, 100)
   274  }
   275  
   276  func (r *RLETestSuite) Test50Zeros50Ones() {
   277  	for i := 0; i < 50; i++ {
   278  		r.values[i] = 0
   279  	}
   280  	for i := 50; i < 100; i++ {
   281  		r.values[i] = 1
   282  	}
   283  
   284  	r.expectedBuf = append(r.expectedBuf, []byte{50 << 1, 0, 50 << 1, 1}...)
   285  	for width := 1; width <= 8; width++ {
   286  		r.Run(fmt.Sprintf("bitwidth: %d", width), func() {
   287  			r.ValidateRle(r.values, width, r.expectedBuf, 4)
   288  		})
   289  	}
   290  
   291  	for width := 9; width <= 32; width++ {
   292  		r.Run(fmt.Sprintf("bitwidth: %d", width), func() {
   293  			r.ValidateRle(r.values, width, nil, int(2*(1+bitutil.BytesForBits(int64(width)))))
   294  		})
   295  	}
   296  }
   297  
   298  func (r *RLETestSuite) Test100ZerosOnesAlternating() {
   299  	for idx := range r.values {
   300  		r.values[idx] = uint64(idx % 2)
   301  	}
   302  
   303  	ngroups := bitutil.BytesForBits(100)
   304  	r.expectedBuf = r.expectedBuf[:ngroups+1]
   305  	r.expectedBuf[0] = byte(ngroups<<1) | 1
   306  	for i := 1; i <= 100/8; i++ {
   307  		r.expectedBuf[i] = 0xAA
   308  	}
   309  	r.expectedBuf[100/8+1] = 0x0A
   310  
   311  	r.Run("width: 1", func() {
   312  		r.ValidateRle(r.values, 1, r.expectedBuf, int(1+ngroups))
   313  	})
   314  	for width := 2; width < 32; width++ {
   315  		r.Run(fmt.Sprintf("width: %d", width), func() {
   316  			nvalues := bitutil.BytesForBits(100) * 8
   317  			r.ValidateRle(r.values, width, nil, int(1+bitutil.BytesForBits(int64(width)*nvalues)))
   318  		})
   319  	}
   320  }
   321  
   322  func (r *RLETestSuite) Test16BitValues() {
   323  	// confirm encoded values are little endian
   324  	r.values = r.values[:28]
   325  	for i := 0; i < 16; i++ {
   326  		r.values[i] = 0x55aa
   327  	}
   328  	for i := 16; i < 28; i++ {
   329  		r.values[i] = 0xaa55
   330  	}
   331  
   332  	r.expectedBuf = append(r.expectedBuf, []byte{
   333  		16 << 1, 0xaa, 0x55, 12 << 1, 0x55, 0xaa,
   334  	}...)
   335  
   336  	r.ValidateRle(r.values, 16, r.expectedBuf, 6)
   337  }
   338  
   339  func (r *RLETestSuite) Test32BitValues() {
   340  	// confirm encoded values are little endian
   341  	r.values = r.values[:28]
   342  	for i := 0; i < 16; i++ {
   343  		r.values[i] = 0x555aaaa5
   344  	}
   345  	for i := 16; i < 28; i++ {
   346  		r.values[i] = 0x5aaaa555
   347  	}
   348  
   349  	r.expectedBuf = append(r.expectedBuf, []byte{
   350  		16 << 1, 0xa5, 0xaa, 0x5a, 0x55,
   351  		12 << 1, 0x55, 0xa5, 0xaa, 0x5a,
   352  	}...)
   353  
   354  	r.ValidateRle(r.values, 32, r.expectedBuf, 10)
   355  }
   356  
   357  func (r *RLETestSuite) TestRleValues() {
   358  	tests := []struct {
   359  		name  string
   360  		nvals int
   361  		val   int
   362  	}{
   363  		{"1", 1, -1},
   364  		{"1024", 1024, -1},
   365  		{"1024 0", 1024, 0},
   366  		{"1024 1", 1024, 1},
   367  	}
   368  
   369  	for width := 1; width <= 32; width++ {
   370  		r.Run(fmt.Sprintf("width %d", width), func() {
   371  			for _, tt := range tests {
   372  				r.Run(tt.name, func() {
   373  
   374  					var mod uint64 = 1
   375  					if width != 64 {
   376  						mod = uint64(1) << width
   377  					}
   378  
   379  					r.values = r.values[:0]
   380  
   381  					for v := 0; v < tt.nvals; v++ {
   382  						if tt.val != -1 {
   383  							r.values = append(r.values, uint64(tt.val))
   384  						} else {
   385  							r.values = append(r.values, uint64(v)%mod)
   386  						}
   387  					}
   388  					r.ValidateRle(r.values, width, nil, -1)
   389  				})
   390  			}
   391  		})
   392  	}
   393  }
   394  
   395  // Test that writes out a repeated group and then a literal group
   396  // but flush before finishing
   397  func (r *RLETestSuite) TestBitRleFlush() {
   398  	vals := make([]uint64, 0, 16)
   399  	for i := 0; i < 16; i++ {
   400  		vals = append(vals, 1)
   401  	}
   402  	vals = append(vals, 0)
   403  	r.ValidateRle(vals, 1, nil, -1)
   404  	vals = append(vals, 1)
   405  	r.ValidateRle(vals, 1, nil, -1)
   406  	vals = append(vals, 1)
   407  	r.ValidateRle(vals, 1, nil, -1)
   408  	vals = append(vals, 1)
   409  	r.ValidateRle(vals, 1, nil, -1)
   410  }
   411  
   412  func (r *RLETestSuite) TestRepeatedPattern() {
   413  	r.values = r.values[:0]
   414  	const minrun = 1
   415  	const maxrun = 32
   416  
   417  	for i := minrun; i <= maxrun; i++ {
   418  		v := i % 2
   419  		for j := 0; j < i; j++ {
   420  			r.values = append(r.values, uint64(v))
   421  		}
   422  	}
   423  
   424  	// and go back down again
   425  	for i := maxrun; i >= minrun; i-- {
   426  		v := i % 2
   427  		for j := 0; j < i; j++ {
   428  			r.values = append(r.values, uint64(v))
   429  		}
   430  	}
   431  
   432  	r.ValidateRle(r.values, 1, nil, -1)
   433  }
   434  
   435  func TestBitWidthZeroRepeated(t *testing.T) {
   436  	buf := make([]byte, 1)
   437  	const nvals = 15
   438  	buf[0] = nvals << 1 // repeated indicator byte
   439  	dec := utils.NewRleDecoder(bytes.NewReader(buf), 0)
   440  	for i := 0; i < nvals; i++ {
   441  		val, ok := dec.GetValue()
   442  		assert.True(t, ok)
   443  		assert.Zero(t, val)
   444  	}
   445  	_, ok := dec.GetValue()
   446  	assert.False(t, ok)
   447  }
   448  
   449  func TestBitWidthZeroLiteral(t *testing.T) {
   450  	const ngroups = 4
   451  	buf := []byte{4<<1 | 1}
   452  	dec := utils.NewRleDecoder(bytes.NewReader(buf), 0)
   453  	const nvals = ngroups * 8
   454  	for i := 0; i < nvals; i++ {
   455  		val, ok := dec.GetValue()
   456  		assert.True(t, ok)
   457  		assert.Zero(t, val)
   458  	}
   459  	_, ok := dec.GetValue()
   460  	assert.False(t, ok)
   461  }
   462  
   463  func (r *RLERandomSuite) checkRoundTrip(vals []uint64, width int) bool {
   464  	const buflen = 64 * 1024
   465  	buf := make([]byte, buflen)
   466  	var encoded int
   467  
   468  	res := r.Run("encode values", func() {
   469  		enc := utils.NewRleEncoder(utils.NewWriterAtBuffer(buf), width)
   470  		for idx, val := range vals {
   471  			r.Require().NoErrorf(enc.Put(val), "encoding idx: %d", idx)
   472  		}
   473  		encoded = enc.Flush()
   474  	})
   475  
   476  	res = res && r.Run("decode individual", func() {
   477  		dec := utils.NewRleDecoder(bytes.NewReader(buf[:encoded]), width)
   478  		for idx, val := range vals {
   479  			out, ok := dec.GetValue()
   480  			r.True(ok)
   481  			r.Require().Equalf(out, val, "mismatch idx: %d", idx)
   482  		}
   483  	})
   484  
   485  	res = res && r.Run("batch decode", func() {
   486  		dec := utils.NewRleDecoder(bytes.NewReader(buf[:encoded]), width)
   487  		read := make([]uint64, len(vals))
   488  		r.Require().Equal(len(vals), dec.GetBatch(read))
   489  		r.Equal(vals, read)
   490  	})
   491  
   492  	return res
   493  }
   494  
   495  func (r *RLERandomSuite) checkRoundTripSpaced(vals arrow.Array, width int) {
   496  	nvalues := vals.Len()
   497  	bufsize := utils.MaxBufferSize(width, nvalues)
   498  
   499  	buffer := make([]byte, bufsize)
   500  	encoder := utils.NewRleEncoder(utils.NewWriterAtBuffer(buffer), width)
   501  
   502  	switch v := vals.(type) {
   503  	case *array.Int32:
   504  		for i := 0; i < v.Len(); i++ {
   505  			if v.IsValid(i) {
   506  				r.Require().NoError(encoder.Put(uint64(v.Value(i))))
   507  			}
   508  		}
   509  	}
   510  
   511  	encodedSize := encoder.Flush()
   512  
   513  	// verify batch read
   514  	decoder := utils.NewRleDecoder(bytes.NewReader(buffer[:encodedSize]), width)
   515  	valuesRead := make([]uint64, nvalues)
   516  	val, err := decoder.GetBatchSpaced(valuesRead, vals.NullN(), vals.NullBitmapBytes(), int64(vals.Data().Offset()))
   517  	r.NoError(err)
   518  	r.EqualValues(nvalues, val)
   519  
   520  	switch v := vals.(type) {
   521  	case *array.Int32:
   522  		for i := 0; i < nvalues; i++ {
   523  			if vals.IsValid(i) {
   524  				r.EqualValues(v.Value(i), valuesRead[i])
   525  			}
   526  		}
   527  	}
   528  }
   529  
   530  func (r *RLERandomSuite) TestRandomSequences() {
   531  	const niters = 50
   532  	const ngroups = 1000
   533  	const maxgroup = 16
   534  
   535  	values := make([]uint64, ngroups+maxgroup)
   536  	seed := rand.Uint64() ^ (rand.Uint64() << 32)
   537  	gen := rand.New(rand.NewSource(seed))
   538  
   539  	for itr := 0; itr < niters; itr++ {
   540  		parity := false
   541  		values = values[:0]
   542  
   543  		for i := 0; i < ngroups; i++ {
   544  			groupsize := gen.Intn(19) + 1
   545  			if groupsize > maxgroup {
   546  				groupsize = 1
   547  			}
   548  
   549  			v := uint64(0)
   550  			if parity {
   551  				v = 1
   552  			}
   553  			for j := 0; j < groupsize; j++ {
   554  				values = append(values, v)
   555  			}
   556  			parity = !parity
   557  		}
   558  		r.Require().Truef(r.checkRoundTrip(values, bits.Len(uint(len(values)))), "failing seed: %d", seed)
   559  	}
   560  }
   561  
   562  type RandomArrayGenerator struct {
   563  	seed     uint64
   564  	extra    uint64
   565  	src      rand.Source
   566  	seedRand *rand.Rand
   567  }
   568  
   569  func NewRandomArrayGenerator(seed uint64) RandomArrayGenerator {
   570  	src := rand.NewSource(seed)
   571  	return RandomArrayGenerator{seed, 0, src, rand.New(src)}
   572  }
   573  
   574  func (r *RandomArrayGenerator) generateBitmap(buffer []byte, n int64, prob float64) int64 {
   575  	count := int64(0)
   576  	r.extra++
   577  
   578  	dist := distuv.Bernoulli{P: prob, Src: rand.NewSource(r.seed + r.extra)}
   579  	for i := int(0); int64(i) < n; i++ {
   580  		if dist.Rand() != float64(0.0) {
   581  			bitutil.SetBit(buffer, i)
   582  		} else {
   583  			count++
   584  		}
   585  	}
   586  
   587  	return count
   588  }
   589  
   590  func (r *RandomArrayGenerator) Int32(size int64, min, max int32, prob float64) arrow.Array {
   591  	buffers := make([]*memory.Buffer, 2)
   592  	nullCount := int64(0)
   593  
   594  	buffers[0] = memory.NewResizableBuffer(memory.DefaultAllocator)
   595  	buffers[0].Resize(int(bitutil.BytesForBits(size)))
   596  	nullCount = r.generateBitmap(buffers[0].Bytes(), size, prob)
   597  
   598  	buffers[1] = memory.NewResizableBuffer(memory.DefaultAllocator)
   599  	buffers[1].Resize(int(size * int64(arrow.Int32SizeBytes)))
   600  
   601  	r.extra++
   602  	dist := rand.New(rand.NewSource(r.seed + r.extra))
   603  	out := arrow.Int32Traits.CastFromBytes(buffers[1].Bytes())
   604  	for i := int64(0); i < size; i++ {
   605  		out[i] = int32(dist.Int31n(max-min+1)) + min
   606  	}
   607  
   608  	return array.NewInt32Data(array.NewData(arrow.PrimitiveTypes.Int32, int(size), buffers, nil, int(nullCount), 0))
   609  }
   610  
   611  func (r *RLERandomSuite) TestGetBatchSpaced() {
   612  	seed := uint64(1337)
   613  
   614  	rng := NewRandomArrayGenerator(seed)
   615  
   616  	tests := []struct {
   617  		name     string
   618  		max      int32
   619  		size     int64
   620  		nullProb float64
   621  		bitWidth int
   622  	}{
   623  		{"all ones 0.01 nullprob width 1", 1, 100000, 0.01, 1},
   624  		{"all ones 0.1 nullprob width 1", 1, 100000, 0.1, 1},
   625  		{"all ones 0.5 nullprob width 1", 1, 100000, 0.5, 1},
   626  		{"max 4 0.05 nullprob width 3", 4, 100000, 0.05, 3},
   627  		{"max 100 0.05 nullprob width 7", 100, 100000, 0.05, 7},
   628  	}
   629  
   630  	for _, tt := range tests {
   631  		r.Run(tt.name, func() {
   632  			arr := rng.Int32(tt.size, 0, tt.max, tt.nullProb)
   633  			r.checkRoundTripSpaced(arr, tt.bitWidth)
   634  			r.checkRoundTripSpaced(array.NewSlice(arr, 1, int64(arr.Len())), tt.bitWidth)
   635  		})
   636  	}
   637  }