]> git.saurik.com Git - redis.git/blob - tests/unit/bitops.tcl
BITCOUNT performance improved.
[redis.git] / tests / unit / bitops.tcl
1 # Compare Redis commadns 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
7 proc simulate_bit_op {op args} {
8 set maxlen 0
9 set j 0
10 set count [llength $args]
11 foreach a $args {
12 binary scan $a b* bits
13 set b($j) $bits
14 if {[string length $bits] > $maxlen} {
15 set maxlen [string length $bits]
16 }
17 incr j
18 }
19 for {set j 0} {$j < $count} {incr j} {
20 if {[string length $b($j)] < $maxlen} {
21 append b($j) [string repeat 0 [expr $maxlen-[string length $b($j)]]]
22 }
23 }
24 set out {}
25 for {set x 0} {$x < $maxlen} {incr x} {
26 set bit [string range $b(0) $x $x]
27 for {set j 1} {$j < $count} {incr j} {
28 set bit2 [string range $b($j) $x $x]
29 switch $op {
30 and {set bit [expr {$bit & $bit2}]}
31 or {set bit [expr {$bit | $bit2}]}
32 xor {set bit [expr {$bit ^ $bit2}]}
33 not {set bit [expr {!$bit}]}
34 }
35 }
36 append out $bit
37 }
38 binary format b* $out
39 }
40
41 start_server {tags {"bitops"}} {
42 test {BITCOUNT returns 0 against non existing key} {
43 r bitcount no-key
44 } 0
45
46 catch {unset num}
47 foreach vec [list "" "\xaa" "\x00\x00\xff" "foobar"] {
48 incr num
49 test "BITCOUNT against test vector #$num" {
50 r set str $vec
51 assert {[r bitcount str] == [count_bits $vec]}
52 }
53 }
54
55 test {BITCOUNT fuzzing} {
56 for {set j 0} {$j < 100} {incr j} {
57 set str [randstring 0 3000]
58 r set str $str
59 assert {[r bitcount str] == [count_bits $str]}
60 }
61 }
62
63 test {BITCOUNT with start, end} {
64 r set s "foobar"
65 assert_equal [r bitcount s 0 -1] [count_bits "foobar"]
66 assert_equal [r bitcount s 1 -2] [count_bits "ooba"]
67 assert_equal [r bitcount s -2 1] [count_bits ""]
68 assert_equal [r bitcount s 0 1000] [count_bits "foobar"]
69 }
70
71 test {BITCOUNT syntax error #1} {
72 catch {r bitcount s 0} e
73 set e
74 } {ERR*syntax*}
75
76 test {BITOP NOT (empty string)} {
77 r set s ""
78 r bitop not dest s
79 r get dest
80 } {}
81
82 test {BITOP NOT (known string)} {
83 r set s "\xaa\x00\xff\x55"
84 r bitop not dest s
85 r get dest
86 } "\x55\xff\x00\xaa"
87
88 test {BITOP where dest and target are the same key} {
89 r set s "\xaa\x00\xff\x55"
90 r bitop not s s
91 r get s
92 } "\x55\xff\x00\xaa"
93
94 test {BITOP AND|OR|XOR don't change the string with single input key} {
95 r set a "\x01\x02\xff"
96 r bitop and res1 a
97 r bitop or res2 a
98 r bitop xor res3 a
99 list [r get res1] [r get res2] [r get res3]
100 } [list "\x01\x02\xff" "\x01\x02\xff" "\x01\x02\xff"]
101
102 test {BITOP missing key is considered a stream of zero} {
103 r set a "\x01\x02\xff"
104 r bitop and res1 no-suck-key a
105 r bitop or res2 no-suck-key a no-such-key
106 r bitop xor res3 no-such-key a
107 list [r get res1] [r get res2] [r get res3]
108 } [list "\x00\x00\x00" "\x01\x02\xff" "\x01\x02\xff"]
109
110 test {BITOP shorter keys are zero-padded to the key with max length} {
111 r set a "\x01\x02\xff\xff"
112 r set b "\x01\x02\xff"
113 r bitop and res1 a b
114 r bitop or res2 a b
115 r bitop xor res3 a b
116 list [r get res1] [r get res2] [r get res3]
117 } [list "\x01\x02\xff\x00" "\x01\x02\xff\xff" "\x00\x00\x00\xff"]
118
119 foreach op {and or xor} {
120 test "BITOP $op fuzzing" {
121 for {set i 0} {$i < 10} {incr i} {
122 set vec {}
123 set veckeys {}
124 set numvec [expr {[randomInt 10]+1}]
125 for {set j 0} {$j < $numvec} {incr j} {
126 set str [randstring 0 1000]
127 lappend vec $str
128 lappend veckeys vector_$j
129 r set vector_$j $str
130 }
131 r bitop $op target {*}$veckeys
132 assert_equal [r get target] [simulate_bit_op $op {*}$vec]
133 }
134 }
135 }
136 }