]> git.saurik.com Git - redis.git/blob - tests/unit/bitops.tcl
5945d32d710c5024e89cc189e665f06734fbeb6e
[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 if {$op eq {not}} {set bit [expr {!$bit}]}
28 for {set j 1} {$j < $count} {incr j} {
29 set bit2 [string range $b($j) $x $x]
30 switch $op {
31 and {set bit [expr {$bit & $bit2}]}
32 or {set bit [expr {$bit | $bit2}]}
33 xor {set bit [expr {$bit ^ $bit2}]}
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" "123"] {
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 {BITCOUNT regression test for github issue #582} {
77 r del str
78 r setbit foo 0 1
79 r bitcount foo 0 4294967296
80 } {1}
81
82 test {BITOP NOT (empty string)} {
83 r set s ""
84 r bitop not dest s
85 r get dest
86 } {}
87
88 test {BITOP NOT (known string)} {
89 r set s "\xaa\x00\xff\x55"
90 r bitop not dest s
91 r get dest
92 } "\x55\xff\x00\xaa"
93
94 test {BITOP where dest and target are the same key} {
95 r set s "\xaa\x00\xff\x55"
96 r bitop not s s
97 r get s
98 } "\x55\xff\x00\xaa"
99
100 test {BITOP AND|OR|XOR don't change the string with single input key} {
101 r set a "\x01\x02\xff"
102 r bitop and res1 a
103 r bitop or res2 a
104 r bitop xor res3 a
105 list [r get res1] [r get res2] [r get res3]
106 } [list "\x01\x02\xff" "\x01\x02\xff" "\x01\x02\xff"]
107
108 test {BITOP missing key is considered a stream of zero} {
109 r set a "\x01\x02\xff"
110 r bitop and res1 no-suck-key a
111 r bitop or res2 no-suck-key a no-such-key
112 r bitop xor res3 no-such-key a
113 list [r get res1] [r get res2] [r get res3]
114 } [list "\x00\x00\x00" "\x01\x02\xff" "\x01\x02\xff"]
115
116 test {BITOP shorter keys are zero-padded to the key with max length} {
117 r set a "\x01\x02\xff\xff"
118 r set b "\x01\x02\xff"
119 r bitop and res1 a b
120 r bitop or res2 a b
121 r bitop xor res3 a b
122 list [r get res1] [r get res2] [r get res3]
123 } [list "\x01\x02\xff\x00" "\x01\x02\xff\xff" "\x00\x00\x00\xff"]
124
125 foreach op {and or xor} {
126 test "BITOP $op fuzzing" {
127 for {set i 0} {$i < 10} {incr i} {
128 r flushall
129 set vec {}
130 set veckeys {}
131 set numvec [expr {[randomInt 10]+1}]
132 for {set j 0} {$j < $numvec} {incr j} {
133 set str [randstring 0 1000]
134 lappend vec $str
135 lappend veckeys vector_$j
136 r set vector_$j $str
137 }
138 r bitop $op target {*}$veckeys
139 assert_equal [r get target] [simulate_bit_op $op {*}$vec]
140 }
141 }
142 }
143
144 test {BITOP NOT fuzzing} {
145 for {set i 0} {$i < 10} {incr i} {
146 r flushall
147 set str [randstring 0 1000]
148 r set str $str
149 r bitop not target str
150 assert_equal [r get target] [simulate_bit_op not $str]
151 }
152 }
153
154 test {BITOP with integer encoded source objects} {
155 r set a 1
156 r set b 2
157 r bitop xor dest a b a
158 r get dest
159 } {2}
160
161 test {BITOP with non string source key} {
162 r del c
163 r set a 1
164 r set b 2
165 r lpush c foo
166 catch {r bitop xor dest a b c d} e
167 set e
168 } {*ERR*}
169
170 test {BITOP with empty string after non empty string (issue #529)} {
171 r flushdb
172 r set a "\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"
173 r bitop or x a b
174 } {32}
175 }