vitess.io/vitess@v0.16.2/go/vt/vtgate/vindexes/xxhash_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package vindexes
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"encoding/hex"
    23  	"fmt"
    24  	"reflect"
    25  	"testing"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  
    29  	"vitess.io/vitess/go/sqltypes"
    30  	"vitess.io/vitess/go/vt/key"
    31  )
    32  
    33  var xxHash SingleColumn
    34  
    35  func init() {
    36  	hv, err := CreateVindex("xxhash", "xxhash_name", map[string]string{"Table": "t", "Column": "c"})
    37  	if err != nil {
    38  		panic(err)
    39  	}
    40  	xxHash = hv.(SingleColumn)
    41  }
    42  
    43  func TestXXHashInfo(t *testing.T) {
    44  	assert.Equal(t, 1, xxHash.Cost())
    45  	assert.Equal(t, "xxhash_name", xxHash.String())
    46  	assert.True(t, xxHash.IsUnique())
    47  	assert.False(t, xxHash.NeedsVCursor())
    48  }
    49  
    50  func TestXXHashMap(t *testing.T) {
    51  	tcases := []struct {
    52  		in  sqltypes.Value
    53  		out []byte
    54  	}{{
    55  		in:  sqltypes.NewVarChar("test1"),
    56  		out: []byte{0xd0, 0x1a, 0xb7, 0xe4, 0xd6, 0x97, 0x8f, 0xb},
    57  	}, {
    58  		in:  sqltypes.NewVarChar("test2"),
    59  		out: []byte{0x87, 0xeb, 0x11, 0x71, 0x4c, 0xa, 0xe, 0x89},
    60  	}, {
    61  		in:  sqltypes.NewVarChar("testaverylongvaluetomakesurethisworks"),
    62  		out: []byte{0x81, 0xd8, 0xc3, 0x8e, 0xd, 0x85, 0xe, 0x6a},
    63  	}, {
    64  		in:  sqltypes.NewInt64(1),
    65  		out: []byte{0xd4, 0x64, 0x5, 0x36, 0x76, 0x12, 0xb4, 0xb7},
    66  	}, {
    67  		in:  sqltypes.NULL,
    68  		out: []byte{0x99, 0xe9, 0xd8, 0x51, 0x37, 0xdb, 0x46, 0xef},
    69  	}, {
    70  		in:  sqltypes.NewInt64(-1),
    71  		out: []byte{0xd8, 0xe2, 0xa6, 0xa7, 0xc8, 0xc7, 0x62, 0x3d},
    72  	}, {
    73  		in:  sqltypes.NewUint64(18446744073709551615),
    74  		out: []byte{0x47, 0x7c, 0xfa, 0x8d, 0x6d, 0x8f, 0x1f, 0x8d},
    75  	}, {
    76  		in:  sqltypes.NewInt64(9223372036854775807),
    77  		out: []byte{0xb3, 0x7e, 0xb0, 0x1f, 0x7b, 0xff, 0xaf, 0xd8},
    78  	}, {
    79  		in:  sqltypes.NewUint64(9223372036854775807),
    80  		out: []byte{0xb3, 0x7e, 0xb0, 0x1f, 0x7b, 0xff, 0xaf, 0xd8},
    81  	}, {
    82  		in:  sqltypes.NewInt64(-9223372036854775808),
    83  		out: []byte{0x10, 0x2c, 0x27, 0xdd, 0xb2, 0x6a, 0x60, 0x9e},
    84  	}}
    85  
    86  	for _, tcase := range tcases {
    87  		got, err := xxHash.Map(context.Background(), nil, []sqltypes.Value{tcase.in})
    88  		if err != nil {
    89  			t.Error(err)
    90  		}
    91  		out := []byte(got[0].(key.DestinationKeyspaceID))
    92  		if !bytes.Equal(tcase.out, out) {
    93  			t.Errorf("Map(%#v): %#v, want %#v", tcase.in, out, tcase.out)
    94  		}
    95  	}
    96  }
    97  
    98  func TestXXHashVerify(t *testing.T) {
    99  	hexValStr := "9efa"
   100  	hexValStrSQL := fmt.Sprintf("x'%s'", hexValStr)
   101  	hexNumStrSQL := fmt.Sprintf("0x%s", hexValStr)
   102  	hexBytes, _ := hex.DecodeString(hexValStr)
   103  	ids := []sqltypes.Value{sqltypes.NewUint64(1), sqltypes.NewUint64(2), sqltypes.NewHexVal([]byte(hexValStrSQL)), sqltypes.NewHexNum([]byte(hexNumStrSQL))}
   104  	ksids := [][]byte{{0xd4, 0x64, 0x5, 0x36, 0x76, 0x12, 0xb4, 0xb7}, {0xd4, 0x64, 0x5, 0x36, 0x76, 0x12, 0xb4, 0xb7}, vXXHash(hexBytes), vXXHash(hexBytes)}
   105  	got, err := xxHash.Verify(context.Background(), nil, ids, ksids)
   106  	if err != nil {
   107  		t.Fatal(err)
   108  	}
   109  	want := []bool{true, false, true, true}
   110  	if !reflect.DeepEqual(got, want) {
   111  		t.Errorf("xxHash.Verify: %v, want %v", got, want)
   112  	}
   113  }
   114  
   115  func BenchmarkXXHash(b *testing.B) {
   116  	for _, benchSize := range []struct {
   117  		name string
   118  		n    int
   119  	}{
   120  		{"8B", 8},
   121  		{"32B", 32},
   122  		{"64B", 64},
   123  		{"512B", 512},
   124  		{"1KB", 1e3},
   125  		{"4KB", 4e3},
   126  	} {
   127  		input := make([]byte, benchSize.n)
   128  		for i := range input {
   129  			input[i] = byte(i)
   130  		}
   131  
   132  		name := fmt.Sprintf("xxHash,direct,bytes,n=%s", benchSize.name)
   133  		b.Run(name, func(b *testing.B) {
   134  			benchmarkXXHashBytes(b, input)
   135  		})
   136  
   137  	}
   138  }
   139  
   140  var sinkXXHash []byte
   141  
   142  func benchmarkXXHashBytes(b *testing.B, input []byte) {
   143  	b.SetBytes(int64(len(input)))
   144  	for i := 0; i < b.N; i++ {
   145  		sinkXXHash = vXXHash(input)
   146  	}
   147  }