mirror of
https://github.com/fluencelabs/redis
synced 2025-03-19 17:10:50 +00:00
131 lines
3.9 KiB
Tcl
131 lines
3.9 KiB
Tcl
|
# Compare Redis commadns against Tcl implementations of the same commands.
|
||
|
proc count_bits s {
|
||
|
binary scan $s b* bits
|
||
|
string length [regsub -all {0} $bits {}]
|
||
|
}
|
||
|
|
||
|
proc simulate_bit_op {op args} {
|
||
|
set maxlen 0
|
||
|
set j 0
|
||
|
set count [llength $args]
|
||
|
foreach a $args {
|
||
|
binary scan $a b* bits
|
||
|
set b($j) $bits
|
||
|
if {[string length $bits] > $maxlen} {
|
||
|
set maxlen [string length $bits]
|
||
|
}
|
||
|
incr j
|
||
|
}
|
||
|
for {set j 0} {$j < $count} {incr j} {
|
||
|
if {[string length $b($j)] < $maxlen} {
|
||
|
append b($j) [string repeat 0 [expr $maxlen-[string length $b($j)]]]
|
||
|
}
|
||
|
}
|
||
|
set out {}
|
||
|
for {set x 0} {$x < $maxlen} {incr x} {
|
||
|
set bit [string range $b(0) $x $x]
|
||
|
for {set j 1} {$j < $count} {incr j} {
|
||
|
set bit2 [string range $b($j) $x $x]
|
||
|
switch $op {
|
||
|
and {set bit [expr {$bit & $bit2}]}
|
||
|
or {set bit [expr {$bit | $bit2}]}
|
||
|
xor {set bit [expr {$bit ^ $bit2}]}
|
||
|
not {set bit [expr {!$bit}]}
|
||
|
}
|
||
|
}
|
||
|
append out $bit
|
||
|
}
|
||
|
binary format b* $out
|
||
|
}
|
||
|
|
||
|
start_server {tags {"bitops"}} {
|
||
|
test {BITCOUNT returns 0 against non existing key} {
|
||
|
r bitcount no-key
|
||
|
} 0
|
||
|
|
||
|
catch {unset num}
|
||
|
foreach vec [list \
|
||
|
"" "\xaa" "\x00\x00\xff" "foobar" \
|
||
|
[randstring 2000 3000] [randstring 2000 3000] \
|
||
|
[randstring 2000 3000] \
|
||
|
] {
|
||
|
incr num
|
||
|
test "BITCOUNT against test vector #$num" {
|
||
|
r set str $vec
|
||
|
assert {[r bitcount str] == [count_bits $vec]}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
test {BITCOUNT with start, end} {
|
||
|
r set s "foobar"
|
||
|
assert_equal [r bitcount s 0 -1] [count_bits "foobar"]
|
||
|
assert_equal [r bitcount s 1 -2] [count_bits "ooba"]
|
||
|
assert_equal [r bitcount s -2 1] [count_bits ""]
|
||
|
assert_equal [r bitcount s 0 1000] [count_bits "foobar"]
|
||
|
}
|
||
|
|
||
|
test {BITCOUNT syntax error #1} {
|
||
|
catch {r bitcount s 0} e
|
||
|
set e
|
||
|
} {ERR*syntax*}
|
||
|
|
||
|
test {BITOP NOT (empty string)} {
|
||
|
r set s ""
|
||
|
r bitop not dest s
|
||
|
r get dest
|
||
|
} {}
|
||
|
|
||
|
test {BITOP NOT (known string)} {
|
||
|
r set s "\xaa\x00\xff\x55"
|
||
|
r bitop not dest s
|
||
|
r get dest
|
||
|
} "\x55\xff\x00\xaa"
|
||
|
|
||
|
test {BITOP where dest and target are the same key} {
|
||
|
r set s "\xaa\x00\xff\x55"
|
||
|
r bitop not s s
|
||
|
r get s
|
||
|
} "\x55\xff\x00\xaa"
|
||
|
|
||
|
test {BITOP AND|OR|XOR don't change the string with single input key} {
|
||
|
r set a "\x01\x02\xff"
|
||
|
r bitop and res1 a
|
||
|
r bitop or res2 a
|
||
|
r bitop xor res3 a
|
||
|
list [r get res1] [r get res2] [r get res3]
|
||
|
} [list "\x01\x02\xff" "\x01\x02\xff" "\x01\x02\xff"]
|
||
|
|
||
|
test {BITOP missing key is considered a stream of zero} {
|
||
|
r set a "\x01\x02\xff"
|
||
|
r bitop and res1 no-suck-key a
|
||
|
r bitop or res2 no-suck-key a no-such-key
|
||
|
r bitop xor res3 no-such-key a
|
||
|
list [r get res1] [r get res2] [r get res3]
|
||
|
} [list "\x00\x00\x00" "\x01\x02\xff" "\x01\x02\xff"]
|
||
|
|
||
|
test {BITOP shorter keys are zero-padded to the key with max length} {
|
||
|
r set a "\x01\x02\xff\xff"
|
||
|
r set b "\x01\x02\xff"
|
||
|
r bitop and res1 a b
|
||
|
r bitop or res2 a b
|
||
|
r bitop xor res3 a b
|
||
|
list [r get res1] [r get res2] [r get res3]
|
||
|
} [list "\x01\x02\xff\x00" "\x01\x02\xff\xff" "\x00\x00\x00\xff"]
|
||
|
|
||
|
foreach op {and or xor} {
|
||
|
test "BITOP $op fuzzing" {
|
||
|
set vec {}
|
||
|
set veckeys {}
|
||
|
set numvec [expr {[randomInt 10]+1}]
|
||
|
for {set j 0} {$j < $numvec} {incr j} {
|
||
|
set str [randstring 0 1000]
|
||
|
lappend vec $str
|
||
|
lappend veckeys vector_$j
|
||
|
r set vector_$j $str
|
||
|
}
|
||
|
r bitop $op target {*}$veckeys
|
||
|
assert_equal [r get target] [simulate_bit_op $op {*}$vec]
|
||
|
}
|
||
|
}
|
||
|
}
|