1start_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 __avoid_collisions__[randstring 0 8 alpha] 6 set val __avoid_collisions__[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 __avoid_collisions__[randstring 0 8 alpha] 25 set val __avoid_collisions__[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 an hash table?} { 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 {HSTRLEN against the small hash} { 394 set err {} 395 foreach k [array names smallhash *] { 396 if {[string length $smallhash($k)] ne [r hstrlen smallhash $k]} { 397 set err "[string length $smallhash($k)] != [r hstrlen smallhash $k]" 398 break 399 } 400 } 401 set _ $err 402 } {} 403 404 test {HSTRLEN against the big hash} { 405 set err {} 406 foreach k [array names bighash *] { 407 if {[string length $bighash($k)] ne [r hstrlen bighash $k]} { 408 set err "[string length $bighash($k)] != [r hstrlen bighash $k]" 409 puts "HSTRLEN and logical length mismatch:" 410 puts "key: $k" 411 puts "Logical content: $bighash($k)" 412 puts "Server content: [r hget bighash $k]" 413 } 414 } 415 set _ $err 416 } {} 417 418 test {HSTRLEN against non existing field} { 419 set rv {} 420 lappend rv [r hstrlen smallhash __123123123__] 421 lappend rv [r hstrlen bighash __123123123__] 422 set _ $rv 423 } {0 0} 424 425 test {HSTRLEN corner cases} { 426 set vals { 427 -9223372036854775808 9223372036854775807 9223372036854775808 428 {} 0 -1 x 429 } 430 foreach v $vals { 431 r hmset smallhash field $v 432 r hmset bighash field $v 433 set len1 [string length $v] 434 set len2 [r hstrlen smallhash field] 435 set len3 [r hstrlen bighash field] 436 assert {$len1 == $len2} 437 assert {$len2 == $len3} 438 } 439 } 440 441 test {Hash ziplist regression test for large keys} { 442 r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk a 443 r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk b 444 r hget hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk 445 } {b} 446 447 foreach size {10 512} { 448 test "Hash fuzzing #1 - $size fields" { 449 for {set times 0} {$times < 10} {incr times} { 450 catch {unset hash} 451 array set hash {} 452 r del hash 453 454 # Create 455 for {set j 0} {$j < $size} {incr j} { 456 set field [randomValue] 457 set value [randomValue] 458 r hset hash $field $value 459 set hash($field) $value 460 } 461 462 # Verify 463 foreach {k v} [array get hash] { 464 assert_equal $v [r hget hash $k] 465 } 466 assert_equal [array size hash] [r hlen hash] 467 } 468 } 469 470 test "Hash fuzzing #2 - $size fields" { 471 for {set times 0} {$times < 10} {incr times} { 472 catch {unset hash} 473 array set hash {} 474 r del hash 475 476 # Create 477 for {set j 0} {$j < $size} {incr j} { 478 randpath { 479 set field [randomValue] 480 set value [randomValue] 481 r hset hash $field $value 482 set hash($field) $value 483 } { 484 set field [randomSignedInt 512] 485 set value [randomSignedInt 512] 486 r hset hash $field $value 487 set hash($field) $value 488 } { 489 randpath { 490 set field [randomValue] 491 } { 492 set field [randomSignedInt 512] 493 } 494 r hdel hash $field 495 unset -nocomplain hash($field) 496 } 497 } 498 499 # Verify 500 foreach {k v} [array get hash] { 501 assert_equal $v [r hget hash $k] 502 } 503 assert_equal [array size hash] [r hlen hash] 504 } 505 } 506 } 507 508 test {Stress test the hash ziplist -> hashtable encoding conversion} { 509 r config set hash-max-ziplist-entries 32 510 for {set j 0} {$j < 100} {incr j} { 511 r del myhash 512 for {set i 0} {$i < 64} {incr i} { 513 r hset myhash [randomValue] [randomValue] 514 } 515 assert {[r object encoding myhash] eq {hashtable}} 516 } 517 } 518} 519