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 }