]>
Commit | Line | Data |
---|---|---|
1 | start_server {tags {"hash"}} { | |
2 | test {HSET/HLEN - Small hash creation} { | |
3 | array set smallhash {} | |
4 | for {set i 0} {$i < 8} {incr i} { | |
5 | set key [randstring 0 8 alpha] | |
6 | set val [randstring 0 8 alpha] | |
7 | if {[info exists smallhash($key)]} { | |
8 | incr i -1 | |
9 | continue | |
10 | } | |
11 | r hset smallhash $key $val | |
12 | set smallhash($key) $val | |
13 | } | |
14 | list [r hlen smallhash] | |
15 | } {8} | |
16 | ||
17 | test {Is the small hash encoded with a ziplist?} { | |
18 | assert_encoding ziplist smallhash | |
19 | } | |
20 | ||
21 | test {HSET/HLEN - Big hash creation} { | |
22 | array set bighash {} | |
23 | for {set i 0} {$i < 1024} {incr i} { | |
24 | set key [randstring 0 8 alpha] | |
25 | set val [randstring 0 8 alpha] | |
26 | if {[info exists bighash($key)]} { | |
27 | incr i -1 | |
28 | continue | |
29 | } | |
30 | r hset bighash $key $val | |
31 | set bighash($key) $val | |
32 | } | |
33 | list [r hlen bighash] | |
34 | } {1024} | |
35 | ||
36 | test {Is the big hash encoded with a ziplist?} { | |
37 | assert_encoding hashtable bighash | |
38 | } | |
39 | ||
40 | test {HGET against the small hash} { | |
41 | set err {} | |
42 | foreach k [array names smallhash *] { | |
43 | if {$smallhash($k) ne [r hget smallhash $k]} { | |
44 | set err "$smallhash($k) != [r hget smallhash $k]" | |
45 | break | |
46 | } | |
47 | } | |
48 | set _ $err | |
49 | } {} | |
50 | ||
51 | test {HGET against the big hash} { | |
52 | set err {} | |
53 | foreach k [array names bighash *] { | |
54 | if {$bighash($k) ne [r hget bighash $k]} { | |
55 | set err "$bighash($k) != [r hget bighash $k]" | |
56 | break | |
57 | } | |
58 | } | |
59 | set _ $err | |
60 | } {} | |
61 | ||
62 | test {HGET against non existing key} { | |
63 | set rv {} | |
64 | lappend rv [r hget smallhash __123123123__] | |
65 | lappend rv [r hget bighash __123123123__] | |
66 | set _ $rv | |
67 | } {{} {}} | |
68 | ||
69 | test {HSET in update and insert mode} { | |
70 | set rv {} | |
71 | set k [lindex [array names smallhash *] 0] | |
72 | lappend rv [r hset smallhash $k newval1] | |
73 | set smallhash($k) newval1 | |
74 | lappend rv [r hget smallhash $k] | |
75 | lappend rv [r hset smallhash __foobar123__ newval] | |
76 | set k [lindex [array names bighash *] 0] | |
77 | lappend rv [r hset bighash $k newval2] | |
78 | set bighash($k) newval2 | |
79 | lappend rv [r hget bighash $k] | |
80 | lappend rv [r hset bighash __foobar123__ newval] | |
81 | lappend rv [r hdel smallhash __foobar123__] | |
82 | lappend rv [r hdel bighash __foobar123__] | |
83 | set _ $rv | |
84 | } {0 newval1 1 0 newval2 1 1 1} | |
85 | ||
86 | test {HSETNX target key missing - small hash} { | |
87 | r hsetnx smallhash __123123123__ foo | |
88 | r hget smallhash __123123123__ | |
89 | } {foo} | |
90 | ||
91 | test {HSETNX target key exists - small hash} { | |
92 | r hsetnx smallhash __123123123__ bar | |
93 | set result [r hget smallhash __123123123__] | |
94 | r hdel smallhash __123123123__ | |
95 | set _ $result | |
96 | } {foo} | |
97 | ||
98 | test {HSETNX target key missing - big hash} { | |
99 | r hsetnx bighash __123123123__ foo | |
100 | r hget bighash __123123123__ | |
101 | } {foo} | |
102 | ||
103 | test {HSETNX target key exists - big hash} { | |
104 | r hsetnx bighash __123123123__ bar | |
105 | set result [r hget bighash __123123123__] | |
106 | r hdel bighash __123123123__ | |
107 | set _ $result | |
108 | } {foo} | |
109 | ||
110 | test {HMSET wrong number of args} { | |
111 | catch {r hmset smallhash key1 val1 key2} err | |
112 | format $err | |
113 | } {*wrong number*} | |
114 | ||
115 | test {HMSET - small hash} { | |
116 | set args {} | |
117 | foreach {k v} [array get smallhash] { | |
118 | set newval [randstring 0 8 alpha] | |
119 | set smallhash($k) $newval | |
120 | lappend args $k $newval | |
121 | } | |
122 | r hmset smallhash {*}$args | |
123 | } {OK} | |
124 | ||
125 | test {HMSET - big hash} { | |
126 | set args {} | |
127 | foreach {k v} [array get bighash] { | |
128 | set newval [randstring 0 8 alpha] | |
129 | set bighash($k) $newval | |
130 | lappend args $k $newval | |
131 | } | |
132 | r hmset bighash {*}$args | |
133 | } {OK} | |
134 | ||
135 | test {HMGET against non existing key and fields} { | |
136 | set rv {} | |
137 | lappend rv [r hmget doesntexist __123123123__ __456456456__] | |
138 | lappend rv [r hmget smallhash __123123123__ __456456456__] | |
139 | lappend rv [r hmget bighash __123123123__ __456456456__] | |
140 | set _ $rv | |
141 | } {{{} {}} {{} {}} {{} {}}} | |
142 | ||
143 | test {HMGET against wrong type} { | |
144 | r set wrongtype somevalue | |
145 | assert_error "*wrong*" {r hmget wrongtype field1 field2} | |
146 | } | |
147 | ||
148 | test {HMGET - small hash} { | |
149 | set keys {} | |
150 | set vals {} | |
151 | foreach {k v} [array get smallhash] { | |
152 | lappend keys $k | |
153 | lappend vals $v | |
154 | } | |
155 | set err {} | |
156 | set result [r hmget smallhash {*}$keys] | |
157 | if {$vals ne $result} { | |
158 | set err "$vals != $result" | |
159 | break | |
160 | } | |
161 | set _ $err | |
162 | } {} | |
163 | ||
164 | test {HMGET - big hash} { | |
165 | set keys {} | |
166 | set vals {} | |
167 | foreach {k v} [array get bighash] { | |
168 | lappend keys $k | |
169 | lappend vals $v | |
170 | } | |
171 | set err {} | |
172 | set result [r hmget bighash {*}$keys] | |
173 | if {$vals ne $result} { | |
174 | set err "$vals != $result" | |
175 | break | |
176 | } | |
177 | set _ $err | |
178 | } {} | |
179 | ||
180 | test {HKEYS - small hash} { | |
181 | lsort [r hkeys smallhash] | |
182 | } [lsort [array names smallhash *]] | |
183 | ||
184 | test {HKEYS - big hash} { | |
185 | lsort [r hkeys bighash] | |
186 | } [lsort [array names bighash *]] | |
187 | ||
188 | test {HVALS - small hash} { | |
189 | set vals {} | |
190 | foreach {k v} [array get smallhash] { | |
191 | lappend vals $v | |
192 | } | |
193 | set _ [lsort $vals] | |
194 | } [lsort [r hvals smallhash]] | |
195 | ||
196 | test {HVALS - big hash} { | |
197 | set vals {} | |
198 | foreach {k v} [array get bighash] { | |
199 | lappend vals $v | |
200 | } | |
201 | set _ [lsort $vals] | |
202 | } [lsort [r hvals bighash]] | |
203 | ||
204 | test {HGETALL - small hash} { | |
205 | lsort [r hgetall smallhash] | |
206 | } [lsort [array get smallhash]] | |
207 | ||
208 | test {HGETALL - big hash} { | |
209 | lsort [r hgetall bighash] | |
210 | } [lsort [array get bighash]] | |
211 | ||
212 | test {HDEL and return value} { | |
213 | set rv {} | |
214 | lappend rv [r hdel smallhash nokey] | |
215 | lappend rv [r hdel bighash nokey] | |
216 | set k [lindex [array names smallhash *] 0] | |
217 | lappend rv [r hdel smallhash $k] | |
218 | lappend rv [r hdel smallhash $k] | |
219 | lappend rv [r hget smallhash $k] | |
220 | unset smallhash($k) | |
221 | set k [lindex [array names bighash *] 0] | |
222 | lappend rv [r hdel bighash $k] | |
223 | lappend rv [r hdel bighash $k] | |
224 | lappend rv [r hget bighash $k] | |
225 | unset bighash($k) | |
226 | set _ $rv | |
227 | } {0 0 1 0 {} 1 0 {}} | |
228 | ||
229 | test {HDEL - more than a single value} { | |
230 | set rv {} | |
231 | r del myhash | |
232 | r hmset myhash a 1 b 2 c 3 | |
233 | assert_equal 0 [r hdel myhash x y] | |
234 | assert_equal 2 [r hdel myhash a c f] | |
235 | r hgetall myhash | |
236 | } {b 2} | |
237 | ||
238 | test {HDEL - hash becomes empty before deleting all specified fields} { | |
239 | r del myhash | |
240 | r hmset myhash a 1 b 2 c 3 | |
241 | assert_equal 3 [r hdel myhash a b c d e] | |
242 | assert_equal 0 [r exists myhash] | |
243 | } | |
244 | ||
245 | test {HEXISTS} { | |
246 | set rv {} | |
247 | set k [lindex [array names smallhash *] 0] | |
248 | lappend rv [r hexists smallhash $k] | |
249 | lappend rv [r hexists smallhash nokey] | |
250 | set k [lindex [array names bighash *] 0] | |
251 | lappend rv [r hexists bighash $k] | |
252 | lappend rv [r hexists bighash nokey] | |
253 | } {1 0 1 0} | |
254 | ||
255 | test {Is a ziplist encoded Hash promoted on big payload?} { | |
256 | r hset smallhash foo [string repeat a 1024] | |
257 | r debug object smallhash | |
258 | } {*hashtable*} | |
259 | ||
260 | test {HINCRBY against non existing database key} { | |
261 | r del htest | |
262 | list [r hincrby htest foo 2] | |
263 | } {2} | |
264 | ||
265 | test {HINCRBY against non existing hash key} { | |
266 | set rv {} | |
267 | r hdel smallhash tmp | |
268 | r hdel bighash tmp | |
269 | lappend rv [r hincrby smallhash tmp 2] | |
270 | lappend rv [r hget smallhash tmp] | |
271 | lappend rv [r hincrby bighash tmp 2] | |
272 | lappend rv [r hget bighash tmp] | |
273 | } {2 2 2 2} | |
274 | ||
275 | test {HINCRBY against hash key created by hincrby itself} { | |
276 | set rv {} | |
277 | lappend rv [r hincrby smallhash tmp 3] | |
278 | lappend rv [r hget smallhash tmp] | |
279 | lappend rv [r hincrby bighash tmp 3] | |
280 | lappend rv [r hget bighash tmp] | |
281 | } {5 5 5 5} | |
282 | ||
283 | test {HINCRBY against hash key originally set with HSET} { | |
284 | r hset smallhash tmp 100 | |
285 | r hset bighash tmp 100 | |
286 | list [r hincrby smallhash tmp 2] [r hincrby bighash tmp 2] | |
287 | } {102 102} | |
288 | ||
289 | test {HINCRBY over 32bit value} { | |
290 | r hset smallhash tmp 17179869184 | |
291 | r hset bighash tmp 17179869184 | |
292 | list [r hincrby smallhash tmp 1] [r hincrby bighash tmp 1] | |
293 | } {17179869185 17179869185} | |
294 | ||
295 | test {HINCRBY over 32bit value with over 32bit increment} { | |
296 | r hset smallhash tmp 17179869184 | |
297 | r hset bighash tmp 17179869184 | |
298 | list [r hincrby smallhash tmp 17179869184] [r hincrby bighash tmp 17179869184] | |
299 | } {34359738368 34359738368} | |
300 | ||
301 | test {HINCRBY fails against hash value with spaces (left)} { | |
302 | r hset smallhash str " 11" | |
303 | r hset bighash str " 11" | |
304 | catch {r hincrby smallhash str 1} smallerr | |
305 | catch {r hincrby smallhash str 1} bigerr | |
306 | set rv {} | |
307 | lappend rv [string match "ERR*not an integer*" $smallerr] | |
308 | lappend rv [string match "ERR*not an integer*" $bigerr] | |
309 | } {1 1} | |
310 | ||
311 | test {HINCRBY fails against hash value with spaces (right)} { | |
312 | r hset smallhash str "11 " | |
313 | r hset bighash str "11 " | |
314 | catch {r hincrby smallhash str 1} smallerr | |
315 | catch {r hincrby smallhash str 1} bigerr | |
316 | set rv {} | |
317 | lappend rv [string match "ERR*not an integer*" $smallerr] | |
318 | lappend rv [string match "ERR*not an integer*" $bigerr] | |
319 | } {1 1} | |
320 | ||
321 | test {HINCRBY can detect overflows} { | |
322 | set e {} | |
323 | r hset hash n -9223372036854775484 | |
324 | assert {[r hincrby hash n -1] == -9223372036854775485} | |
325 | catch {r hincrby hash n -10000} e | |
326 | set e | |
327 | } {*overflow*} | |
328 | ||
329 | test {HINCRBYFLOAT against non existing database key} { | |
330 | r del htest | |
331 | list [r hincrbyfloat htest foo 2.5] | |
332 | } {2.5} | |
333 | ||
334 | test {HINCRBYFLOAT against non existing hash key} { | |
335 | set rv {} | |
336 | r hdel smallhash tmp | |
337 | r hdel bighash tmp | |
338 | lappend rv [roundFloat [r hincrbyfloat smallhash tmp 2.5]] | |
339 | lappend rv [roundFloat [r hget smallhash tmp]] | |
340 | lappend rv [roundFloat [r hincrbyfloat bighash tmp 2.5]] | |
341 | lappend rv [roundFloat [r hget bighash tmp]] | |
342 | } {2.5 2.5 2.5 2.5} | |
343 | ||
344 | test {HINCRBYFLOAT against hash key created by hincrby itself} { | |
345 | set rv {} | |
346 | lappend rv [roundFloat [r hincrbyfloat smallhash tmp 3.5]] | |
347 | lappend rv [roundFloat [r hget smallhash tmp]] | |
348 | lappend rv [roundFloat [r hincrbyfloat bighash tmp 3.5]] | |
349 | lappend rv [roundFloat [r hget bighash tmp]] | |
350 | } {6 6 6 6} | |
351 | ||
352 | test {HINCRBYFLOAT against hash key originally set with HSET} { | |
353 | r hset smallhash tmp 100 | |
354 | r hset bighash tmp 100 | |
355 | list [roundFloat [r hincrbyfloat smallhash tmp 2.5]] \ | |
356 | [roundFloat [r hincrbyfloat bighash tmp 2.5]] | |
357 | } {102.5 102.5} | |
358 | ||
359 | test {HINCRBYFLOAT over 32bit value} { | |
360 | r hset smallhash tmp 17179869184 | |
361 | r hset bighash tmp 17179869184 | |
362 | list [r hincrbyfloat smallhash tmp 1] \ | |
363 | [r hincrbyfloat bighash tmp 1] | |
364 | } {17179869185 17179869185} | |
365 | ||
366 | test {HINCRBYFLOAT over 32bit value with over 32bit increment} { | |
367 | r hset smallhash tmp 17179869184 | |
368 | r hset bighash tmp 17179869184 | |
369 | list [r hincrbyfloat smallhash tmp 17179869184] \ | |
370 | [r hincrbyfloat bighash tmp 17179869184] | |
371 | } {34359738368 34359738368} | |
372 | ||
373 | test {HINCRBYFLOAT fails against hash value with spaces (left)} { | |
374 | r hset smallhash str " 11" | |
375 | r hset bighash str " 11" | |
376 | catch {r hincrbyfloat smallhash str 1} smallerr | |
377 | catch {r hincrbyfloat smallhash str 1} bigerr | |
378 | set rv {} | |
379 | lappend rv [string match "ERR*not*float*" $smallerr] | |
380 | lappend rv [string match "ERR*not*float*" $bigerr] | |
381 | } {1 1} | |
382 | ||
383 | test {HINCRBYFLOAT fails against hash value with spaces (right)} { | |
384 | r hset smallhash str "11 " | |
385 | r hset bighash str "11 " | |
386 | catch {r hincrbyfloat smallhash str 1} smallerr | |
387 | catch {r hincrbyfloat smallhash str 1} bigerr | |
388 | set rv {} | |
389 | lappend rv [string match "ERR*not*float*" $smallerr] | |
390 | lappend rv [string match "ERR*not*float*" $bigerr] | |
391 | } {1 1} | |
392 | ||
393 | test {Hash ziplist regression test for large keys} { | |
394 | r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk a | |
395 | r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk b | |
396 | r hget hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk | |
397 | } {b} | |
398 | ||
399 | foreach size {10 512} { | |
400 | test "Hash fuzzing #1 - $size fields" { | |
401 | for {set times 0} {$times < 10} {incr times} { | |
402 | catch {unset hash} | |
403 | array set hash {} | |
404 | r del hash | |
405 | ||
406 | # Create | |
407 | for {set j 0} {$j < $size} {incr j} { | |
408 | set field [randomValue] | |
409 | set value [randomValue] | |
410 | r hset hash $field $value | |
411 | set hash($field) $value | |
412 | } | |
413 | ||
414 | # Verify | |
415 | foreach {k v} [array get hash] { | |
416 | assert_equal $v [r hget hash $k] | |
417 | } | |
418 | assert_equal [array size hash] [r hlen hash] | |
419 | } | |
420 | } | |
421 | ||
422 | test "Hash fuzzing #2 - $size fields" { | |
423 | for {set times 0} {$times < 10} {incr times} { | |
424 | catch {unset hash} | |
425 | array set hash {} | |
426 | r del hash | |
427 | ||
428 | # Create | |
429 | for {set j 0} {$j < $size} {incr j} { | |
430 | randpath { | |
431 | set field [randomValue] | |
432 | set value [randomValue] | |
433 | r hset hash $field $value | |
434 | set hash($field) $value | |
435 | } { | |
436 | set field [randomSignedInt 512] | |
437 | set value [randomSignedInt 512] | |
438 | r hset hash $field $value | |
439 | set hash($field) $value | |
440 | } { | |
441 | randpath { | |
442 | set field [randomValue] | |
443 | } { | |
444 | set field [randomSignedInt 512] | |
445 | } | |
446 | r hdel hash $field | |
447 | unset -nocomplain hash($field) | |
448 | } | |
449 | } | |
450 | ||
451 | # Verify | |
452 | foreach {k v} [array get hash] { | |
453 | assert_equal $v [r hget hash $k] | |
454 | } | |
455 | assert_equal [array size hash] [r hlen hash] | |
456 | } | |
457 | } | |
458 | } | |
459 | ||
460 | test {Stress test the hash ziplist -> hashtable encoding conversion} { | |
461 | r config set hash-max-ziplist-entries 32 | |
462 | for {set j 0} {$j < 100} {incr j} { | |
463 | r del myhash | |
464 | for {set i 0} {$i < 64} {incr i} { | |
465 | r hset myhash [randomValue] [randomValue] | |
466 | } | |
467 | assert {[r object encoding myhash] eq {hashtable}} | |
468 | } | |
469 | } | |
470 | } |