github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/ekv/key_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, 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  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package ekv
    15  
    16  import (
    17  	"bytes"
    18  	"errors"
    19  	"testing"
    20  	"time"
    21  
    22  	. "github.com/whtcorpsinc/check"
    23  	"github.com/whtcorpsinc/milevadb/soliton/codec"
    24  	"github.com/whtcorpsinc/milevadb/soliton/testleak"
    25  	"github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx"
    26  	"github.com/whtcorpsinc/milevadb/types"
    27  )
    28  
    29  var _ = Suite(&testKeySuite{})
    30  
    31  type testKeySuite struct {
    32  }
    33  
    34  func (s *testKeySuite) TestPartialNext(c *C) {
    35  	defer testleak.AfterTest(c)()
    36  	sc := &stmtctx.StatementContext{TimeZone: time.Local}
    37  	// keyA represents a multi column index.
    38  	keyA, err := codec.EncodeValue(sc, nil, types.NewCauset("abc"), types.NewCauset("def"))
    39  	c.Check(err, IsNil)
    40  	keyB, err := codec.EncodeValue(sc, nil, types.NewCauset("abca"), types.NewCauset("def"))
    41  	c.Check(err, IsNil)
    42  
    43  	// We only use first column value to seek.
    44  	seekKey, err := codec.EncodeValue(sc, nil, types.NewCauset("abc"))
    45  	c.Check(err, IsNil)
    46  
    47  	nextKey := Key(seekKey).Next()
    48  	cmp := bytes.Compare(nextKey, keyA)
    49  	c.Assert(cmp, Equals, -1)
    50  
    51  	// Use next partial key, we can skip all index keys with first column value equal to "abc".
    52  	nextPartialKey := Key(seekKey).PrefixNext()
    53  	cmp = bytes.Compare(nextPartialKey, keyA)
    54  	c.Assert(cmp, Equals, 1)
    55  
    56  	cmp = bytes.Compare(nextPartialKey, keyB)
    57  	c.Assert(cmp, Equals, -1)
    58  }
    59  
    60  func (s *testKeySuite) TestIsPoint(c *C) {
    61  	tests := []struct {
    62  		start   []byte
    63  		end     []byte
    64  		isPoint bool
    65  	}{
    66  		{
    67  			start:   Key("rowkey1"),
    68  			end:     Key("rowkey2"),
    69  			isPoint: true,
    70  		},
    71  		{
    72  			start:   Key("rowkey1"),
    73  			end:     Key("rowkey3"),
    74  			isPoint: false,
    75  		},
    76  		{
    77  			start:   Key(""),
    78  			end:     []byte{0},
    79  			isPoint: true,
    80  		},
    81  		{
    82  			start:   []byte{123, 123, 255, 255},
    83  			end:     []byte{123, 124, 0, 0},
    84  			isPoint: true,
    85  		},
    86  		{
    87  			start:   []byte{123, 123, 255, 255},
    88  			end:     []byte{123, 124, 0, 1},
    89  			isPoint: false,
    90  		},
    91  		{
    92  			start:   []byte{123, 123},
    93  			end:     []byte{123, 123, 0},
    94  			isPoint: true,
    95  		},
    96  		{
    97  			start:   []byte{255},
    98  			end:     []byte{0},
    99  			isPoint: false,
   100  		},
   101  	}
   102  	for _, tt := range tests {
   103  		kr := KeyRange{
   104  			StartKey: tt.start,
   105  			EndKey:   tt.end,
   106  		}
   107  		c.Check(kr.IsPoint(), Equals, tt.isPoint)
   108  	}
   109  }
   110  
   111  func (s *testKeySuite) TestBasicFunc(c *C) {
   112  	c.Assert(IsTxnRetryableError(nil), IsFalse)
   113  	c.Assert(IsTxnRetryableError(ErrTxnRetryable), IsTrue)
   114  	c.Assert(IsTxnRetryableError(errors.New("test")), IsFalse)
   115  }
   116  
   117  func (s *testKeySuite) TestHandle(c *C) {
   118  	ih := IntHandle(100)
   119  	c.Assert(ih.IsInt(), IsTrue)
   120  	_, iv, _ := codec.DecodeInt(ih.Encoded())
   121  	c.Assert(iv, Equals, ih.IntValue())
   122  	ih2 := ih.Next()
   123  	c.Assert(ih2.IntValue(), Equals, int64(101))
   124  	c.Assert(ih.Equal(ih2), IsFalse)
   125  	c.Assert(ih.Compare(ih2), Equals, -1)
   126  	c.Assert(ih.String(), Equals, "100")
   127  	ch := mustNewCommonHandle(c, 100, "abc")
   128  	c.Assert(ch.IsInt(), IsFalse)
   129  	ch2 := ch.Next()
   130  	c.Assert(ch.Equal(ch2), IsFalse)
   131  	c.Assert(ch.Compare(ch2), Equals, -1)
   132  	c.Assert(ch2.Encoded(), HasLen, len(ch.Encoded()))
   133  	c.Assert(ch.NumDefCauss(), Equals, 2)
   134  	_, d, err := codec.DecodeOne(ch.EncodedDefCaus(0))
   135  	c.Assert(err, IsNil)
   136  	c.Assert(d.GetInt64(), Equals, int64(100))
   137  	_, d, err = codec.DecodeOne(ch.EncodedDefCaus(1))
   138  	c.Assert(err, IsNil)
   139  	c.Assert(d.GetString(), Equals, "abc")
   140  	c.Assert(ch.String(), Equals, "{100, abc}")
   141  }
   142  
   143  func (s *testKeySuite) TestPaddingHandle(c *C) {
   144  	dec := types.NewDecFromInt(1)
   145  	encoded, err := codec.EncodeKey(new(stmtctx.StatementContext), nil, types.NewDecimalCauset(dec))
   146  	c.Assert(err, IsNil)
   147  	c.Assert(len(encoded), Less, 9)
   148  	handle, err := NewCommonHandle(encoded)
   149  	c.Assert(err, IsNil)
   150  	c.Assert(handle.Encoded(), HasLen, 9)
   151  	c.Assert(handle.EncodedDefCaus(0), BytesEquals, encoded)
   152  	newHandle, err := NewCommonHandle(handle.Encoded())
   153  	c.Assert(err, IsNil)
   154  	c.Assert(newHandle.EncodedDefCaus(0), BytesEquals, handle.EncodedDefCaus(0))
   155  }
   156  
   157  func (s *testKeySuite) TestHandleMap(c *C) {
   158  	m := NewHandleMap()
   159  	h := IntHandle(1)
   160  	m.Set(h, 1)
   161  	v, ok := m.Get(h)
   162  	c.Assert(ok, IsTrue)
   163  	c.Assert(v, Equals, 1)
   164  	m.Delete(h)
   165  	v, ok = m.Get(h)
   166  	c.Assert(ok, IsFalse)
   167  	c.Assert(v, IsNil)
   168  	ch := mustNewCommonHandle(c, 100, "abc")
   169  	m.Set(ch, "a")
   170  	v, ok = m.Get(ch)
   171  	c.Assert(ok, IsTrue)
   172  	c.Assert(v, Equals, "a")
   173  	m.Delete(ch)
   174  	v, ok = m.Get(ch)
   175  	c.Assert(ok, IsFalse)
   176  	c.Assert(v, IsNil)
   177  	m.Set(ch, "a")
   178  	ch2 := mustNewCommonHandle(c, 101, "abc")
   179  	m.Set(ch2, "b")
   180  	ch3 := mustNewCommonHandle(c, 99, "def")
   181  	m.Set(ch3, "c")
   182  	c.Assert(m.Len(), Equals, 3)
   183  	cnt := 0
   184  	m.Range(func(h Handle, val interface{}) bool {
   185  		cnt++
   186  		if h.Equal(ch) {
   187  			c.Assert(val, Equals, "a")
   188  		} else if h.Equal(ch2) {
   189  			c.Assert(val, Equals, "b")
   190  		} else {
   191  			c.Assert(val, Equals, "c")
   192  		}
   193  		if cnt == 2 {
   194  			return false
   195  		}
   196  		return true
   197  	})
   198  	c.Assert(cnt, Equals, 2)
   199  }
   200  
   201  func mustNewCommonHandle(c *C, values ...interface{}) *CommonHandle {
   202  	encoded, err := codec.EncodeKey(new(stmtctx.StatementContext), nil, types.MakeCausets(values...)...)
   203  	c.Assert(err, IsNil)
   204  	ch, err := NewCommonHandle(encoded)
   205  	c.Assert(err, IsNil)
   206  	return ch
   207  }
   208  
   209  func BenchmarkIsPoint(b *testing.B) {
   210  	b.ReportAllocs()
   211  	kr := KeyRange{
   212  		StartKey: []byte("rowkey1"),
   213  		EndKey:   []byte("rowkey2"),
   214  	}
   215  	for i := 0; i < b.N; i++ {
   216  		kr.IsPoint()
   217  	}
   218  }