]> git.saurik.com Git - redis.git/blame - tests/unit/type/hash.tcl
A reimplementation of blocking operation internals.
[redis.git] / tests / unit / type / hash.tcl
CommitLineData
7f7499ee 1start_server {tags {"hash"}} {
98578b57
PN
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
ebd85e9a
PN
17 test {Is the small hash encoded with a ziplist?} {
18 assert_encoding ziplist smallhash
efc5d4cc 19 }
98578b57
PN
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
ebd85e9a 36 test {Is the big hash encoded with a ziplist?} {
3c23ee1b
PN
37 assert_encoding hashtable bighash
38 }
98578b57
PN
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
e584d82f
PN
143 test {HMGET against wrong type} {
144 r set wrongtype somevalue
145 assert_error "*wrong*" {r hmget wrongtype field1 field2}
146 }
147
98578b57
PN
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
64a13a36 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
2d7162bb
PN
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
98578b57
PN
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
ebd85e9a 255 test {Is a ziplist encoded Hash promoted on big payload?} {
98578b57
PN
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
3c5680ed 301 test {HINCRBY fails against hash value with spaces (left)} {
302 r hset smallhash str " 11"
303 r hset bighash str " 11"
98578b57
PN
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}
d6d3f92f 310
3c5680ed 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
d3473481 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
3c5680ed 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
bf758397 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]]
3c5680ed 342 } {2.5 2.5 2.5 2.5}
343
344 test {HINCRBYFLOAT against hash key created by hincrby itself} {
345 set rv {}
bf758397 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]]
cd4aba36 350 } {6 6 6 6}
3c5680ed 351
352 test {HINCRBYFLOAT against hash key originally set with HSET} {
353 r hset smallhash tmp 100
354 r hset bighash tmp 100
bf758397 355 list [roundFloat [r hincrbyfloat smallhash tmp 2.5]] \
356 [roundFloat [r hincrbyfloat bighash tmp 2.5]]
3c5680ed 357 } {102.5 102.5}
358
359 test {HINCRBYFLOAT over 32bit value} {
360 r hset smallhash tmp 17179869184
361 r hset bighash tmp 17179869184
bf758397 362 list [r hincrbyfloat smallhash tmp 1] \
363 [r hincrbyfloat bighash tmp 1]
3c5680ed 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
ebd85e9a 393 test {Hash ziplist regression test for large keys} {
d6d3f92f 394 r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk a
395 r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk b
396 r hget hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
397 } {b}
24982f2b 398
399 foreach size {10 512} {
1364395f 400 test "Hash fuzzing #1 - $size fields" {
24982f2b 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 }
1364395f 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 }
24982f2b 458 }
a85c8985 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 }
98578b57 470}