bitops.tcl 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. # Compare Redis commands against Tcl implementations of the same commands.
  2. proc count_bits s {
  3. binary scan $s b* bits
  4. string length [regsub -all {0} $bits {}]
  5. }
  6. # start end are bit index
  7. proc count_bits_start_end {s start end} {
  8. binary scan $s B* bits
  9. string length [regsub -all {0} [string range $bits $start $end] {}]
  10. }
  11. proc simulate_bit_op {op args} {
  12. set maxlen 0
  13. set j 0
  14. set count [llength $args]
  15. foreach a $args {
  16. binary scan $a b* bits
  17. set b($j) $bits
  18. if {[string length $bits] > $maxlen} {
  19. set maxlen [string length $bits]
  20. }
  21. incr j
  22. }
  23. for {set j 0} {$j < $count} {incr j} {
  24. if {[string length $b($j)] < $maxlen} {
  25. append b($j) [string repeat 0 [expr $maxlen-[string length $b($j)]]]
  26. }
  27. }
  28. set out {}
  29. for {set x 0} {$x < $maxlen} {incr x} {
  30. set bit [string range $b(0) $x $x]
  31. if {$op eq {not}} {set bit [expr {!$bit}]}
  32. for {set j 1} {$j < $count} {incr j} {
  33. set bit2 [string range $b($j) $x $x]
  34. switch $op {
  35. and {set bit [expr {$bit & $bit2}]}
  36. or {set bit [expr {$bit | $bit2}]}
  37. xor {set bit [expr {$bit ^ $bit2}]}
  38. }
  39. }
  40. append out $bit
  41. }
  42. binary format b* $out
  43. }
  44. start_server {tags {"bitops"}} {
  45. test {BITCOUNT returns 0 against non existing key} {
  46. assert {[r bitcount no-key] == 0}
  47. assert {[r bitcount no-key 0 1000 bit] == 0}
  48. }
  49. test {BITCOUNT returns 0 with out of range indexes} {
  50. r set str "xxxx"
  51. assert {[r bitcount str 4 10] == 0}
  52. assert {[r bitcount str 32 87 bit] == 0}
  53. }
  54. test {BITCOUNT returns 0 with negative indexes where start > end} {
  55. r set str "xxxx"
  56. assert {[r bitcount str -6 -7] == 0}
  57. assert {[r bitcount str -6 -15 bit] == 0}
  58. }
  59. catch {unset num}
  60. foreach vec [list "" "\xaa" "\x00\x00\xff" "foobar" "123"] {
  61. incr num
  62. test "BITCOUNT against test vector #$num" {
  63. r set str $vec
  64. set count [count_bits $vec]
  65. assert {[r bitcount str] == $count}
  66. assert {[r bitcount str 0 -1 bit] == $count}
  67. }
  68. }
  69. test {BITCOUNT fuzzing without start/end} {
  70. for {set j 0} {$j < 100} {incr j} {
  71. set str [randstring 0 3000]
  72. r set str $str
  73. set count [count_bits $str]
  74. assert {[r bitcount str] == $count}
  75. assert {[r bitcount str 0 -1 bit] == $count}
  76. }
  77. }
  78. test {BITCOUNT fuzzing with start/end} {
  79. for {set j 0} {$j < 100} {incr j} {
  80. set str [randstring 0 3000]
  81. r set str $str
  82. set l [string length $str]
  83. set start [randomInt $l]
  84. set end [randomInt $l]
  85. if {$start > $end} {
  86. # Swap start and end
  87. lassign [list $end $start] start end
  88. }
  89. assert {[r bitcount str $start $end] == [count_bits [string range $str $start $end]]}
  90. }
  91. for {set j 0} {$j < 100} {incr j} {
  92. set str [randstring 0 3000]
  93. r set str $str
  94. set l [expr [string length $str] * 8]
  95. set start [randomInt $l]
  96. set end [randomInt $l]
  97. if {$start > $end} {
  98. # Swap start and end
  99. lassign [list $end $start] start end
  100. }
  101. assert {[r bitcount str $start $end bit] == [count_bits_start_end $str $start $end]}
  102. }
  103. }
  104. test {BITCOUNT with start, end} {
  105. set s "foobar"
  106. r set s $s
  107. assert_equal [r bitcount s 0 -1] [count_bits "foobar"]
  108. assert_equal [r bitcount s 1 -2] [count_bits "ooba"]
  109. assert_equal [r bitcount s -2 1] [count_bits ""]
  110. assert_equal [r bitcount s 0 1000] [count_bits "foobar"]
  111. assert_equal [r bitcount s 0 -1 bit] [count_bits $s]
  112. assert_equal [r bitcount s 10 14 bit] [count_bits_start_end $s 10 14]
  113. assert_equal [r bitcount s 3 14 bit] [count_bits_start_end $s 3 14]
  114. assert_equal [r bitcount s 3 29 bit] [count_bits_start_end $s 3 29]
  115. assert_equal [r bitcount s 10 -34 bit] [count_bits_start_end $s 10 14]
  116. assert_equal [r bitcount s 3 -34 bit] [count_bits_start_end $s 3 14]
  117. assert_equal [r bitcount s 3 -19 bit] [count_bits_start_end $s 3 29]
  118. assert_equal [r bitcount s -2 1 bit] 0
  119. assert_equal [r bitcount s 0 1000 bit] [count_bits $s]
  120. }
  121. test {BITCOUNT syntax error #1} {
  122. catch {r bitcount s 0} e
  123. set e
  124. } {ERR*syntax*}
  125. test {BITCOUNT syntax error #2} {
  126. catch {r bitcount s 0 1 hello} e
  127. set e
  128. } {ERR*syntax*}
  129. test {BITCOUNT regression test for github issue #582} {
  130. r del foo
  131. r setbit foo 0 1
  132. if {[catch {r bitcount foo 0 4294967296} e]} {
  133. assert_match {*ERR*out of range*} $e
  134. set _ 1
  135. } else {
  136. set e
  137. }
  138. } {1}
  139. test {BITCOUNT misaligned prefix} {
  140. r del str
  141. r set str ab
  142. r bitcount str 1 -1
  143. } {3}
  144. test {BITCOUNT misaligned prefix + full words + remainder} {
  145. r del str
  146. r set str __PPxxxxxxxxxxxxxxxxRR__
  147. r bitcount str 2 -3
  148. } {74}
  149. test {BITOP NOT (empty string)} {
  150. r set s{t} ""
  151. r bitop not dest{t} s{t}
  152. r get dest{t}
  153. } {}
  154. test {BITOP NOT (known string)} {
  155. r set s{t} "\xaa\x00\xff\x55"
  156. r bitop not dest{t} s{t}
  157. r get dest{t}
  158. } "\x55\xff\x00\xaa"
  159. test {BITOP where dest and target are the same key} {
  160. r set s "\xaa\x00\xff\x55"
  161. r bitop not s s
  162. r get s
  163. } "\x55\xff\x00\xaa"
  164. test {BITOP AND|OR|XOR don't change the string with single input key} {
  165. r set a{t} "\x01\x02\xff"
  166. r bitop and res1{t} a{t}
  167. r bitop or res2{t} a{t}
  168. r bitop xor res3{t} a{t}
  169. list [r get res1{t}] [r get res2{t}] [r get res3{t}]
  170. } [list "\x01\x02\xff" "\x01\x02\xff" "\x01\x02\xff"]
  171. test {BITOP missing key is considered a stream of zero} {
  172. r set a{t} "\x01\x02\xff"
  173. r bitop and res1{t} no-suck-key{t} a{t}
  174. r bitop or res2{t} no-suck-key{t} a{t} no-such-key{t}
  175. r bitop xor res3{t} no-such-key{t} a{t}
  176. list [r get res1{t}] [r get res2{t}] [r get res3{t}]
  177. } [list "\x00\x00\x00" "\x01\x02\xff" "\x01\x02\xff"]
  178. test {BITOP shorter keys are zero-padded to the key with max length} {
  179. r set a{t} "\x01\x02\xff\xff"
  180. r set b{t} "\x01\x02\xff"
  181. r bitop and res1{t} a{t} b{t}
  182. r bitop or res2{t} a{t} b{t}
  183. r bitop xor res3{t} a{t} b{t}
  184. list [r get res1{t}] [r get res2{t}] [r get res3{t}]
  185. } [list "\x01\x02\xff\x00" "\x01\x02\xff\xff" "\x00\x00\x00\xff"]
  186. foreach op {and or xor} {
  187. test "BITOP $op fuzzing" {
  188. for {set i 0} {$i < 10} {incr i} {
  189. r flushall
  190. set vec {}
  191. set veckeys {}
  192. set numvec [expr {[randomInt 10]+1}]
  193. for {set j 0} {$j < $numvec} {incr j} {
  194. set str [randstring 0 1000]
  195. lappend vec $str
  196. lappend veckeys vector_$j{t}
  197. r set vector_$j{t} $str
  198. }
  199. r bitop $op target{t} {*}$veckeys
  200. assert_equal [r get target{t}] [simulate_bit_op $op {*}$vec]
  201. }
  202. }
  203. }
  204. test {BITOP NOT fuzzing} {
  205. for {set i 0} {$i < 10} {incr i} {
  206. r flushall
  207. set str [randstring 0 1000]
  208. r set str{t} $str
  209. r bitop not target{t} str{t}
  210. assert_equal [r get target{t}] [simulate_bit_op not $str]
  211. }
  212. }
  213. test {BITOP with integer encoded source objects} {
  214. r set a{t} 1
  215. r set b{t} 2
  216. r bitop xor dest{t} a{t} b{t} a{t}
  217. r get dest{t}
  218. } {2}
  219. test {BITOP with non string source key} {
  220. r del c{t}
  221. r set a{t} 1
  222. r set b{t} 2
  223. r lpush c{t} foo
  224. catch {r bitop xor dest{t} a{t} b{t} c{t} d{t}} e
  225. set e
  226. } {WRONGTYPE*}
  227. test {BITOP with empty string after non empty string (issue #529)} {
  228. r flushdb
  229. r set a{t} "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  230. r bitop or x{t} a{t} b{t}
  231. } {32}
  232. test {BITPOS bit=0 with empty key returns 0} {
  233. r del str
  234. assert {[r bitpos str 0] == 0}
  235. assert {[r bitpos str 0 0 -1 bit] == 0}
  236. }
  237. test {BITPOS bit=1 with empty key returns -1} {
  238. r del str
  239. assert {[r bitpos str 1] == -1}
  240. assert {[r bitpos str 1 0 -1] == -1}
  241. }
  242. test {BITPOS bit=0 with string less than 1 word works} {
  243. r set str "\xff\xf0\x00"
  244. assert {[r bitpos str 0] == 12}
  245. assert {[r bitpos str 0 0 -1 bit] == 12}
  246. }
  247. test {BITPOS bit=1 with string less than 1 word works} {
  248. r set str "\x00\x0f\x00"
  249. assert {[r bitpos str 1] == 12}
  250. assert {[r bitpos str 1 0 -1 bit] == 12}
  251. }
  252. test {BITPOS bit=0 starting at unaligned address} {
  253. r set str "\xff\xf0\x00"
  254. assert {[r bitpos str 0 1] == 12}
  255. assert {[r bitpos str 0 1 -1 bit] == 12}
  256. }
  257. test {BITPOS bit=1 starting at unaligned address} {
  258. r set str "\x00\x0f\xff"
  259. assert {[r bitpos str 1 1] == 12}
  260. assert {[r bitpos str 1 1 -1 bit] == 12}
  261. }
  262. test {BITPOS bit=0 unaligned+full word+reminder} {
  263. r del str
  264. r set str "\xff\xff\xff" ; # Prefix
  265. # Followed by two (or four in 32 bit systems) full words
  266. r append str "\xff\xff\xff\xff\xff\xff\xff\xff"
  267. r append str "\xff\xff\xff\xff\xff\xff\xff\xff"
  268. r append str "\xff\xff\xff\xff\xff\xff\xff\xff"
  269. # First zero bit.
  270. r append str "\x0f"
  271. assert {[r bitpos str 0] == 216}
  272. assert {[r bitpos str 0 1] == 216}
  273. assert {[r bitpos str 0 2] == 216}
  274. assert {[r bitpos str 0 3] == 216}
  275. assert {[r bitpos str 0 4] == 216}
  276. assert {[r bitpos str 0 5] == 216}
  277. assert {[r bitpos str 0 6] == 216}
  278. assert {[r bitpos str 0 7] == 216}
  279. assert {[r bitpos str 0 8] == 216}
  280. assert {[r bitpos str 0 1 -1 bit] == 216}
  281. assert {[r bitpos str 0 9 -1 bit] == 216}
  282. assert {[r bitpos str 0 17 -1 bit] == 216}
  283. assert {[r bitpos str 0 25 -1 bit] == 216}
  284. assert {[r bitpos str 0 33 -1 bit] == 216}
  285. assert {[r bitpos str 0 41 -1 bit] == 216}
  286. assert {[r bitpos str 0 49 -1 bit] == 216}
  287. assert {[r bitpos str 0 57 -1 bit] == 216}
  288. assert {[r bitpos str 0 65 -1 bit] == 216}
  289. }
  290. test {BITPOS bit=1 unaligned+full word+reminder} {
  291. r del str
  292. r set str "\x00\x00\x00" ; # Prefix
  293. # Followed by two (or four in 32 bit systems) full words
  294. r append str "\x00\x00\x00\x00\x00\x00\x00\x00"
  295. r append str "\x00\x00\x00\x00\x00\x00\x00\x00"
  296. r append str "\x00\x00\x00\x00\x00\x00\x00\x00"
  297. # First zero bit.
  298. r append str "\xf0"
  299. assert {[r bitpos str 1] == 216}
  300. assert {[r bitpos str 1 1] == 216}
  301. assert {[r bitpos str 1 2] == 216}
  302. assert {[r bitpos str 1 3] == 216}
  303. assert {[r bitpos str 1 4] == 216}
  304. assert {[r bitpos str 1 5] == 216}
  305. assert {[r bitpos str 1 6] == 216}
  306. assert {[r bitpos str 1 7] == 216}
  307. assert {[r bitpos str 1 8] == 216}
  308. assert {[r bitpos str 1 1 -1 bit] == 216}
  309. assert {[r bitpos str 1 9 -1 bit] == 216}
  310. assert {[r bitpos str 1 17 -1 bit] == 216}
  311. assert {[r bitpos str 1 25 -1 bit] == 216}
  312. assert {[r bitpos str 1 33 -1 bit] == 216}
  313. assert {[r bitpos str 1 41 -1 bit] == 216}
  314. assert {[r bitpos str 1 49 -1 bit] == 216}
  315. assert {[r bitpos str 1 57 -1 bit] == 216}
  316. assert {[r bitpos str 1 65 -1 bit] == 216}
  317. }
  318. test {BITPOS bit=1 returns -1 if string is all 0 bits} {
  319. r set str ""
  320. for {set j 0} {$j < 20} {incr j} {
  321. assert {[r bitpos str 1] == -1}
  322. assert {[r bitpos str 1 0 -1 bit] == -1}
  323. r append str "\x00"
  324. }
  325. }
  326. test {BITPOS bit=0 works with intervals} {
  327. r set str "\x00\xff\x00"
  328. assert {[r bitpos str 0 0 -1] == 0}
  329. assert {[r bitpos str 0 1 -1] == 16}
  330. assert {[r bitpos str 0 2 -1] == 16}
  331. assert {[r bitpos str 0 2 200] == 16}
  332. assert {[r bitpos str 0 1 1] == -1}
  333. assert {[r bitpos str 0 0 -1 bit] == 0}
  334. assert {[r bitpos str 0 8 -1 bit] == 16}
  335. assert {[r bitpos str 0 16 -1 bit] == 16}
  336. assert {[r bitpos str 0 16 200 bit] == 16}
  337. assert {[r bitpos str 0 8 8 bit] == -1}
  338. }
  339. test {BITPOS bit=1 works with intervals} {
  340. r set str "\x00\xff\x00"
  341. assert {[r bitpos str 1 0 -1] == 8}
  342. assert {[r bitpos str 1 1 -1] == 8}
  343. assert {[r bitpos str 1 2 -1] == -1}
  344. assert {[r bitpos str 1 2 200] == -1}
  345. assert {[r bitpos str 1 1 1] == 8}
  346. assert {[r bitpos str 1 0 -1 bit] == 8}
  347. assert {[r bitpos str 1 8 -1 bit] == 8}
  348. assert {[r bitpos str 1 16 -1 bit] == -1}
  349. assert {[r bitpos str 1 16 200 bit] == -1}
  350. assert {[r bitpos str 1 8 8 bit] == 8}
  351. }
  352. test {BITPOS bit=0 changes behavior if end is given} {
  353. r set str "\xff\xff\xff"
  354. assert {[r bitpos str 0] == 24}
  355. assert {[r bitpos str 0 0] == 24}
  356. assert {[r bitpos str 0 0 -1] == -1}
  357. assert {[r bitpos str 0 0 -1 bit] == -1}
  358. }
  359. test {SETBIT/BITFIELD only increase dirty when the value changed} {
  360. r del foo{t} foo2{t} foo3{t}
  361. set dirty [s rdb_changes_since_last_save]
  362. # Create a new key, always increase the dirty.
  363. r setbit foo{t} 0 0
  364. r bitfield foo2{t} set i5 0 0
  365. set dirty2 [s rdb_changes_since_last_save]
  366. assert {$dirty2 == $dirty + 2}
  367. # No change.
  368. r setbit foo{t} 0 0
  369. r bitfield foo2{t} set i5 0 0
  370. set dirty3 [s rdb_changes_since_last_save]
  371. assert {$dirty3 == $dirty2}
  372. # Do a change and a no change.
  373. r setbit foo{t} 0 1
  374. r setbit foo{t} 0 1
  375. r setbit foo{t} 0 0
  376. r setbit foo{t} 0 0
  377. r bitfield foo2{t} set i5 0 1
  378. r bitfield foo2{t} set i5 0 1
  379. r bitfield foo2{t} set i5 0 0
  380. r bitfield foo2{t} set i5 0 0
  381. set dirty4 [s rdb_changes_since_last_save]
  382. assert {$dirty4 == $dirty3 + 4}
  383. # BITFIELD INCRBY always increase dirty.
  384. r bitfield foo3{t} incrby i5 0 1
  385. r bitfield foo3{t} incrby i5 0 1
  386. set dirty5 [s rdb_changes_since_last_save]
  387. assert {$dirty5 == $dirty4 + 2}
  388. }
  389. test {BITPOS bit=1 fuzzy testing using SETBIT} {
  390. r del str
  391. set max 524288; # 64k
  392. set first_one_pos -1
  393. for {set j 0} {$j < 1000} {incr j} {
  394. assert {[r bitpos str 1] == $first_one_pos}
  395. assert {[r bitpos str 1 0 -1 bit] == $first_one_pos}
  396. set pos [randomInt $max]
  397. r setbit str $pos 1
  398. if {$first_one_pos == -1 || $first_one_pos > $pos} {
  399. # Update the position of the first 1 bit in the array
  400. # if the bit we set is on the left of the previous one.
  401. set first_one_pos $pos
  402. }
  403. }
  404. }
  405. test {BITPOS bit=0 fuzzy testing using SETBIT} {
  406. set max 524288; # 64k
  407. set first_zero_pos $max
  408. r set str [string repeat "\xff" [expr $max/8]]
  409. for {set j 0} {$j < 1000} {incr j} {
  410. assert {[r bitpos str 0] == $first_zero_pos}
  411. if {$first_zero_pos == $max} {
  412. assert {[r bitpos str 0 0 -1 bit] == -1}
  413. } else {
  414. assert {[r bitpos str 0 0 -1 bit] == $first_zero_pos}
  415. }
  416. set pos [randomInt $max]
  417. r setbit str $pos 0
  418. if {$first_zero_pos > $pos} {
  419. # Update the position of the first 0 bit in the array
  420. # if the bit we clear is on the left of the previous one.
  421. set first_zero_pos $pos
  422. }
  423. }
  424. }
  425. # This test creates a string of 10 bytes. It has two iterations. One clears
  426. # all the bits and sets just one bit and another set all the bits and clears
  427. # just one bit. Each iteration loops from bit offset 0 to 79 and uses SETBIT
  428. # to set the bit to 0 or 1, and then use BITPOS and BITCOUNT on a few mutations.
  429. test {BITPOS/BITCOUNT fuzzy testing using SETBIT} {
  430. # We have two start and end ranges, each range used to select a random
  431. # position, one for start position and one for end position.
  432. proc test_one {start1 end1 start2 end2 pos bit pos_type} {
  433. set start [randomRange $start1 $end1]
  434. set end [randomRange $start2 $end2]
  435. if {$start > $end} {
  436. # Swap start and end
  437. lassign [list $end $start] start end
  438. }
  439. set startbit $start
  440. set endbit $end
  441. # For byte index, we need to generate the real bit index
  442. if {[string equal $pos_type byte]} {
  443. set startbit [expr $start << 3]
  444. set endbit [expr ($end << 3) + 7]
  445. }
  446. # This means whether the test bit index is in the range.
  447. set inrange [expr ($pos >= $startbit && $pos <= $endbit) ? 1: 0]
  448. # For bitcount, there are four different results.
  449. # $inrange == 0 && $bit == 0, all bits in the range are set, so $endbit - $startbit + 1
  450. # $inrange == 0 && $bit == 1, all bits in the range are clear, so 0
  451. # $inrange == 1 && $bit == 0, all bits in the range are set but one, so $endbit - $startbit
  452. # $inrange == 1 && $bit == 1, all bits in the range are clear but one, so 1
  453. set res_count [expr ($endbit - $startbit + 1) * (1 - $bit) + $inrange * [expr $bit ? 1 : -1]]
  454. assert {[r bitpos str $bit $start $end $pos_type] == [expr $inrange ? $pos : -1]}
  455. assert {[r bitcount str $start $end $pos_type] == $res_count}
  456. }
  457. r del str
  458. set max 80;
  459. r setbit str [expr $max - 1] 0
  460. set bytes [expr $max >> 3]
  461. # First iteration sets all bits to 1, then set bit to 0 from 0 to max - 1
  462. # Second iteration sets all bits to 0, then set bit to 1 from 0 to max - 1
  463. for {set bit 0} {$bit < 2} {incr bit} {
  464. r bitop not str str
  465. for {set j 0} {$j < $max} {incr j} {
  466. r setbit str $j $bit
  467. # First iteration tests byte index and second iteration tests bit index.
  468. foreach {curr end pos_type} [list [expr $j >> 3] $bytes byte $j $max bit] {
  469. # start==end set to bit position
  470. test_one $curr $curr $curr $curr $j $bit $pos_type
  471. # Both start and end are before bit position
  472. if {$curr > 0} {
  473. test_one 0 $curr 0 $curr $j $bit $pos_type
  474. }
  475. # Both start and end are after bit position
  476. if {$curr < [expr $end - 1]} {
  477. test_one [expr $curr + 1] $end [expr $curr + 1] $end $j $bit $pos_type
  478. }
  479. # start is before and end is after bit position
  480. if {$curr > 0 && $curr < [expr $end - 1]} {
  481. test_one 0 $curr [expr $curr +1] $end $j $bit $pos_type
  482. }
  483. }
  484. # restore bit
  485. r setbit str $j [expr 1 - $bit]
  486. }
  487. }
  488. }
  489. test "BIT pos larger than UINT_MAX" {
  490. set bytes [expr (1 << 29) + 1]
  491. set bitpos [expr (1 << 32)]
  492. set oldval [lindex [r config get proto-max-bulk-len] 1]
  493. r config set proto-max-bulk-len $bytes
  494. r setbit mykey $bitpos 1
  495. assert_equal $bytes [r strlen mykey]
  496. assert_equal 1 [r getbit mykey $bitpos]
  497. assert_equal [list 128 128 -1] [r bitfield mykey get u8 $bitpos set u8 $bitpos 255 get i8 $bitpos]
  498. assert_equal $bitpos [r bitpos mykey 1]
  499. assert_equal $bitpos [r bitpos mykey 1 [expr $bytes - 1]]
  500. if {$::accurate} {
  501. # set all bits to 1
  502. set mega [expr (1 << 23)]
  503. set part [string repeat "\xFF" $mega]
  504. for {set i 0} {$i < 64} {incr i} {
  505. r setrange mykey [expr $i * $mega] $part
  506. }
  507. r setrange mykey [expr $bytes - 1] "\xFF"
  508. assert_equal [expr $bitpos + 8] [r bitcount mykey]
  509. assert_equal -1 [r bitpos mykey 0 0 [expr $bytes - 1]]
  510. }
  511. r config set proto-max-bulk-len $oldval
  512. r del mykey
  513. } {1} {large-memory}
  514. }