vitess.io/vitess@v0.16.2/go/vt/vtgate/vindexes/lookup_hash_unique_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  	"context"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  
    27  	"vitess.io/vitess/go/sqltypes"
    28  	"vitess.io/vitess/go/vt/key"
    29  	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
    30  )
    31  
    32  func TestLookupHashUniqueNew(t *testing.T) {
    33  	l := createLookup(t, "lookup_hash_unique", false /* writeOnly */)
    34  	if want, got := l.(*LookupHashUnique).writeOnly, false; got != want {
    35  		t.Errorf("Create(lookup, false): %v, want %v", got, want)
    36  	}
    37  
    38  	vindex, _ := CreateVindex("lookup_hash_unique", "lookup_hash_unique", map[string]string{
    39  		"table":      "t",
    40  		"from":       "fromc",
    41  		"to":         "toc",
    42  		"write_only": "true",
    43  	})
    44  	l = vindex.(SingleColumn)
    45  	if want, got := l.(*LookupHashUnique).writeOnly, true; got != want {
    46  		t.Errorf("Create(lookup, false): %v, want %v", got, want)
    47  	}
    48  
    49  	_, err := CreateVindex("lookup_hash_unique", "lookup_hash_unique", map[string]string{
    50  		"table":      "t",
    51  		"from":       "fromc",
    52  		"to":         "toc",
    53  		"write_only": "invalid",
    54  	})
    55  	want := "write_only value must be 'true' or 'false': 'invalid'"
    56  	if err == nil || err.Error() != want {
    57  		t.Errorf("Create(bad_scatter): %v, want %s", err, want)
    58  	}
    59  }
    60  
    61  func TestLookupHashUniqueInfo(t *testing.T) {
    62  	lhu := createLookup(t, "lookup_hash_unique", false /* writeOnly */)
    63  	assert.Equal(t, 10, lhu.Cost())
    64  	assert.Equal(t, "lookup_hash_unique", lhu.String())
    65  	assert.True(t, lhu.IsUnique())
    66  	assert.True(t, lhu.NeedsVCursor())
    67  }
    68  
    69  func TestLookupHashUniqueMap(t *testing.T) {
    70  	lhu := createLookup(t, "lookup_hash_unique", false /* writeOnly */)
    71  	vc := &vcursor{numRows: 1}
    72  
    73  	got, err := lhu.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewInt64(2)})
    74  	require.NoError(t, err)
    75  	want := []key.Destination{
    76  		key.DestinationKeyspaceID([]byte("\x16k@\xb4J\xbaK\xd6")),
    77  		key.DestinationNone{},
    78  	}
    79  	if !reflect.DeepEqual(got, want) {
    80  		t.Errorf("Map(): %#v, want %+v", got, want)
    81  	}
    82  
    83  	vc.numRows = 0
    84  	got, err = lhu.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewInt64(2)})
    85  	require.NoError(t, err)
    86  	want = []key.Destination{
    87  		key.DestinationNone{},
    88  		key.DestinationNone{},
    89  	}
    90  	if !reflect.DeepEqual(got, want) {
    91  		t.Errorf("Map(): %#v, want %+v", got, want)
    92  	}
    93  
    94  	vc.numRows = 2
    95  	_, err = lhu.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewInt64(2)})
    96  	wantErr := "LookupHash.Map: unexpected multiple results from vindex t: INT64(1)"
    97  	if err == nil || err.Error() != wantErr {
    98  		t.Errorf("lhu(query fail) err: %v, want %s", err, wantErr)
    99  	}
   100  
   101  	// Test conversion fail.
   102  	vc.result = sqltypes.MakeTestResult(
   103  		sqltypes.MakeTestFields("b|a", "bigint|varbinary"),
   104  		"1|notint",
   105  	)
   106  	got, err = lhu.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)})
   107  	require.NoError(t, err)
   108  	want = []key.Destination{
   109  		key.DestinationNone{},
   110  	}
   111  	if !reflect.DeepEqual(got, want) {
   112  		t.Errorf("Map(): %#v, want %+v", got, want)
   113  	}
   114  
   115  	// Test query fail.
   116  	vc.mustFail = true
   117  	_, err = lhu.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)})
   118  	wantErr = "lookup.Map: execute failed"
   119  	if err == nil || err.Error() != wantErr {
   120  		t.Errorf("lhu(query fail) err: %v, want %s", err, wantErr)
   121  	}
   122  	vc.mustFail = false
   123  }
   124  
   125  func TestLookupHashUniqueMapWriteOnly(t *testing.T) {
   126  	lhu := createLookup(t, "lookup_hash_unique", true)
   127  	vc := &vcursor{numRows: 0}
   128  
   129  	got, err := lhu.Map(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewInt64(2)})
   130  	require.NoError(t, err)
   131  	want := []key.Destination{
   132  		key.DestinationKeyRange{
   133  			KeyRange: &topodatapb.KeyRange{},
   134  		},
   135  		key.DestinationKeyRange{
   136  			KeyRange: &topodatapb.KeyRange{},
   137  		},
   138  	}
   139  	if !reflect.DeepEqual(got, want) {
   140  		t.Errorf("Map(): %#v, want %+v", got, want)
   141  	}
   142  }
   143  
   144  func TestLookupHashUniqueVerify(t *testing.T) {
   145  	lhu := createLookup(t, "lookup_hash_unique", false /* writeOnly */)
   146  	vc := &vcursor{numRows: 1}
   147  
   148  	// The check doesn't actually happen. But we give correct values
   149  	// to avoid confusion.
   150  	got, err := lhu.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1), sqltypes.NewInt64(2)}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6"), []byte("\x06\xe7\xea\"Βp\x8f")})
   151  	require.NoError(t, err)
   152  	want := []bool{true, true}
   153  	if !reflect.DeepEqual(got, want) {
   154  		t.Errorf("lhu.Verify(match): %v, want %v", got, want)
   155  	}
   156  
   157  	vc.numRows = 0
   158  	got, err = lhu.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")})
   159  	require.NoError(t, err)
   160  	want = []bool{false}
   161  	if !reflect.DeepEqual(got, want) {
   162  		t.Errorf("lhu.Verify(mismatch): %v, want %v", got, want)
   163  	}
   164  
   165  	_, err = lhu.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)}, [][]byte{[]byte("bogus")})
   166  	wantErr := "lookup.Verify.vunhash: invalid keyspace id: 626f677573"
   167  	if err == nil || err.Error() != wantErr {
   168  		t.Errorf("lhu.Verify(bogus) err: %v, want %s", err, wantErr)
   169  	}
   170  }
   171  
   172  func TestLookupHashUniqueVerifyWriteOnly(t *testing.T) {
   173  	lhu := createLookup(t, "lookup_hash_unique", true)
   174  	vc := &vcursor{numRows: 0}
   175  
   176  	got, err := lhu.Verify(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)}, [][]byte{[]byte("test")})
   177  	require.NoError(t, err)
   178  	want := []bool{true}
   179  	if !reflect.DeepEqual(got, want) {
   180  		t.Errorf("lhu.Verify: %v, want %v", got, want)
   181  	}
   182  	if got, want := len(vc.queries), 0; got != want {
   183  		t.Errorf("vc.queries length: %v, want %v", got, want)
   184  	}
   185  }
   186  
   187  func TestLookupHashUniqueCreate(t *testing.T) {
   188  	lhu := createLookup(t, "lookup_hash_unique", false /* writeOnly */)
   189  	vc := &vcursor{}
   190  
   191  	err := lhu.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1)}}, [][]byte{[]byte("\x16k@\xb4J\xbaK\xd6")}, false /* ignoreMode */)
   192  	require.NoError(t, err)
   193  	if got, want := len(vc.queries), 1; got != want {
   194  		t.Errorf("vc.queries length: %v, want %v", got, want)
   195  	}
   196  
   197  	err = lhu.(Lookup).Create(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1)}}, [][]byte{[]byte("bogus")}, false /* ignoreMode */)
   198  	want := "lookup.Create.vunhash: invalid keyspace id: 626f677573"
   199  	if err == nil || err.Error() != want {
   200  		t.Errorf("lhu.Create(bogus) err: %v, want %s", err, want)
   201  	}
   202  }
   203  
   204  func TestLookupHashUniqueDelete(t *testing.T) {
   205  	lhu := createLookup(t, "lookup_hash_unique", false /* writeOnly */)
   206  	vc := &vcursor{}
   207  
   208  	err := lhu.(Lookup).Delete(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1)}}, []byte("\x16k@\xb4J\xbaK\xd6"))
   209  	require.NoError(t, err)
   210  	if got, want := len(vc.queries), 1; got != want {
   211  		t.Errorf("vc.queries length: %v, want %v", got, want)
   212  	}
   213  
   214  	err = lhu.(Lookup).Delete(context.Background(), vc, [][]sqltypes.Value{{sqltypes.NewInt64(1)}}, []byte("bogus"))
   215  	want := "lookup.Delete.vunhash: invalid keyspace id: 626f677573"
   216  	if err == nil || err.Error() != want {
   217  		t.Errorf("lhu.Delete(bogus) err: %v, want %s", err, want)
   218  	}
   219  }
   220  
   221  func TestLookupHashUniqueUpdate(t *testing.T) {
   222  	lhu := createLookup(t, "lookup_hash_unique", false /* writeOnly */)
   223  	vc := &vcursor{}
   224  
   225  	err := lhu.(Lookup).Update(context.Background(), vc, []sqltypes.Value{sqltypes.NewInt64(1)}, []byte("\x16k@\xb4J\xbaK\xd6"), []sqltypes.Value{sqltypes.NewInt64(2)})
   226  	require.NoError(t, err)
   227  	if got, want := len(vc.queries), 2; got != want {
   228  		t.Errorf("vc.queries length: %v, want %v", got, want)
   229  	}
   230  }