github.com/KinWaiYuen/client-go/v2@v2.5.4/internal/unionstore/memdb_norace_test.go (about) 1 // Copyright 2021 TiKV Authors 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 // NOTE: The code in this file is based on code from the 16 // TiDB project, licensed under the Apache License v 2.0 17 // 18 // https://github.com/pingcap/tidb/tree/cc5e161ac06827589c4966674597c137cc9e809c/store/tikv/unionstore/memdb_norace_test.go 19 // 20 21 // Copyright 2020 PingCAP, Inc. 22 // 23 // Licensed under the Apache License, Version 2.0 (the "License"); 24 // you may not use this file except in compliance with the License. 25 // You may obtain a copy of the License at 26 // 27 // http://www.apache.org/licenses/LICENSE-2.0 28 // 29 // Unless required by applicable law or agreed to in writing, software 30 // distributed under the License is distributed on an "AS IS" BASIS, 31 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 // See the License for the specific language governing permissions and 33 // limitations under the License. 34 35 // +build !race 36 37 package unionstore 38 39 import ( 40 "encoding/binary" 41 "math/rand" 42 "testing" 43 44 "github.com/pingcap/goleveldb/leveldb/comparer" 45 leveldb "github.com/pingcap/goleveldb/leveldb/memdb" 46 "github.com/stretchr/testify/require" 47 ) 48 49 // The test takes too long under the race detector. 50 func TestRandom(t *testing.T) { 51 require := require.New(t) 52 53 const cnt = 50000 54 keys := make([][]byte, cnt) 55 for i := range keys { 56 keys[i] = make([]byte, rand.Intn(19)+1) 57 rand.Read(keys[i]) 58 } 59 60 p1 := newMemDB() 61 p2 := leveldb.New(comparer.DefaultComparer, 4*1024) 62 for _, k := range keys { 63 p1.Set(k, k) 64 _ = p2.Put(k, k) 65 } 66 67 require.Equal(p1.Len(), p2.Len()) 68 require.Equal(p1.Size(), p2.Size()) 69 70 rand.Shuffle(cnt, func(i, j int) { keys[i], keys[j] = keys[j], keys[i] }) 71 72 for _, k := range keys { 73 op := rand.Float64() 74 if op < 0.35 { 75 p1.DeleteKey(k) 76 p2.Delete(k) 77 } else { 78 newValue := make([]byte, rand.Intn(19)+1) 79 rand.Read(newValue) 80 p1.Set(k, newValue) 81 _ = p2.Put(k, newValue) 82 } 83 } 84 checkConsist(t, p1, p2) 85 } 86 87 // The test takes too long under the race detector. 88 func TestRandomDerive(t *testing.T) { 89 db := newMemDB() 90 golden := leveldb.New(comparer.DefaultComparer, 4*1024) 91 testRandomDeriveRecur(t, db, golden, 0) 92 } 93 94 func testRandomDeriveRecur(t *testing.T, db *MemDB, golden *leveldb.DB, depth int) [][2][]byte { 95 var keys [][]byte 96 if op := rand.Float64(); op < 0.33 { 97 start, end := rand.Intn(512), rand.Intn(512)+512 98 cnt := end - start 99 keys = make([][]byte, cnt) 100 for i := range keys { 101 keys[i] = make([]byte, 8) 102 binary.BigEndian.PutUint64(keys[i], uint64(start+i)) 103 } 104 } else if op < 0.66 { 105 keys = make([][]byte, rand.Intn(512)+512) 106 for i := range keys { 107 keys[i] = make([]byte, rand.Intn(19)+1) 108 rand.Read(keys[i]) 109 } 110 } else { 111 keys = make([][]byte, 512) 112 for i := range keys { 113 keys[i] = make([]byte, 8) 114 binary.BigEndian.PutUint64(keys[i], uint64(i)) 115 } 116 } 117 118 vals := make([][]byte, len(keys)) 119 for i := range vals { 120 vals[i] = make([]byte, rand.Intn(255)+1) 121 rand.Read(vals[i]) 122 } 123 124 h := db.Staging() 125 opLog := make([][2][]byte, 0, len(keys)) 126 for i := range keys { 127 db.Set(keys[i], vals[i]) 128 old, err := golden.Get(keys[i]) 129 if err != nil { 130 opLog = append(opLog, [2][]byte{keys[i], nil}) 131 } else { 132 opLog = append(opLog, [2][]byte{keys[i], old}) 133 } 134 golden.Put(keys[i], vals[i]) 135 } 136 137 if depth < 100 { 138 childOps := testRandomDeriveRecur(t, db, golden, depth+1) 139 opLog = append(opLog, childOps...) 140 } 141 142 if rand.Float64() < 0.3 && depth > 0 { 143 db.Cleanup(h) 144 for i := len(opLog) - 1; i >= 0; i-- { 145 if opLog[i][1] == nil { 146 golden.Delete(opLog[i][0]) 147 } else { 148 golden.Put(opLog[i][0], opLog[i][1]) 149 } 150 } 151 opLog = nil 152 } else { 153 db.Release(h) 154 } 155 156 if depth%10 == 0 { 157 checkConsist(t, db, golden) 158 } 159 160 return opLog 161 }