github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/einsteindb/scan_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 einsteindb 15 16 import ( 17 "bytes" 18 "context" 19 "fmt" 20 21 . "github.com/whtcorpsinc/check" 22 "github.com/whtcorpsinc/milevadb/blockcodec" 23 "github.com/whtcorpsinc/milevadb/ekv" 24 "github.com/whtcorpsinc/milevadb/soliton/logutil" 25 "github.com/whtcorpsinc/milevadb/soliton/rowcodec" 26 "github.com/whtcorpsinc/milevadb/stochastikctx" 27 "go.uber.org/zap" 28 ) 29 30 type testScanSuite struct { 31 OneByOneSuite 32 causetstore *einsteindbStore 33 recordPrefix []byte 34 rowNums []int 35 ctx context.Context 36 } 37 38 var _ = SerialSuites(&testScanSuite{}) 39 40 func (s *testScanSuite) SetUpSuite(c *C) { 41 s.OneByOneSuite.SetUpSuite(c) 42 s.causetstore = NewTestStore(c).(*einsteindbStore) 43 s.recordPrefix = blockcodec.GenTableRecordPrefix(1) 44 s.rowNums = append(s.rowNums, 1, scanBatchSize, scanBatchSize+1, scanBatchSize*3) 45 // Avoid using async commit logic. 46 s.ctx = context.WithValue(context.Background(), stochastikctx.ConnID, uint64(0)) 47 } 48 49 func (s *testScanSuite) TearDownSuite(c *C) { 50 txn := s.beginTxn(c) 51 scanner, err := txn.Iter(s.recordPrefix, nil) 52 c.Assert(err, IsNil) 53 c.Assert(scanner, NotNil) 54 for scanner.Valid() { 55 k := scanner.Key() 56 err = txn.Delete(k) 57 c.Assert(err, IsNil) 58 scanner.Next() 59 } 60 err = txn.Commit(s.ctx) 61 c.Assert(err, IsNil) 62 err = s.causetstore.Close() 63 c.Assert(err, IsNil) 64 s.OneByOneSuite.TearDownSuite(c) 65 } 66 67 func (s *testScanSuite) beginTxn(c *C) *einsteindbTxn { 68 txn, err := s.causetstore.Begin() 69 c.Assert(err, IsNil) 70 return txn.(*einsteindbTxn) 71 } 72 73 func (s *testScanSuite) TestScan(c *C) { 74 check := func(c *C, scan ekv.Iterator, rowNum int, keyOnly bool) { 75 for i := 0; i < rowNum; i++ { 76 k := scan.Key() 77 expectedKey := blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(i)) 78 if ok := bytes.Equal([]byte(k), []byte(expectedKey)); !ok { 79 logutil.BgLogger().Error("bytes equal check fail", 80 zap.Int("i", i), 81 zap.Int("rowNum", rowNum), 82 zap.Stringer("obtained key", k), 83 zap.Stringer("obtained val", ekv.Key(scan.Value())), 84 zap.Stringer("expected", expectedKey), 85 zap.Bool("keyOnly", keyOnly)) 86 } 87 c.Assert([]byte(k), BytesEquals, []byte(expectedKey)) 88 if !keyOnly { 89 v := scan.Value() 90 c.Assert(v, BytesEquals, genValueBytes(i)) 91 } 92 // Because newScan return first item without calling scan.Next() just like go-hbase, 93 // for-loop count will decrease 1. 94 if i < rowNum-1 { 95 scan.Next() 96 } 97 } 98 scan.Next() 99 c.Assert(scan.Valid(), IsFalse) 100 } 101 102 for _, rowNum := range s.rowNums { 103 txn := s.beginTxn(c) 104 for i := 0; i < rowNum; i++ { 105 err := txn.Set(blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(i)), genValueBytes(i)) 106 c.Assert(err, IsNil) 107 } 108 err := txn.Commit(s.ctx) 109 c.Assert(err, IsNil) 110 mockTableID := int64(999) 111 if rowNum > 123 { 112 _, err = s.causetstore.SplitRegions(s.ctx, [][]byte{blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(123))}, false, &mockTableID) 113 c.Assert(err, IsNil) 114 } 115 116 if rowNum > 456 { 117 _, err = s.causetstore.SplitRegions(s.ctx, [][]byte{blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(456))}, false, &mockTableID) 118 c.Assert(err, IsNil) 119 } 120 121 txn2 := s.beginTxn(c) 122 val, err := txn2.Get(context.TODO(), blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(0))) 123 c.Assert(err, IsNil) 124 c.Assert(val, BytesEquals, genValueBytes(0)) 125 // Test scan without upperBound 126 scan, err := txn2.Iter(s.recordPrefix, nil) 127 c.Assert(err, IsNil) 128 check(c, scan, rowNum, false) 129 // Test scan with upperBound 130 upperBound := rowNum / 2 131 scan, err = txn2.Iter(s.recordPrefix, blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(upperBound))) 132 c.Assert(err, IsNil) 133 check(c, scan, upperBound, false) 134 135 txn3 := s.beginTxn(c) 136 txn3.SetOption(ekv.KeyOnly, true) 137 // Test scan without upper bound 138 scan, err = txn3.Iter(s.recordPrefix, nil) 139 c.Assert(err, IsNil) 140 check(c, scan, rowNum, true) 141 // test scan with upper bound 142 scan, err = txn3.Iter(s.recordPrefix, blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(upperBound))) 143 c.Assert(err, IsNil) 144 check(c, scan, upperBound, true) 145 146 // Restore KeyOnly to false 147 txn3.SetOption(ekv.KeyOnly, false) 148 scan, err = txn3.Iter(s.recordPrefix, nil) 149 c.Assert(err, IsNil) 150 check(c, scan, rowNum, true) 151 // test scan with upper bound 152 scan, err = txn3.Iter(s.recordPrefix, blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(upperBound))) 153 c.Assert(err, IsNil) 154 check(c, scan, upperBound, true) 155 } 156 } 157 158 func genValueBytes(i int) []byte { 159 var res = []byte{rowcodec.CodecVer} 160 res = append(res, []byte(fmt.Sprintf("%d", i))...) 161 return res 162 }