github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/store/val/tuple_builder_test.go (about)

     1  // Copyright 2021 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package val
    16  
    17  import (
    18  	"math"
    19  	"math/rand"
    20  	"testing"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  )
    24  
    25  func TestTupleBuilder(t *testing.T) {
    26  	t.Run("smoke test", func(t *testing.T) {
    27  		smokeTestTupleBuilder(t)
    28  	})
    29  	t.Run("round trip ints", func(t *testing.T) {
    30  		testRoundTripInts(t)
    31  	})
    32  	t.Run("build large tuple", func(t *testing.T) {
    33  		testBuildLargeTuple(t)
    34  	})
    35  }
    36  
    37  func smokeTestTupleBuilder(t *testing.T) {
    38  	desc := NewTupleDescriptor(
    39  		Type{Enc: Int8Enc},
    40  		Type{Enc: Int16Enc},
    41  		Type{Enc: Int32Enc},
    42  		Type{Enc: Int64Enc},
    43  		Type{Enc: Uint8Enc},
    44  		Type{Enc: Uint16Enc},
    45  		Type{Enc: Uint32Enc},
    46  		Type{Enc: Uint64Enc},
    47  		Type{Enc: Float32Enc},
    48  		Type{Enc: Float64Enc},
    49  		Type{Enc: StringEnc},
    50  		Type{Enc: ByteStringEnc},
    51  	)
    52  
    53  	tb := NewTupleBuilder(desc)
    54  	tb.PutInt8(0, math.MaxInt8)
    55  	tb.PutInt16(1, math.MaxInt16)
    56  	tb.PutInt32(2, math.MaxInt32)
    57  	tb.PutInt64(3, math.MaxInt64)
    58  	tb.PutUint8(4, math.MaxUint8)
    59  	tb.PutUint16(5, math.MaxUint16)
    60  	tb.PutUint32(6, math.MaxUint32)
    61  	tb.PutUint64(7, math.MaxUint64)
    62  	tb.PutFloat32(8, math.MaxFloat32)
    63  	tb.PutFloat64(9, math.MaxFloat64)
    64  	tb.PutString(10, "123")
    65  	tb.PutByteString(11, []byte("abc"))
    66  
    67  	tup := tb.Build(testPool)
    68  	i8, ok := desc.GetInt8(0, tup)
    69  	assert.True(t, ok)
    70  	assert.Equal(t, int8(math.MaxInt8), i8)
    71  	i16, ok := desc.GetInt16(1, tup)
    72  	assert.True(t, ok)
    73  	assert.Equal(t, int16(math.MaxInt16), i16)
    74  	i32, ok := desc.GetInt32(2, tup)
    75  	assert.True(t, ok)
    76  	assert.Equal(t, int32(math.MaxInt32), i32)
    77  	i64, ok := desc.GetInt64(3, tup)
    78  	assert.True(t, ok)
    79  	assert.Equal(t, int64(math.MaxInt64), i64)
    80  	u8, ok := desc.GetUint8(4, tup)
    81  	assert.True(t, ok)
    82  	assert.Equal(t, uint8(math.MaxUint8), u8)
    83  	u16, ok := desc.GetUint16(5, tup)
    84  	assert.True(t, ok)
    85  	assert.Equal(t, uint16(math.MaxUint16), u16)
    86  	u32, ok := desc.GetUint32(6, tup)
    87  	assert.True(t, ok)
    88  	assert.Equal(t, uint32(math.MaxUint32), u32)
    89  	u64, ok := desc.GetUint64(7, tup)
    90  	assert.True(t, ok)
    91  	assert.Equal(t, uint64(math.MaxUint64), u64)
    92  	f32, ok := desc.GetFloat32(8, tup)
    93  	assert.True(t, ok)
    94  	assert.Equal(t, float32(math.MaxFloat32), f32)
    95  	f64, ok := desc.GetFloat64(9, tup)
    96  	assert.True(t, ok)
    97  	assert.Equal(t, float64(math.MaxFloat64), f64)
    98  	str, ok := desc.GetString(10, tup)
    99  	assert.True(t, ok)
   100  	assert.Equal(t, "123", str)
   101  	byts, ok := desc.GetBytes(11, tup)
   102  	assert.True(t, ok)
   103  	assert.Equal(t, []byte("abc"), byts)
   104  }
   105  
   106  func testRoundTripInts(t *testing.T) {
   107  	typ := Type{Enc: Int64Enc, Nullable: true}
   108  
   109  	tests := []struct {
   110  		desc TupleDesc
   111  		data map[int]int64
   112  	}{
   113  		{
   114  			desc: NewTupleDescriptor(typ),
   115  			data: map[int]int64{
   116  				0: 0,
   117  			},
   118  		},
   119  		{
   120  			desc: NewTupleDescriptor(typ, typ, typ),
   121  			data: map[int]int64{
   122  				0: 0,
   123  				1: 1,
   124  				2: 2,
   125  			},
   126  		},
   127  		{
   128  			desc: NewTupleDescriptor(typ),
   129  			data: map[int]int64{
   130  				// 0: NULL,
   131  			},
   132  		},
   133  		{
   134  			desc: NewTupleDescriptor(typ, typ, typ),
   135  			data: map[int]int64{
   136  				// 0: NULL,
   137  				// 1: NULL,
   138  				2: 2,
   139  			},
   140  		},
   141  	}
   142  
   143  	for _, test := range tests {
   144  		// build
   145  		bld := NewTupleBuilder(test.desc)
   146  		for idx, value := range test.data {
   147  			bld.PutInt64(idx, value)
   148  		}
   149  		tup := bld.Build(testPool)
   150  
   151  		// verify
   152  		n := test.desc.Count()
   153  		for idx := 0; idx < n; idx++ {
   154  			exp, ok := test.data[idx]
   155  
   156  			if !ok {
   157  				null := test.desc.IsNull(idx, tup)
   158  				assert.True(t, null)
   159  			} else {
   160  				act, ok := test.desc.GetInt64(idx, tup)
   161  				assert.True(t, ok)
   162  				assert.Equal(t, exp, act)
   163  			}
   164  		}
   165  	}
   166  }
   167  
   168  func testBuildLargeTuple(t *testing.T) {
   169  	desc := NewTupleDescriptor(
   170  		Type{Enc: Int8Enc},
   171  		Type{Enc: Int16Enc},
   172  		Type{Enc: Int32Enc},
   173  		Type{Enc: Int64Enc},
   174  		Type{Enc: Uint8Enc},
   175  		Type{Enc: Uint16Enc},
   176  		Type{Enc: Uint32Enc},
   177  		Type{Enc: Uint64Enc},
   178  		Type{Enc: Float32Enc},
   179  		Type{Enc: Float64Enc},
   180  		Type{Enc: StringEnc},
   181  		Type{Enc: ByteStringEnc},
   182  	)
   183  
   184  	s1 := make([]byte, 1024)
   185  	s2 := make([]byte, 1024)
   186  	rand.Read(s1)
   187  	rand.Read(s2)
   188  
   189  	tb := NewTupleBuilder(desc)
   190  	tb.PutInt8(0, math.MaxInt8)
   191  	tb.PutInt16(1, math.MaxInt16)
   192  	tb.PutInt32(2, math.MaxInt32)
   193  	tb.PutInt64(3, math.MaxInt64)
   194  	tb.PutUint8(4, math.MaxUint8)
   195  	tb.PutUint16(5, math.MaxUint16)
   196  	tb.PutUint32(6, math.MaxUint32)
   197  	tb.PutUint64(7, math.MaxUint64)
   198  	tb.PutFloat32(8, math.MaxFloat32)
   199  	tb.PutFloat64(9, math.MaxFloat64)
   200  	tb.PutString(10, string(s1))
   201  	tb.PutByteString(11, []byte(s2))
   202  }
   203  
   204  type testCompare struct{}
   205  
   206  var _ TupleComparator = testCompare{}
   207  
   208  func (tc testCompare) Compare(left, right Tuple, desc TupleDesc) (cmp int) {
   209  	for i, typ := range desc.Types {
   210  		cmp = compare(typ, left.GetField(i), right.GetField(i))
   211  		if cmp != 0 {
   212  			break
   213  		}
   214  	}
   215  	return
   216  }
   217  
   218  func (tc testCompare) CompareValues(_ int, left, right []byte, typ Type) int {
   219  	return compare(typ, left, right)
   220  }
   221  
   222  func (tc testCompare) Prefix(n int) TupleComparator {
   223  	return tc
   224  }
   225  
   226  func (tc testCompare) Suffix(n int) TupleComparator {
   227  	return tc
   228  }
   229  
   230  func (tc testCompare) Validated(types []Type) TupleComparator {
   231  	return tc
   232  }