1
0

hash.tcl 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  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 __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. test {Is the small hash encoded with a listpack?} {
  17. assert_encoding listpack smallhash
  18. }
  19. proc create_hash {key entries} {
  20. r del $key
  21. foreach entry $entries {
  22. r hset $key [lindex $entry 0] [lindex $entry 1]
  23. }
  24. }
  25. proc get_keys {l} {
  26. set res {}
  27. foreach entry $l {
  28. set key [lindex $entry 0]
  29. lappend res $key
  30. }
  31. return $res
  32. }
  33. foreach {type contents} "listpack {{a 1} {b 2} {c 3}} hashtable {{a 1} {b 2} {[randstring 70 90 alpha] 3}}" {
  34. set original_max_value [lindex [r config get hash-max-ziplist-value] 1]
  35. r config set hash-max-ziplist-value 10
  36. create_hash myhash $contents
  37. assert_encoding $type myhash
  38. # coverage for objectComputeSize
  39. assert_morethan [r memory usage myhash] 0
  40. test "HRANDFIELD - $type" {
  41. unset -nocomplain myhash
  42. array set myhash {}
  43. for {set i 0} {$i < 100} {incr i} {
  44. set key [r hrandfield myhash]
  45. set myhash($key) 1
  46. }
  47. assert_equal [lsort [get_keys $contents]] [lsort [array names myhash]]
  48. }
  49. r config set hash-max-ziplist-value $original_max_value
  50. }
  51. test "HRANDFIELD with RESP3" {
  52. r hello 3
  53. set res [r hrandfield myhash 3 withvalues]
  54. assert_equal [llength $res] 3
  55. assert_equal [llength [lindex $res 1]] 2
  56. set res [r hrandfield myhash 3]
  57. assert_equal [llength $res] 3
  58. assert_equal [llength [lindex $res 1]] 1
  59. r hello 2
  60. }
  61. test "HRANDFIELD count of 0 is handled correctly" {
  62. r hrandfield myhash 0
  63. } {}
  64. test "HRANDFIELD with <count> against non existing key" {
  65. r hrandfield nonexisting_key 100
  66. } {}
  67. # Make sure we can distinguish between an empty array and a null response
  68. r readraw 1
  69. test "HRANDFIELD count of 0 is handled correctly - emptyarray" {
  70. r hrandfield myhash 0
  71. } {*0}
  72. test "HRANDFIELD with <count> against non existing key - emptyarray" {
  73. r hrandfield nonexisting_key 100
  74. } {*0}
  75. r readraw 0
  76. foreach {type contents} "
  77. hashtable {{a 1} {b 2} {c 3} {d 4} {e 5} {6 f} {7 g} {8 h} {9 i} {[randstring 70 90 alpha] 10}}
  78. listpack {{a 1} {b 2} {c 3} {d 4} {e 5} {6 f} {7 g} {8 h} {9 i} {10 j}} " {
  79. test "HRANDFIELD with <count> - $type" {
  80. set original_max_value [lindex [r config get hash-max-ziplist-value] 1]
  81. r config set hash-max-ziplist-value 10
  82. create_hash myhash $contents
  83. assert_encoding $type myhash
  84. # create a dict for easy lookup
  85. unset -nocomplain mydict
  86. foreach {k v} [r hgetall myhash] {
  87. dict append mydict $k $v
  88. }
  89. # We'll stress different parts of the code, see the implementation
  90. # of HRANDFIELD for more information, but basically there are
  91. # four different code paths.
  92. # PATH 1: Use negative count.
  93. # 1) Check that it returns repeated elements with and without values.
  94. set res [r hrandfield myhash -20]
  95. assert_equal [llength $res] 20
  96. set res [r hrandfield myhash -1001]
  97. assert_equal [llength $res] 1001
  98. # again with WITHVALUES
  99. set res [r hrandfield myhash -20 withvalues]
  100. assert_equal [llength $res] 40
  101. set res [r hrandfield myhash -1001 withvalues]
  102. assert_equal [llength $res] 2002
  103. # Test random uniform distribution
  104. # df = 9, 40 means 0.00001 probability
  105. set res [r hrandfield myhash -1000]
  106. assert_lessthan [chi_square_value $res] 40
  107. # 2) Check that all the elements actually belong to the original hash.
  108. foreach {key val} $res {
  109. assert {[dict exists $mydict $key]}
  110. }
  111. # 3) Check that eventually all the elements are returned.
  112. # Use both WITHVALUES and without
  113. unset -nocomplain auxset
  114. set iterations 1000
  115. while {$iterations != 0} {
  116. incr iterations -1
  117. if {[expr {$iterations % 2}] == 0} {
  118. set res [r hrandfield myhash -3 withvalues]
  119. foreach {key val} $res {
  120. dict append auxset $key $val
  121. }
  122. } else {
  123. set res [r hrandfield myhash -3]
  124. foreach key $res {
  125. dict append auxset $key $val
  126. }
  127. }
  128. if {[lsort [dict keys $mydict]] eq
  129. [lsort [dict keys $auxset]]} {
  130. break;
  131. }
  132. }
  133. assert {$iterations != 0}
  134. # PATH 2: positive count (unique behavior) with requested size
  135. # equal or greater than set size.
  136. foreach size {10 20} {
  137. set res [r hrandfield myhash $size]
  138. assert_equal [llength $res] 10
  139. assert_equal [lsort $res] [lsort [dict keys $mydict]]
  140. # again with WITHVALUES
  141. set res [r hrandfield myhash $size withvalues]
  142. assert_equal [llength $res] 20
  143. assert_equal [lsort $res] [lsort $mydict]
  144. }
  145. # PATH 3: Ask almost as elements as there are in the set.
  146. # In this case the implementation will duplicate the original
  147. # set and will remove random elements up to the requested size.
  148. #
  149. # PATH 4: Ask a number of elements definitely smaller than
  150. # the set size.
  151. #
  152. # We can test both the code paths just changing the size but
  153. # using the same code.
  154. foreach size {8 2} {
  155. set res [r hrandfield myhash $size]
  156. assert_equal [llength $res] $size
  157. # again with WITHVALUES
  158. set res [r hrandfield myhash $size withvalues]
  159. assert_equal [llength $res] [expr {$size * 2}]
  160. # 1) Check that all the elements actually belong to the
  161. # original set.
  162. foreach ele [dict keys $res] {
  163. assert {[dict exists $mydict $ele]}
  164. }
  165. # 2) Check that eventually all the elements are returned.
  166. # Use both WITHVALUES and without
  167. unset -nocomplain auxset
  168. unset -nocomplain allkey
  169. set iterations [expr {1000 / $size}]
  170. set all_ele_return false
  171. while {$iterations != 0} {
  172. incr iterations -1
  173. if {[expr {$iterations % 2}] == 0} {
  174. set res [r hrandfield myhash $size withvalues]
  175. foreach {key value} $res {
  176. dict append auxset $key $value
  177. lappend allkey $key
  178. }
  179. } else {
  180. set res [r hrandfield myhash $size]
  181. foreach key $res {
  182. dict append auxset $key
  183. lappend allkey $key
  184. }
  185. }
  186. if {[lsort [dict keys $mydict]] eq
  187. [lsort [dict keys $auxset]]} {
  188. set all_ele_return true
  189. }
  190. }
  191. assert_equal $all_ele_return true
  192. # df = 9, 40 means 0.00001 probability
  193. assert_lessthan [chi_square_value $allkey] 40
  194. }
  195. }
  196. r config set hash-max-ziplist-value $original_max_value
  197. }
  198. test {HSET/HLEN - Big hash creation} {
  199. array set bighash {}
  200. for {set i 0} {$i < 1024} {incr i} {
  201. set key __avoid_collisions__[randstring 0 8 alpha]
  202. set val __avoid_collisions__[randstring 0 8 alpha]
  203. if {[info exists bighash($key)]} {
  204. incr i -1
  205. continue
  206. }
  207. r hset bighash $key $val
  208. set bighash($key) $val
  209. }
  210. list [r hlen bighash]
  211. } {1024}
  212. test {Is the big hash encoded with an hash table?} {
  213. assert_encoding hashtable bighash
  214. }
  215. test {HGET against the small hash} {
  216. set err {}
  217. foreach k [array names smallhash *] {
  218. if {$smallhash($k) ne [r hget smallhash $k]} {
  219. set err "$smallhash($k) != [r hget smallhash $k]"
  220. break
  221. }
  222. }
  223. set _ $err
  224. } {}
  225. test {HGET against the big hash} {
  226. set err {}
  227. foreach k [array names bighash *] {
  228. if {$bighash($k) ne [r hget bighash $k]} {
  229. set err "$bighash($k) != [r hget bighash $k]"
  230. break
  231. }
  232. }
  233. set _ $err
  234. } {}
  235. test {HGET against non existing key} {
  236. set rv {}
  237. lappend rv [r hget smallhash __123123123__]
  238. lappend rv [r hget bighash __123123123__]
  239. set _ $rv
  240. } {{} {}}
  241. test {HSET in update and insert mode} {
  242. set rv {}
  243. set k [lindex [array names smallhash *] 0]
  244. lappend rv [r hset smallhash $k newval1]
  245. set smallhash($k) newval1
  246. lappend rv [r hget smallhash $k]
  247. lappend rv [r hset smallhash __foobar123__ newval]
  248. set k [lindex [array names bighash *] 0]
  249. lappend rv [r hset bighash $k newval2]
  250. set bighash($k) newval2
  251. lappend rv [r hget bighash $k]
  252. lappend rv [r hset bighash __foobar123__ newval]
  253. lappend rv [r hdel smallhash __foobar123__]
  254. lappend rv [r hdel bighash __foobar123__]
  255. set _ $rv
  256. } {0 newval1 1 0 newval2 1 1 1}
  257. test {HSETNX target key missing - small hash} {
  258. r hsetnx smallhash __123123123__ foo
  259. r hget smallhash __123123123__
  260. } {foo}
  261. test {HSETNX target key exists - small hash} {
  262. r hsetnx smallhash __123123123__ bar
  263. set result [r hget smallhash __123123123__]
  264. r hdel smallhash __123123123__
  265. set _ $result
  266. } {foo}
  267. test {HSETNX target key missing - big hash} {
  268. r hsetnx bighash __123123123__ foo
  269. r hget bighash __123123123__
  270. } {foo}
  271. test {HSETNX target key exists - big hash} {
  272. r hsetnx bighash __123123123__ bar
  273. set result [r hget bighash __123123123__]
  274. r hdel bighash __123123123__
  275. set _ $result
  276. } {foo}
  277. test {HMSET wrong number of args} {
  278. catch {r hmset smallhash key1 val1 key2} err
  279. format $err
  280. } {*wrong number*}
  281. test {HMSET - small hash} {
  282. set args {}
  283. foreach {k v} [array get smallhash] {
  284. set newval [randstring 0 8 alpha]
  285. set smallhash($k) $newval
  286. lappend args $k $newval
  287. }
  288. r hmset smallhash {*}$args
  289. } {OK}
  290. test {HMSET - big hash} {
  291. set args {}
  292. foreach {k v} [array get bighash] {
  293. set newval [randstring 0 8 alpha]
  294. set bighash($k) $newval
  295. lappend args $k $newval
  296. }
  297. r hmset bighash {*}$args
  298. } {OK}
  299. test {HMGET against non existing key and fields} {
  300. set rv {}
  301. lappend rv [r hmget doesntexist __123123123__ __456456456__]
  302. lappend rv [r hmget smallhash __123123123__ __456456456__]
  303. lappend rv [r hmget bighash __123123123__ __456456456__]
  304. set _ $rv
  305. } {{{} {}} {{} {}} {{} {}}}
  306. test {HMGET against wrong type} {
  307. r set wrongtype somevalue
  308. assert_error "*wrong*" {r hmget wrongtype field1 field2}
  309. }
  310. test {HMGET - small hash} {
  311. set keys {}
  312. set vals {}
  313. foreach {k v} [array get smallhash] {
  314. lappend keys $k
  315. lappend vals $v
  316. }
  317. set err {}
  318. set result [r hmget smallhash {*}$keys]
  319. if {$vals ne $result} {
  320. set err "$vals != $result"
  321. break
  322. }
  323. set _ $err
  324. } {}
  325. test {HMGET - big hash} {
  326. set keys {}
  327. set vals {}
  328. foreach {k v} [array get bighash] {
  329. lappend keys $k
  330. lappend vals $v
  331. }
  332. set err {}
  333. set result [r hmget bighash {*}$keys]
  334. if {$vals ne $result} {
  335. set err "$vals != $result"
  336. break
  337. }
  338. set _ $err
  339. } {}
  340. test {HKEYS - small hash} {
  341. lsort [r hkeys smallhash]
  342. } [lsort [array names smallhash *]]
  343. test {HKEYS - big hash} {
  344. lsort [r hkeys bighash]
  345. } [lsort [array names bighash *]]
  346. test {HVALS - small hash} {
  347. set vals {}
  348. foreach {k v} [array get smallhash] {
  349. lappend vals $v
  350. }
  351. set _ [lsort $vals]
  352. } [lsort [r hvals smallhash]]
  353. test {HVALS - big hash} {
  354. set vals {}
  355. foreach {k v} [array get bighash] {
  356. lappend vals $v
  357. }
  358. set _ [lsort $vals]
  359. } [lsort [r hvals bighash]]
  360. test {HGETALL - small hash} {
  361. lsort [r hgetall smallhash]
  362. } [lsort [array get smallhash]]
  363. test {HGETALL - big hash} {
  364. lsort [r hgetall bighash]
  365. } [lsort [array get bighash]]
  366. test {HDEL and return value} {
  367. set rv {}
  368. lappend rv [r hdel smallhash nokey]
  369. lappend rv [r hdel bighash nokey]
  370. set k [lindex [array names smallhash *] 0]
  371. lappend rv [r hdel smallhash $k]
  372. lappend rv [r hdel smallhash $k]
  373. lappend rv [r hget smallhash $k]
  374. unset smallhash($k)
  375. set k [lindex [array names bighash *] 0]
  376. lappend rv [r hdel bighash $k]
  377. lappend rv [r hdel bighash $k]
  378. lappend rv [r hget bighash $k]
  379. unset bighash($k)
  380. set _ $rv
  381. } {0 0 1 0 {} 1 0 {}}
  382. test {HDEL - more than a single value} {
  383. set rv {}
  384. r del myhash
  385. r hmset myhash a 1 b 2 c 3
  386. assert_equal 0 [r hdel myhash x y]
  387. assert_equal 2 [r hdel myhash a c f]
  388. r hgetall myhash
  389. } {b 2}
  390. test {HDEL - hash becomes empty before deleting all specified fields} {
  391. r del myhash
  392. r hmset myhash a 1 b 2 c 3
  393. assert_equal 3 [r hdel myhash a b c d e]
  394. assert_equal 0 [r exists myhash]
  395. }
  396. test {HEXISTS} {
  397. set rv {}
  398. set k [lindex [array names smallhash *] 0]
  399. lappend rv [r hexists smallhash $k]
  400. lappend rv [r hexists smallhash nokey]
  401. set k [lindex [array names bighash *] 0]
  402. lappend rv [r hexists bighash $k]
  403. lappend rv [r hexists bighash nokey]
  404. } {1 0 1 0}
  405. test {Is a ziplist encoded Hash promoted on big payload?} {
  406. r hset smallhash foo [string repeat a 1024]
  407. r debug object smallhash
  408. } {*hashtable*} {needs:debug}
  409. test {HINCRBY against non existing database key} {
  410. r del htest
  411. list [r hincrby htest foo 2]
  412. } {2}
  413. test {HINCRBY against non existing hash key} {
  414. set rv {}
  415. r hdel smallhash tmp
  416. r hdel bighash tmp
  417. lappend rv [r hincrby smallhash tmp 2]
  418. lappend rv [r hget smallhash tmp]
  419. lappend rv [r hincrby bighash tmp 2]
  420. lappend rv [r hget bighash tmp]
  421. } {2 2 2 2}
  422. test {HINCRBY against hash key created by hincrby itself} {
  423. set rv {}
  424. lappend rv [r hincrby smallhash tmp 3]
  425. lappend rv [r hget smallhash tmp]
  426. lappend rv [r hincrby bighash tmp 3]
  427. lappend rv [r hget bighash tmp]
  428. } {5 5 5 5}
  429. test {HINCRBY against hash key originally set with HSET} {
  430. r hset smallhash tmp 100
  431. r hset bighash tmp 100
  432. list [r hincrby smallhash tmp 2] [r hincrby bighash tmp 2]
  433. } {102 102}
  434. test {HINCRBY over 32bit value} {
  435. r hset smallhash tmp 17179869184
  436. r hset bighash tmp 17179869184
  437. list [r hincrby smallhash tmp 1] [r hincrby bighash tmp 1]
  438. } {17179869185 17179869185}
  439. test {HINCRBY over 32bit value with over 32bit increment} {
  440. r hset smallhash tmp 17179869184
  441. r hset bighash tmp 17179869184
  442. list [r hincrby smallhash tmp 17179869184] [r hincrby bighash tmp 17179869184]
  443. } {34359738368 34359738368}
  444. test {HINCRBY fails against hash value with spaces (left)} {
  445. r hset smallhash str " 11"
  446. r hset bighash str " 11"
  447. catch {r hincrby smallhash str 1} smallerr
  448. catch {r hincrby bighash str 1} bigerr
  449. set rv {}
  450. lappend rv [string match "ERR*not an integer*" $smallerr]
  451. lappend rv [string match "ERR*not an integer*" $bigerr]
  452. } {1 1}
  453. test {HINCRBY fails against hash value with spaces (right)} {
  454. r hset smallhash str "11 "
  455. r hset bighash str "11 "
  456. catch {r hincrby smallhash str 1} smallerr
  457. catch {r hincrby bighash str 1} bigerr
  458. set rv {}
  459. lappend rv [string match "ERR*not an integer*" $smallerr]
  460. lappend rv [string match "ERR*not an integer*" $bigerr]
  461. } {1 1}
  462. test {HINCRBY can detect overflows} {
  463. set e {}
  464. r hset hash n -9223372036854775484
  465. assert {[r hincrby hash n -1] == -9223372036854775485}
  466. catch {r hincrby hash n -10000} e
  467. set e
  468. } {*overflow*}
  469. test {HINCRBYFLOAT against non existing database key} {
  470. r del htest
  471. list [r hincrbyfloat htest foo 2.5]
  472. } {2.5}
  473. test {HINCRBYFLOAT against non existing hash key} {
  474. set rv {}
  475. r hdel smallhash tmp
  476. r hdel bighash tmp
  477. lappend rv [roundFloat [r hincrbyfloat smallhash tmp 2.5]]
  478. lappend rv [roundFloat [r hget smallhash tmp]]
  479. lappend rv [roundFloat [r hincrbyfloat bighash tmp 2.5]]
  480. lappend rv [roundFloat [r hget bighash tmp]]
  481. } {2.5 2.5 2.5 2.5}
  482. test {HINCRBYFLOAT against hash key created by hincrby itself} {
  483. set rv {}
  484. lappend rv [roundFloat [r hincrbyfloat smallhash tmp 3.5]]
  485. lappend rv [roundFloat [r hget smallhash tmp]]
  486. lappend rv [roundFloat [r hincrbyfloat bighash tmp 3.5]]
  487. lappend rv [roundFloat [r hget bighash tmp]]
  488. } {6 6 6 6}
  489. test {HINCRBYFLOAT against hash key originally set with HSET} {
  490. r hset smallhash tmp 100
  491. r hset bighash tmp 100
  492. list [roundFloat [r hincrbyfloat smallhash tmp 2.5]] \
  493. [roundFloat [r hincrbyfloat bighash tmp 2.5]]
  494. } {102.5 102.5}
  495. test {HINCRBYFLOAT over 32bit value} {
  496. r hset smallhash tmp 17179869184
  497. r hset bighash tmp 17179869184
  498. list [r hincrbyfloat smallhash tmp 1] \
  499. [r hincrbyfloat bighash tmp 1]
  500. } {17179869185 17179869185}
  501. test {HINCRBYFLOAT over 32bit value with over 32bit increment} {
  502. r hset smallhash tmp 17179869184
  503. r hset bighash tmp 17179869184
  504. list [r hincrbyfloat smallhash tmp 17179869184] \
  505. [r hincrbyfloat bighash tmp 17179869184]
  506. } {34359738368 34359738368}
  507. test {HINCRBYFLOAT fails against hash value with spaces (left)} {
  508. r hset smallhash str " 11"
  509. r hset bighash str " 11"
  510. catch {r hincrbyfloat smallhash str 1} smallerr
  511. catch {r hincrbyfloat bighash str 1} bigerr
  512. set rv {}
  513. lappend rv [string match "ERR*not*float*" $smallerr]
  514. lappend rv [string match "ERR*not*float*" $bigerr]
  515. } {1 1}
  516. test {HINCRBYFLOAT fails against hash value with spaces (right)} {
  517. r hset smallhash str "11 "
  518. r hset bighash str "11 "
  519. catch {r hincrbyfloat smallhash str 1} smallerr
  520. catch {r hincrbyfloat bighash str 1} bigerr
  521. set rv {}
  522. lappend rv [string match "ERR*not*float*" $smallerr]
  523. lappend rv [string match "ERR*not*float*" $bigerr]
  524. } {1 1}
  525. test {HINCRBYFLOAT fails against hash value that contains a null-terminator in the middle} {
  526. r hset h f "1\x002"
  527. catch {r hincrbyfloat h f 1} err
  528. set rv {}
  529. lappend rv [string match "ERR*not*float*" $err]
  530. } {1}
  531. test {HSTRLEN against the small hash} {
  532. set err {}
  533. foreach k [array names smallhash *] {
  534. if {[string length $smallhash($k)] ne [r hstrlen smallhash $k]} {
  535. set err "[string length $smallhash($k)] != [r hstrlen smallhash $k]"
  536. break
  537. }
  538. }
  539. set _ $err
  540. } {}
  541. test {HSTRLEN against the big hash} {
  542. set err {}
  543. foreach k [array names bighash *] {
  544. if {[string length $bighash($k)] ne [r hstrlen bighash $k]} {
  545. set err "[string length $bighash($k)] != [r hstrlen bighash $k]"
  546. puts "HSTRLEN and logical length mismatch:"
  547. puts "key: $k"
  548. puts "Logical content: $bighash($k)"
  549. puts "Server content: [r hget bighash $k]"
  550. }
  551. }
  552. set _ $err
  553. } {}
  554. test {HSTRLEN against non existing field} {
  555. set rv {}
  556. lappend rv [r hstrlen smallhash __123123123__]
  557. lappend rv [r hstrlen bighash __123123123__]
  558. set _ $rv
  559. } {0 0}
  560. test {HSTRLEN corner cases} {
  561. set vals {
  562. -9223372036854775808 9223372036854775807 9223372036854775808
  563. {} 0 -1 x
  564. }
  565. foreach v $vals {
  566. r hmset smallhash field $v
  567. r hmset bighash field $v
  568. set len1 [string length $v]
  569. set len2 [r hstrlen smallhash field]
  570. set len3 [r hstrlen bighash field]
  571. assert {$len1 == $len2}
  572. assert {$len2 == $len3}
  573. }
  574. }
  575. test {Hash ziplist regression test for large keys} {
  576. r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk a
  577. r hset hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk b
  578. r hget hash kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
  579. } {b}
  580. foreach size {10 512} {
  581. test "Hash fuzzing #1 - $size fields" {
  582. for {set times 0} {$times < 10} {incr times} {
  583. catch {unset hash}
  584. array set hash {}
  585. r del hash
  586. # Create
  587. for {set j 0} {$j < $size} {incr j} {
  588. set field [randomValue]
  589. set value [randomValue]
  590. r hset hash $field $value
  591. set hash($field) $value
  592. }
  593. # Verify
  594. foreach {k v} [array get hash] {
  595. assert_equal $v [r hget hash $k]
  596. }
  597. assert_equal [array size hash] [r hlen hash]
  598. }
  599. }
  600. test "Hash fuzzing #2 - $size fields" {
  601. for {set times 0} {$times < 10} {incr times} {
  602. catch {unset hash}
  603. array set hash {}
  604. r del hash
  605. # Create
  606. for {set j 0} {$j < $size} {incr j} {
  607. randpath {
  608. set field [randomValue]
  609. set value [randomValue]
  610. r hset hash $field $value
  611. set hash($field) $value
  612. } {
  613. set field [randomSignedInt 512]
  614. set value [randomSignedInt 512]
  615. r hset hash $field $value
  616. set hash($field) $value
  617. } {
  618. randpath {
  619. set field [randomValue]
  620. } {
  621. set field [randomSignedInt 512]
  622. }
  623. r hdel hash $field
  624. unset -nocomplain hash($field)
  625. }
  626. }
  627. # Verify
  628. foreach {k v} [array get hash] {
  629. assert_equal $v [r hget hash $k]
  630. }
  631. assert_equal [array size hash] [r hlen hash]
  632. }
  633. }
  634. }
  635. test {Stress test the hash ziplist -> hashtable encoding conversion} {
  636. r config set hash-max-ziplist-entries 32
  637. for {set j 0} {$j < 100} {incr j} {
  638. r del myhash
  639. for {set i 0} {$i < 64} {incr i} {
  640. r hset myhash [randomValue] [randomValue]
  641. }
  642. assert_encoding hashtable myhash
  643. }
  644. }
  645. # The following test can only be executed if we don't use Valgrind, and if
  646. # we are using x86_64 architecture, because:
  647. #
  648. # 1) Valgrind has floating point limitations, no support for 80 bits math.
  649. # 2) Other archs may have the same limits.
  650. #
  651. # 1.23 cannot be represented correctly with 64 bit doubles, so we skip
  652. # the test, since we are only testing pretty printing here and is not
  653. # a bug if the program outputs things like 1.299999...
  654. if {!$::valgrind && [string match *x86_64* [exec uname -a]]} {
  655. test {Test HINCRBYFLOAT for correct float representation (issue #2846)} {
  656. r del myhash
  657. assert {[r hincrbyfloat myhash float 1.23] eq {1.23}}
  658. assert {[r hincrbyfloat myhash float 0.77] eq {2}}
  659. assert {[r hincrbyfloat myhash float -0.1] eq {1.9}}
  660. }
  661. }
  662. test {Hash ziplist of various encodings} {
  663. r del k
  664. config_set hash-max-ziplist-entries 1000000000
  665. config_set hash-max-ziplist-value 1000000000
  666. r hset k ZIP_INT_8B 127
  667. r hset k ZIP_INT_16B 32767
  668. r hset k ZIP_INT_32B 2147483647
  669. r hset k ZIP_INT_64B 9223372036854775808
  670. r hset k ZIP_INT_IMM_MIN 0
  671. r hset k ZIP_INT_IMM_MAX 12
  672. r hset k ZIP_STR_06B [string repeat x 31]
  673. r hset k ZIP_STR_14B [string repeat x 8191]
  674. r hset k ZIP_STR_32B [string repeat x 65535]
  675. set k [r hgetall k]
  676. set dump [r dump k]
  677. # will be converted to dict at RESTORE
  678. config_set hash-max-ziplist-entries 2
  679. config_set sanitize-dump-payload no mayfail
  680. r restore kk 0 $dump
  681. set kk [r hgetall kk]
  682. # make sure the values are right
  683. assert_equal [lsort $k] [lsort $kk]
  684. assert_equal [dict get $k ZIP_STR_06B] [string repeat x 31]
  685. set k [dict remove $k ZIP_STR_06B]
  686. assert_equal [dict get $k ZIP_STR_14B] [string repeat x 8191]
  687. set k [dict remove $k ZIP_STR_14B]
  688. assert_equal [dict get $k ZIP_STR_32B] [string repeat x 65535]
  689. set k [dict remove $k ZIP_STR_32B]
  690. set _ $k
  691. } {ZIP_INT_8B 127 ZIP_INT_16B 32767 ZIP_INT_32B 2147483647 ZIP_INT_64B 9223372036854775808 ZIP_INT_IMM_MIN 0 ZIP_INT_IMM_MAX 12}
  692. test {Hash ziplist of various encodings - sanitize dump} {
  693. config_set sanitize-dump-payload yes mayfail
  694. r restore kk 0 $dump replace
  695. set k [r hgetall k]
  696. set kk [r hgetall kk]
  697. # make sure the values are right
  698. assert_equal [lsort $k] [lsort $kk]
  699. assert_equal [dict get $k ZIP_STR_06B] [string repeat x 31]
  700. set k [dict remove $k ZIP_STR_06B]
  701. assert_equal [dict get $k ZIP_STR_14B] [string repeat x 8191]
  702. set k [dict remove $k ZIP_STR_14B]
  703. assert_equal [dict get $k ZIP_STR_32B] [string repeat x 65535]
  704. set k [dict remove $k ZIP_STR_32B]
  705. set _ $k
  706. } {ZIP_INT_8B 127 ZIP_INT_16B 32767 ZIP_INT_32B 2147483647 ZIP_INT_64B 9223372036854775808 ZIP_INT_IMM_MIN 0 ZIP_INT_IMM_MAX 12}
  707. }