diff options
Diffstat (limited to 'examples/redis-unstable/tests/unit/bitfield.tcl')
| -rw-r--r-- | examples/redis-unstable/tests/unit/bitfield.tcl | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/examples/redis-unstable/tests/unit/bitfield.tcl b/examples/redis-unstable/tests/unit/bitfield.tcl new file mode 100644 index 0000000..21091aa --- /dev/null +++ b/examples/redis-unstable/tests/unit/bitfield.tcl | |||
| @@ -0,0 +1,263 @@ | |||
| 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 | |||
| 11 | test {BITFIELD unsigned SET and GET basics} { | ||
| 12 | r del bits | ||
| 13 | set results {} | ||
| 14 | lappend results [r bitfield bits set u8 0 255] | ||
| 15 | lappend results [r bitfield bits set u8 0 100] | ||
| 16 | lappend results [r bitfield bits get u8 0] | ||
| 17 | set results | ||
| 18 | } {0 255 100} | ||
| 19 | |||
| 20 | test {BITFIELD signed SET and GET together} { | ||
| 21 | r del bits | ||
| 22 | set results [r bitfield bits set i8 0 255 set i8 0 100 get i8 0] | ||
| 23 | } {0 -1 100} | ||
| 24 | |||
| 25 | test {BITFIELD unsigned with SET, GET and INCRBY arguments} { | ||
| 26 | r del bits | ||
| 27 | set results [r bitfield bits set u8 0 255 incrby u8 0 100 get u8 0] | ||
| 28 | } {0 99 99} | ||
| 29 | |||
| 30 | test {BITFIELD with only key as argument} { | ||
| 31 | r del bits | ||
| 32 | set result [r bitfield bits] | ||
| 33 | assert {$result eq {}} | ||
| 34 | } | ||
| 35 | |||
| 36 | test {BITFIELD #<idx> form} { | ||
| 37 | r del bits | ||
| 38 | set results {} | ||
| 39 | r bitfield bits set u8 #0 65 | ||
| 40 | r bitfield bits set u8 #1 66 | ||
| 41 | r bitfield bits set u8 #2 67 | ||
| 42 | r get bits | ||
| 43 | } {ABC} | ||
| 44 | |||
| 45 | test {BITFIELD basic INCRBY form} { | ||
| 46 | r del bits | ||
| 47 | set results {} | ||
| 48 | r bitfield bits set u8 #0 10 | ||
| 49 | lappend results [r bitfield bits incrby u8 #0 100] | ||
| 50 | lappend results [r bitfield bits incrby u8 #0 100] | ||
| 51 | set results | ||
| 52 | } {110 210} | ||
| 53 | |||
| 54 | test {BITFIELD chaining of multiple commands} { | ||
| 55 | r del bits | ||
| 56 | set results {} | ||
| 57 | r bitfield bits set u8 #0 10 | ||
| 58 | lappend results [r bitfield bits incrby u8 #0 100 incrby u8 #0 100] | ||
| 59 | set results | ||
| 60 | } {{110 210}} | ||
| 61 | |||
| 62 | test {BITFIELD unsigned overflow wrap} { | ||
| 63 | r del bits | ||
| 64 | set results {} | ||
| 65 | r bitfield bits set u8 #0 100 | ||
| 66 | lappend results [r bitfield bits overflow wrap incrby u8 #0 257] | ||
| 67 | lappend results [r bitfield bits get u8 #0] | ||
| 68 | lappend results [r bitfield bits overflow wrap incrby u8 #0 255] | ||
| 69 | lappend results [r bitfield bits get u8 #0] | ||
| 70 | } {101 101 100 100} | ||
| 71 | |||
| 72 | test {BITFIELD unsigned overflow sat} { | ||
| 73 | r del bits | ||
| 74 | set results {} | ||
| 75 | r bitfield bits set u8 #0 100 | ||
| 76 | lappend results [r bitfield bits overflow sat incrby u8 #0 257] | ||
| 77 | lappend results [r bitfield bits get u8 #0] | ||
| 78 | lappend results [r bitfield bits overflow sat incrby u8 #0 -255] | ||
| 79 | lappend results [r bitfield bits get u8 #0] | ||
| 80 | } {255 255 0 0} | ||
| 81 | |||
| 82 | test {BITFIELD signed overflow wrap} { | ||
| 83 | r del bits | ||
| 84 | set results {} | ||
| 85 | r bitfield bits set i8 #0 100 | ||
| 86 | lappend results [r bitfield bits overflow wrap incrby i8 #0 257] | ||
| 87 | lappend results [r bitfield bits get i8 #0] | ||
| 88 | lappend results [r bitfield bits overflow wrap incrby i8 #0 255] | ||
| 89 | lappend results [r bitfield bits get i8 #0] | ||
| 90 | } {101 101 100 100} | ||
| 91 | |||
| 92 | test {BITFIELD signed overflow sat} { | ||
| 93 | r del bits | ||
| 94 | set results {} | ||
| 95 | r bitfield bits set u8 #0 100 | ||
| 96 | lappend results [r bitfield bits overflow sat incrby i8 #0 257] | ||
| 97 | lappend results [r bitfield bits get i8 #0] | ||
| 98 | lappend results [r bitfield bits overflow sat incrby i8 #0 -255] | ||
| 99 | lappend results [r bitfield bits get i8 #0] | ||
| 100 | } {127 127 -128 -128} | ||
| 101 | |||
| 102 | test {BITFIELD overflow detection fuzzing} { | ||
| 103 | for {set j 0} {$j < 1000} {incr j} { | ||
| 104 | set bits [expr {[randomInt 64]+1}] | ||
| 105 | set sign [randomInt 2] | ||
| 106 | set range [expr {2**$bits}] | ||
| 107 | if {$bits == 64} {set sign 1} ; # u64 is not supported by BITFIELD. | ||
| 108 | if {$sign} { | ||
| 109 | set min [expr {-($range/2)}] | ||
| 110 | set type "i$bits" | ||
| 111 | } else { | ||
| 112 | set min 0 | ||
| 113 | set type "u$bits" | ||
| 114 | } | ||
| 115 | set max [expr {$min+$range-1}] | ||
| 116 | |||
| 117 | # Compare Tcl vs Redis | ||
| 118 | set range2 [expr {$range*2}] | ||
| 119 | set value [expr {($min*2)+[randomInt $range2]}] | ||
| 120 | set increment [expr {($min*2)+[randomInt $range2]}] | ||
| 121 | if {$value > 9223372036854775807} { | ||
| 122 | set value 9223372036854775807 | ||
| 123 | } | ||
| 124 | if {$value < -9223372036854775808} { | ||
| 125 | set value -9223372036854775808 | ||
| 126 | } | ||
| 127 | if {$increment > 9223372036854775807} { | ||
| 128 | set increment 9223372036854775807 | ||
| 129 | } | ||
| 130 | if {$increment < -9223372036854775808} { | ||
| 131 | set increment -9223372036854775808 | ||
| 132 | } | ||
| 133 | |||
| 134 | set overflow 0 | ||
| 135 | if {$value > $max || $value < $min} {set overflow 1} | ||
| 136 | if {($value + $increment) > $max} {set overflow 1} | ||
| 137 | if {($value + $increment) < $min} {set overflow 1} | ||
| 138 | |||
| 139 | r del bits | ||
| 140 | set res1 [r bitfield bits overflow fail set $type 0 $value] | ||
| 141 | set res2 [r bitfield bits overflow fail incrby $type 0 $increment] | ||
| 142 | |||
| 143 | if {$overflow && [lindex $res1 0] ne {} && | ||
| 144 | [lindex $res2 0] ne {}} { | ||
| 145 | fail "OW not detected where needed: $type $value+$increment" | ||
| 146 | } | ||
| 147 | if {!$overflow && ([lindex $res1 0] eq {} || | ||
| 148 | [lindex $res2 0] eq {})} { | ||
| 149 | fail "OW detected where NOT needed: $type $value+$increment" | ||
| 150 | } | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | test {BITFIELD overflow wrap fuzzing} { | ||
| 155 | for {set j 0} {$j < 1000} {incr j} { | ||
| 156 | set bits [expr {[randomInt 64]+1}] | ||
| 157 | set sign [randomInt 2] | ||
| 158 | set range [expr {2**$bits}] | ||
| 159 | if {$bits == 64} {set sign 1} ; # u64 is not supported by BITFIELD. | ||
| 160 | if {$sign} { | ||
| 161 | set min [expr {-($range/2)}] | ||
| 162 | set type "i$bits" | ||
| 163 | } else { | ||
| 164 | set min 0 | ||
| 165 | set type "u$bits" | ||
| 166 | } | ||
| 167 | set max [expr {$min+$range-1}] | ||
| 168 | |||
| 169 | # Compare Tcl vs Redis | ||
| 170 | set range2 [expr {$range*2}] | ||
| 171 | set value [expr {($min*2)+[randomInt $range2]}] | ||
| 172 | set increment [expr {($min*2)+[randomInt $range2]}] | ||
| 173 | if {$value > 9223372036854775807} { | ||
| 174 | set value 9223372036854775807 | ||
| 175 | } | ||
| 176 | if {$value < -9223372036854775808} { | ||
| 177 | set value -9223372036854775808 | ||
| 178 | } | ||
| 179 | if {$increment > 9223372036854775807} { | ||
| 180 | set increment 9223372036854775807 | ||
| 181 | } | ||
| 182 | if {$increment < -9223372036854775808} { | ||
| 183 | set increment -9223372036854775808 | ||
| 184 | } | ||
| 185 | |||
| 186 | r del bits | ||
| 187 | r bitfield bits overflow wrap set $type 0 $value | ||
| 188 | r bitfield bits overflow wrap incrby $type 0 $increment | ||
| 189 | set res [lindex [r bitfield bits get $type 0] 0] | ||
| 190 | |||
| 191 | set expected 0 | ||
| 192 | if {$sign} {incr expected [expr {$max+1}]} | ||
| 193 | incr expected $value | ||
| 194 | incr expected $increment | ||
| 195 | set expected [expr {$expected % $range}] | ||
| 196 | if {$sign} {incr expected $min} | ||
| 197 | |||
| 198 | if {$res != $expected} { | ||
| 199 | fail "WRAP error: $type $value+$increment = $res, should be $expected" | ||
| 200 | } | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | test {BITFIELD regression for #3221} { | ||
| 205 | r set bits 1 | ||
| 206 | r bitfield bits get u1 0 | ||
| 207 | } {0} | ||
| 208 | |||
| 209 | test {BITFIELD regression for #3564} { | ||
| 210 | for {set j 0} {$j < 10} {incr j} { | ||
| 211 | r del mystring | ||
| 212 | set res [r BITFIELD mystring SET i8 0 10 SET i8 64 10 INCRBY i8 10 99900] | ||
| 213 | assert {$res eq {0 0 60}} | ||
| 214 | } | ||
| 215 | r del mystring | ||
| 216 | } | ||
| 217 | |||
| 218 | test {BITFIELD_RO with only key as argument} { | ||
| 219 | set res [r bitfield_ro bits] | ||
| 220 | assert {$res eq {}} | ||
| 221 | } | ||
| 222 | |||
| 223 | test {BITFIELD_RO fails when write option is used} { | ||
| 224 | catch {r bitfield_ro bits set u8 0 100 get u8 0} err | ||
| 225 | assert_match {*ERR BITFIELD_RO only supports the GET subcommand*} $err | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | start_server {tags {"repl external:skip"}} { | ||
| 230 | start_server {} { | ||
| 231 | set master [srv -1 client] | ||
| 232 | set master_host [srv -1 host] | ||
| 233 | set master_port [srv -1 port] | ||
| 234 | set slave [srv 0 client] | ||
| 235 | |||
| 236 | test {BITFIELD: setup slave} { | ||
| 237 | $slave slaveof $master_host $master_port | ||
| 238 | wait_for_condition 50 100 { | ||
| 239 | [s 0 master_link_status] eq {up} | ||
| 240 | } else { | ||
| 241 | fail "Replication not started." | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | test {BITFIELD: write on master, read on slave} { | ||
| 246 | $master del bits | ||
| 247 | assert_equal 0 [$master bitfield bits set u8 0 255] | ||
| 248 | assert_equal 255 [$master bitfield bits set u8 0 100] | ||
| 249 | wait_for_ofs_sync $master $slave | ||
| 250 | assert_equal 100 [$slave bitfield_ro bits get u8 0] | ||
| 251 | } | ||
| 252 | |||
| 253 | test {BITFIELD_RO with only key as argument on read-only replica} { | ||
| 254 | set res [$slave bitfield_ro bits] | ||
| 255 | assert {$res eq {}} | ||
| 256 | } | ||
| 257 | |||
| 258 | test {BITFIELD_RO fails when write option is used on read-only replica} { | ||
| 259 | catch {$slave bitfield_ro bits set u8 0 100 get u8 0} err | ||
| 260 | assert_match {*ERR BITFIELD_RO only supports the GET subcommand*} $err | ||
| 261 | } | ||
| 262 | } | ||
| 263 | } | ||
