bitfield.tcl 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. start_server {tags {"bitops"}} {
  2. test {BITFIELD signed SET and GET basics} {
  3. r del bits
  4. set results {}
  5. lappend results [r bitfield bits set i8 0 -100]
  6. lappend results [r bitfield bits set i8 0 101]
  7. lappend results [r bitfield bits get i8 0]
  8. set results
  9. } {0 -100 101}
  10. test {BITFIELD unsigned SET and GET basics} {
  11. r del bits
  12. set results {}
  13. lappend results [r bitfield bits set u8 0 255]
  14. lappend results [r bitfield bits set u8 0 100]
  15. lappend results [r bitfield bits get u8 0]
  16. set results
  17. } {0 255 100}
  18. test {BITFIELD #<idx> form} {
  19. r del bits
  20. set results {}
  21. r bitfield bits set u8 #0 65
  22. r bitfield bits set u8 #1 66
  23. r bitfield bits set u8 #2 67
  24. r get bits
  25. } {ABC}
  26. test {BITFIELD basic INCRBY form} {
  27. r del bits
  28. set results {}
  29. r bitfield bits set u8 #0 10
  30. lappend results [r bitfield bits incrby u8 #0 100]
  31. lappend results [r bitfield bits incrby u8 #0 100]
  32. set results
  33. } {110 210}
  34. test {BITFIELD chaining of multiple commands} {
  35. r del bits
  36. set results {}
  37. r bitfield bits set u8 #0 10
  38. lappend results [r bitfield bits incrby u8 #0 100 incrby u8 #0 100]
  39. set results
  40. } {{110 210}}
  41. test {BITFIELD unsigned overflow wrap} {
  42. r del bits
  43. set results {}
  44. r bitfield bits set u8 #0 100
  45. lappend results [r bitfield bits overflow wrap incrby u8 #0 257]
  46. lappend results [r bitfield bits get u8 #0]
  47. lappend results [r bitfield bits overflow wrap incrby u8 #0 255]
  48. lappend results [r bitfield bits get u8 #0]
  49. } {101 101 100 100}
  50. test {BITFIELD unsigned overflow sat} {
  51. r del bits
  52. set results {}
  53. r bitfield bits set u8 #0 100
  54. lappend results [r bitfield bits overflow sat incrby u8 #0 257]
  55. lappend results [r bitfield bits get u8 #0]
  56. lappend results [r bitfield bits overflow sat incrby u8 #0 -255]
  57. lappend results [r bitfield bits get u8 #0]
  58. } {255 255 0 0}
  59. test {BITFIELD signed overflow wrap} {
  60. r del bits
  61. set results {}
  62. r bitfield bits set i8 #0 100
  63. lappend results [r bitfield bits overflow wrap incrby i8 #0 257]
  64. lappend results [r bitfield bits get i8 #0]
  65. lappend results [r bitfield bits overflow wrap incrby i8 #0 255]
  66. lappend results [r bitfield bits get i8 #0]
  67. } {101 101 100 100}
  68. test {BITFIELD signed overflow sat} {
  69. r del bits
  70. set results {}
  71. r bitfield bits set u8 #0 100
  72. lappend results [r bitfield bits overflow sat incrby i8 #0 257]
  73. lappend results [r bitfield bits get i8 #0]
  74. lappend results [r bitfield bits overflow sat incrby i8 #0 -255]
  75. lappend results [r bitfield bits get i8 #0]
  76. } {127 127 -128 -128}
  77. test {BITFIELD overflow detection fuzzing} {
  78. for {set j 0} {$j < 1000} {incr j} {
  79. set bits [expr {[randomInt 64]+1}]
  80. set sign [randomInt 2]
  81. set range [expr {2**$bits}]
  82. if {$bits == 64} {set sign 1} ; # u64 is not supported by BITFIELD.
  83. if {$sign} {
  84. set min [expr {-($range/2)}]
  85. set type "i$bits"
  86. } else {
  87. set min 0
  88. set type "u$bits"
  89. }
  90. set max [expr {$min+$range-1}]
  91. # Compare Tcl vs Redis
  92. set range2 [expr {$range*2}]
  93. set value [expr {($min*2)+[randomInt $range2]}]
  94. set increment [expr {($min*2)+[randomInt $range2]}]
  95. if {$value > 9223372036854775807} {
  96. set value 9223372036854775807
  97. }
  98. if {$value < -9223372036854775808} {
  99. set value -9223372036854775808
  100. }
  101. if {$increment > 9223372036854775807} {
  102. set increment 9223372036854775807
  103. }
  104. if {$increment < -9223372036854775808} {
  105. set increment -9223372036854775808
  106. }
  107. set overflow 0
  108. if {$value > $max || $value < $min} {set overflow 1}
  109. if {($value + $increment) > $max} {set overflow 1}
  110. if {($value + $increment) < $min} {set overflow 1}
  111. r del bits
  112. set res1 [r bitfield bits overflow fail set $type 0 $value]
  113. set res2 [r bitfield bits overflow fail incrby $type 0 $increment]
  114. if {$overflow && [lindex $res1 0] ne {} &&
  115. [lindex $res2 0] ne {}} {
  116. fail "OW not detected where needed: $type $value+$increment"
  117. }
  118. if {!$overflow && ([lindex $res1 0] eq {} ||
  119. [lindex $res2 0] eq {})} {
  120. fail "OW detected where NOT needed: $type $value+$increment"
  121. }
  122. }
  123. }
  124. test {BITFIELD overflow wrap fuzzing} {
  125. for {set j 0} {$j < 1000} {incr j} {
  126. set bits [expr {[randomInt 64]+1}]
  127. set sign [randomInt 2]
  128. set range [expr {2**$bits}]
  129. if {$bits == 64} {set sign 1} ; # u64 is not supported by BITFIELD.
  130. if {$sign} {
  131. set min [expr {-($range/2)}]
  132. set type "i$bits"
  133. } else {
  134. set min 0
  135. set type "u$bits"
  136. }
  137. set max [expr {$min+$range-1}]
  138. # Compare Tcl vs Redis
  139. set range2 [expr {$range*2}]
  140. set value [expr {($min*2)+[randomInt $range2]}]
  141. set increment [expr {($min*2)+[randomInt $range2]}]
  142. if {$value > 9223372036854775807} {
  143. set value 9223372036854775807
  144. }
  145. if {$value < -9223372036854775808} {
  146. set value -9223372036854775808
  147. }
  148. if {$increment > 9223372036854775807} {
  149. set increment 9223372036854775807
  150. }
  151. if {$increment < -9223372036854775808} {
  152. set increment -9223372036854775808
  153. }
  154. r del bits
  155. r bitfield bits overflow wrap set $type 0 $value
  156. r bitfield bits overflow wrap incrby $type 0 $increment
  157. set res [lindex [r bitfield bits get $type 0] 0]
  158. set expected 0
  159. if {$sign} {incr expected [expr {$max+1}]}
  160. incr expected $value
  161. incr expected $increment
  162. set expected [expr {$expected % $range}]
  163. if {$sign} {incr expected $min}
  164. if {$res != $expected} {
  165. fail "WRAP error: $type $value+$increment = $res, should be $expected"
  166. }
  167. }
  168. }
  169. test {BITFIELD regression for #3221} {
  170. r set bits 1
  171. r bitfield bits get u1 0
  172. } {0}
  173. }