github.com/nutsdb/nutsdb@v1.0.4/list_test.go (about) 1 // Copyright 2023 The PromiseDB Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file expect in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package nutsdb 15 16 import ( 17 "bytes" 18 "math/rand" 19 "testing" 20 "time" 21 22 "github.com/stretchr/testify/require" 23 ) 24 25 func ListPush(t *testing.T, list *List, key string, r *Record, isLeft bool, expectError error) { 26 var e error 27 if isLeft { 28 e = list.LPush(key, r) 29 } else { 30 e = list.RPush(key, r) 31 } 32 assertErr(t, e, expectError) 33 } 34 35 func ListPop(t *testing.T, list *List, key string, isLeft bool, expectVal *Record, expectError error) { 36 var ( 37 e error 38 r *Record 39 ) 40 41 if isLeft { 42 r, e = list.LPop(key) 43 } else { 44 r, e = list.RPop(key) 45 } 46 if expectError != nil { 47 require.Equal(t, expectError, e) 48 } else { 49 require.NoError(t, e) 50 require.Equal(t, expectVal, r) 51 } 52 } 53 54 func ListCmp(t *testing.T, list *List, key string, expectRecords []*Record, isReverse bool) { 55 records, err := list.LRange(key, 0, -1) 56 require.NoError(t, err) 57 58 if isReverse { 59 for i := len(expectRecords) - 1; i >= 0; i-- { 60 require.Equal(t, expectRecords[i], records[len(expectRecords)-1-i]) 61 } 62 } else { 63 for i := 0; i < len(expectRecords); i++ { 64 require.Equal(t, expectRecords[i], records[i]) 65 } 66 } 67 } 68 69 func TestList_LPush(t *testing.T) { 70 list := NewList() 71 // 测试 LPush 72 key := string(GetTestBytes(0)) 73 expectRecords := generateRecords(5) 74 seqInfo := HeadTailSeq{Head: initialListSeq, Tail: initialListSeq + 1} 75 76 for i := 0; i < len(expectRecords); i++ { 77 seq := generateSeq(&seqInfo, true) 78 newKey := encodeListKey([]byte(key), seq) 79 expectRecords[i].Key = newKey 80 ListPush(t, list, string(newKey), expectRecords[i], true, nil) 81 } 82 83 ListCmp(t, list, key, expectRecords, true) 84 } 85 86 func TestList_RPush(t *testing.T) { 87 list := NewList() 88 expectRecords := generateRecords(5) 89 key := string(GetTestBytes(0)) 90 seqInfo := HeadTailSeq{Head: initialListSeq, Tail: initialListSeq + 1} 91 92 for i := 0; i < len(expectRecords); i++ { 93 seq := generateSeq(&seqInfo, false) 94 newKey := encodeListKey([]byte(key), seq) 95 expectRecords[i].Key = newKey 96 ListPush(t, list, string(newKey), expectRecords[i], false, nil) 97 } 98 99 ListCmp(t, list, key, expectRecords, false) 100 } 101 102 func TestList_Pop(t *testing.T) { 103 list := NewList() 104 expectRecords := generateRecords(5) 105 key := string(GetTestBytes(0)) 106 107 ListPop(t, list, key, true, nil, ErrListNotFound) 108 seqInfo := HeadTailSeq{Head: initialListSeq, Tail: initialListSeq + 1} 109 110 for i := 0; i < len(expectRecords); i++ { 111 seq := generateSeq(&seqInfo, false) 112 newKey := encodeListKey([]byte(key), seq) 113 expectRecords[i].Key = newKey 114 ListPush(t, list, string(newKey), expectRecords[i], false, nil) 115 } 116 117 ListPop(t, list, key, true, expectRecords[0], nil) 118 expectRecords = expectRecords[1:] 119 120 ListPop(t, list, key, false, expectRecords[len(expectRecords)-1], nil) 121 expectRecords = expectRecords[:len(expectRecords)-1] 122 123 ListCmp(t, list, key, expectRecords, false) 124 } 125 126 func TestList_LRem(t *testing.T) { 127 list := NewList() 128 records := generateRecords(2) 129 key := string(GetTestBytes(0)) 130 seqInfo := HeadTailSeq{Head: initialListSeq, Tail: initialListSeq + 1} 131 132 for i := 0; i < 3; i++ { 133 seq := generateSeq(&seqInfo, false) 134 newKey := encodeListKey([]byte(key), seq) 135 records[0].Key = newKey 136 ListPush(t, list, string(newKey), records[0], false, nil) 137 } 138 139 seq := generateSeq(&seqInfo, false) 140 newKey := encodeListKey([]byte(key), seq) 141 records[1].Key = newKey 142 ListPush(t, list, string(newKey), records[1], false, nil) 143 144 seq = generateSeq(&seqInfo, false) 145 newKey = encodeListKey([]byte(key), seq) 146 records[0].Key = newKey 147 ListPush(t, list, string(newKey), records[0], false, nil) 148 149 seq = generateSeq(&seqInfo, false) 150 newKey = encodeListKey([]byte(key), seq) 151 records[1].Key = newKey 152 ListPush(t, list, string(newKey), records[1], false, nil) 153 154 // r1 r1 r1 r2 r1 r2 155 expectRecords := []*Record{records[0], records[0], records[0], records[1], records[0], records[1]} 156 157 cmp := func(r *Record) (bool, error) { 158 return bytes.Equal(r.Value, records[0].Value), nil 159 } 160 161 // r1 r1 r1 r2 r2 162 err := list.LRem(key, -1, cmp) 163 require.NoError(t, err) 164 expectRecords = append(expectRecords[0:4], expectRecords[5:]...) 165 ListCmp(t, list, key, expectRecords, false) 166 167 // r1 r2 r2 168 err = list.LRem(key, 2, cmp) 169 require.NoError(t, err) 170 expectRecords = expectRecords[2:] 171 ListCmp(t, list, key, expectRecords, false) 172 173 cmp = func(r *Record) (bool, error) { 174 return bytes.Equal(r.Value, records[1].Value), nil 175 } 176 177 // r1 178 err = list.LRem(key, 0, cmp) 179 require.NoError(t, err) 180 expectRecords = expectRecords[0:1] 181 ListCmp(t, list, key, expectRecords, false) 182 } 183 184 func TestList_LTrim(t *testing.T) { 185 list := NewList() 186 expectRecords := generateRecords(5) 187 key := string(GetTestBytes(0)) 188 seqInfo := HeadTailSeq{Head: initialListSeq, Tail: initialListSeq + 1} 189 190 for i := 0; i < len(expectRecords); i++ { 191 seq := generateSeq(&seqInfo, false) 192 newKey := encodeListKey([]byte(key), seq) 193 expectRecords[i].Key = newKey 194 ListPush(t, list, string(newKey), expectRecords[i], false, nil) 195 } 196 197 err := list.LTrim(key, 1, 3) 198 require.NoError(t, err) 199 expectRecords = expectRecords[1 : len(expectRecords)-1] 200 ListCmp(t, list, key, expectRecords, false) 201 } 202 203 func TestList_LRemByIndex(t *testing.T) { 204 list := NewList() 205 expectRecords := generateRecords(8) 206 key := string(GetTestBytes(0)) 207 seqInfo := HeadTailSeq{Head: initialListSeq, Tail: initialListSeq + 1} 208 209 // r1 r2 r3 r4 r5 r6 r7 r8 210 for i := 0; i < 8; i++ { 211 seq := generateSeq(&seqInfo, false) 212 newKey := encodeListKey([]byte(key), seq) 213 expectRecords[i].Key = newKey 214 ListPush(t, list, string(newKey), expectRecords[i], false, nil) 215 } 216 217 // r1 r2 r4 r5 r6 r7 r8 218 err := list.LRemByIndex(key, []int{2}) 219 require.NoError(t, err) 220 expectRecords = append(expectRecords[0:2], expectRecords[3:]...) 221 ListCmp(t, list, key, expectRecords, false) 222 223 // r2 r6 r7 r8 224 err = list.LRemByIndex(key, []int{0, 2, 3}) 225 require.NoError(t, err) 226 expectRecords = expectRecords[1:] 227 expectRecords = append(expectRecords[0:1], expectRecords[3:]...) 228 ListCmp(t, list, key, expectRecords, false) 229 230 err = list.LRemByIndex(key, []int{0, 0, 0}) 231 require.NoError(t, err) 232 expectRecords = expectRecords[1:] 233 ListCmp(t, list, key, expectRecords, false) 234 } 235 236 func generateRecords(count int) []*Record { 237 rand.Seed(time.Now().UnixNano()) 238 records := make([]*Record, count) 239 for i := 0; i < count; i++ { 240 key := GetTestBytes(i) 241 val := GetRandomBytes(24) 242 243 record := &Record{ 244 Key: key, 245 Value: val, 246 FileID: int64(i), 247 DataPos: uint64(rand.Uint32()), 248 ValueSize: uint32(len(val)), 249 Timestamp: uint64(time.Now().Unix()), 250 TTL: uint32(rand.Intn(3600)), 251 TxID: uint64(rand.Intn(1000)), 252 } 253 records[i] = record 254 } 255 return records 256 }