github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/store/val/tuple_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/rand"
    19  	"testing"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  
    23  	"github.com/dolthub/dolt/go/store/pool"
    24  )
    25  
    26  var testPool = pool.NewBuffPool()
    27  
    28  func TestNewTuple(t *testing.T) {
    29  	for n := 0; n < 1024; n++ {
    30  		fields := randomByteFields(t)
    31  		tup := NewTuple(testPool, fields...)
    32  		for i, field := range fields {
    33  			assert.Equal(t, field, tup.GetField(i))
    34  		}
    35  	}
    36  }
    37  
    38  func TestTuplePrefix(t *testing.T) {
    39  	for n := 0; n < 1024; n++ {
    40  		fields := randomByteFields(t)
    41  		full := NewTuple(testPool, fields...)
    42  		for i := 0; i <= len(fields); i++ {
    43  			exp := NewTuple(testPool, fields[:i]...)
    44  			act := tuplePrefix(testPool, full, i)
    45  			assert.Equal(t, exp, act)
    46  		}
    47  	}
    48  }
    49  
    50  func TestTupleSuffix(t *testing.T) {
    51  	for n := 0; n < 1024; n++ {
    52  		fields := randomByteFields(t)
    53  		full := NewTuple(testPool, fields...)
    54  		for i := 0; i <= full.Count(); i++ {
    55  			exp := NewTuple(testPool, fields[i:]...)
    56  			act := tupleSuffix(testPool, full, full.Count()-i)
    57  			assert.Equal(t, exp, act)
    58  		}
    59  	}
    60  }
    61  
    62  func randomByteFields(t *testing.T) (fields [][]byte) {
    63  	fields = make([][]byte, rand.Intn(19)+1)
    64  	assert.True(t, len(fields) > 0)
    65  	for i := range fields {
    66  		if rand.Uint32()%4 == 0 {
    67  			// 25% NULL
    68  			fields[i] = nil
    69  			continue
    70  		}
    71  		fields[i] = make([]byte, rand.Intn(19)+1)
    72  		rand.Read(fields[i])
    73  	}
    74  	return
    75  }
    76  
    77  func tuplePrefix(pool pool.BuffPool, tup Tuple, k int) Tuple {
    78  	cnt := tup.Count()
    79  	if k >= cnt {
    80  		return tup
    81  	}
    82  	for k > 0 && tup.FieldIsNull(k-1) {
    83  		k-- // trim NULL suffix
    84  	}
    85  	if k == 0 {
    86  		return EmptyTuple
    87  	}
    88  
    89  	stop, _ := tup.GetOffset(k)
    90  	prefix, offs := allocateTuple(pool, ByteSize(stop), k)
    91  	split := ByteSize(len(tup)) - uint16Size*ByteSize(cnt)
    92  
    93  	copy(prefix, tup[:stop])
    94  	copy(offs, tup[split:])
    95  	return prefix
    96  }
    97  
    98  func tupleSuffix(pool pool.BuffPool, tup Tuple, k int) Tuple {
    99  	cnt := tup.Count()
   100  	if k == 0 {
   101  		return EmptyTuple
   102  	} else if k >= cnt {
   103  		return tup
   104  	}
   105  	fields := make([][]byte, k)
   106  	for i := range fields {
   107  		fields[i] = tup.GetField((cnt - k) + i)
   108  	}
   109  	return NewTuple(pool, fields...)
   110  }