]> git.saurik.com Git - redis.git/blame - tests/support/util.tcl
Test: MULTI/EXEC tests moved into multi.tcl.
[redis.git] / tests / support / util.tcl
CommitLineData
98578b57
PN
1proc randstring {min max {type binary}} {
2 set len [expr {$min+int(rand()*($max-$min+1))}]
3 set output {}
4 if {$type eq {binary}} {
5 set minval 0
6 set maxval 255
7 } elseif {$type eq {alpha}} {
8 set minval 48
9 set maxval 122
10 } elseif {$type eq {compr}} {
11 set minval 48
12 set maxval 52
13 }
14 while {$len} {
15 append output [format "%c" [expr {$minval+int(rand()*($maxval-$minval+1))}]]
16 incr len -1
17 }
18 return $output
19}
20
21# Useful for some test
22proc zlistAlikeSort {a b} {
23 if {[lindex $a 0] > [lindex $b 0]} {return 1}
24 if {[lindex $a 0] < [lindex $b 0]} {return -1}
25 string compare [lindex $a 1] [lindex $b 1]
26}
27
fdfb02e7
PN
28# Return all log lines starting with the first line that contains a warning.
29# Generally, this will be an assertion error with a stack trace.
30proc warnings_from_file {filename} {
31 set lines [split [exec cat $filename] "\n"]
32 set matched 0
2bcd18a2 33 set logall 0
fdfb02e7
PN
34 set result {}
35 foreach line $lines {
2bcd18a2 36 if {[string match {*REDIS BUG REPORT START*} $line]} {
37 set logall 1
38 }
fdfb02e7
PN
39 if {[regexp {^\[\d+\]\s+\d+\s+\w+\s+\d{2}:\d{2}:\d{2} \#} $line]} {
40 set matched 1
41 }
2bcd18a2 42 if {$logall || $matched} {
fdfb02e7
PN
43 lappend result $line
44 }
45 }
46 join $result "\n"
47}
48
9cf9e6f1
PN
49# Return value for INFO property
50proc status {r property} {
a0573260 51 if {[regexp "\r\n$property:(.*?)\r\n" [{*}$r info] _ value]} {
9cf9e6f1
PN
52 set _ $value
53 }
54}
55
98578b57
PN
56proc waitForBgsave r {
57 while 1 {
bc70b8e5 58 if {[status r rdb_bgsave_in_progress] eq 1} {
6f8a32d5
PN
59 if {$::verbose} {
60 puts -nonewline "\nWaiting for background save to finish... "
61 flush stdout
62 }
98578b57
PN
63 after 1000
64 } else {
65 break
66 }
67 }
68}
69
70proc waitForBgrewriteaof r {
71 while 1 {
bc70b8e5 72 if {[status r aof_rewrite_in_progress] eq 1} {
6f8a32d5
PN
73 if {$::verbose} {
74 puts -nonewline "\nWaiting for background AOF rewrite to finish... "
75 flush stdout
76 }
98578b57
PN
77 after 1000
78 } else {
79 break
80 }
81 }
82}
83
85ecc65e
PN
84proc wait_for_sync r {
85 while 1 {
80e808b6 86 if {[status $r master_link_status] eq "down"} {
85ecc65e
PN
87 after 10
88 } else {
89 break
90 }
91 }
92}
93
98578b57
PN
94proc randomInt {max} {
95 expr {int(rand()*$max)}
96}
97
c0de4592 98proc randomSignedInt {max} {
99 set i [randomInt $max]
100 if {rand() > 0.5} {
101 set i -$i
102 }
103 return $i
104}
105
98578b57
PN
106proc randpath args {
107 set path [expr {int(rand()*[llength $args])}]
108 uplevel 1 [lindex $args $path]
109}
110
111proc randomValue {} {
112 randpath {
113 # Small enough to likely collide
c0de4592 114 randomSignedInt 1000
98578b57
PN
115 } {
116 # 32 bit compressible signed/unsigned
c0de4592 117 randpath {randomSignedInt 2000000000} {randomSignedInt 4000000000}
98578b57
PN
118 } {
119 # 64 bit
c0de4592 120 randpath {randomSignedInt 1000000000000}
98578b57
PN
121 } {
122 # Random string
123 randpath {randstring 0 256 alpha} \
124 {randstring 0 256 compr} \
125 {randstring 0 256 binary}
126 }
127}
128
129proc randomKey {} {
130 randpath {
131 # Small enough to likely collide
132 randomInt 1000
133 } {
134 # 32 bit compressible signed/unsigned
135 randpath {randomInt 2000000000} {randomInt 4000000000}
136 } {
137 # 64 bit
138 randpath {randomInt 1000000000000}
139 } {
140 # Random string
141 randpath {randstring 1 256 alpha} \
142 {randstring 1 256 compr}
143 }
144}
145
b056ca39 146proc findKeyWithType {r type} {
147 for {set j 0} {$j < 20} {incr j} {
a0573260 148 set k [{*}$r randomkey]
b056ca39 149 if {$k eq {}} {
150 return {}
151 }
a0573260 152 if {[{*}$r type $k] eq $type} {
b056ca39 153 return $k
154 }
155 }
156 return {}
157}
158
6146329f 159proc createComplexDataset {r ops {opt {}}} {
98578b57
PN
160 for {set j 0} {$j < $ops} {incr j} {
161 set k [randomKey]
b056ca39 162 set k2 [randomKey]
98578b57
PN
163 set f [randomValue]
164 set v [randomValue]
6146329f 165
166 if {[lsearch -exact $opt useexpire] != -1} {
167 if {rand() < 0.1} {
168 {*}$r expire [randomKey] [randomInt 2]
169 }
170 }
171
98578b57
PN
172 randpath {
173 set d [expr {rand()}]
174 } {
175 set d [expr {rand()}]
176 } {
177 set d [expr {rand()}]
178 } {
179 set d [expr {rand()}]
180 } {
181 set d [expr {rand()}]
182 } {
183 randpath {set d +inf} {set d -inf}
184 }
a0573260 185 set t [{*}$r type $k]
98578b57
PN
186
187 if {$t eq {none}} {
188 randpath {
a0573260 189 {*}$r set $k $v
98578b57 190 } {
a0573260 191 {*}$r lpush $k $v
98578b57 192 } {
a0573260 193 {*}$r sadd $k $v
98578b57 194 } {
a0573260 195 {*}$r zadd $k $d $v
98578b57 196 } {
a0573260 197 {*}$r hset $k $f $v
b056ca39 198 } {
a0573260 199 {*}$r del $k
98578b57 200 }
a0573260 201 set t [{*}$r type $k]
98578b57
PN
202 }
203
204 switch $t {
205 {string} {
206 # Nothing to do
207 }
208 {list} {
a0573260 209 randpath {{*}$r lpush $k $v} \
210 {{*}$r rpush $k $v} \
211 {{*}$r lrem $k 0 $v} \
212 {{*}$r rpop $k} \
213 {{*}$r lpop $k}
98578b57
PN
214 }
215 {set} {
a0573260 216 randpath {{*}$r sadd $k $v} \
217 {{*}$r srem $k $v} \
b056ca39 218 {
4d7e1255 219 set otherset [findKeyWithType {*}$r set]
b056ca39 220 if {$otherset ne {}} {
a0573260 221 randpath {
222 {*}$r sunionstore $k2 $k $otherset
223 } {
224 {*}$r sinterstore $k2 $k $otherset
225 } {
226 {*}$r sdiffstore $k2 $k $otherset
227 }
b056ca39 228 }
229 }
98578b57
PN
230 }
231 {zset} {
a0573260 232 randpath {{*}$r zadd $k $d $v} \
233 {{*}$r zrem $k $v} \
b056ca39 234 {
4d7e1255 235 set otherzset [findKeyWithType {*}$r zset]
b056ca39 236 if {$otherzset ne {}} {
a0573260 237 randpath {
238 {*}$r zunionstore $k2 2 $k $otherzset
239 } {
240 {*}$r zinterstore $k2 2 $k $otherzset
241 }
b056ca39 242 }
243 }
98578b57
PN
244 }
245 {hash} {
a0573260 246 randpath {{*}$r hset $k $f $v} \
247 {{*}$r hdel $k $f}
98578b57
PN
248 }
249 }
250 }
251}
53cbf66c
PN
252
253proc formatCommand {args} {
254 set cmd "*[llength $args]\r\n"
255 foreach a $args {
256 append cmd "$[string length $a]\r\n$a\r\n"
257 }
258 set _ $cmd
259}
dd3f505f 260
261proc csvdump r {
262 set o {}
a0573260 263 foreach k [lsort [{*}$r keys *]] {
264 set type [{*}$r type $k]
dd3f505f 265 append o [csvstring $k] , [csvstring $type] ,
266 switch $type {
267 string {
a0573260 268 append o [csvstring [{*}$r get $k]] "\n"
dd3f505f 269 }
270 list {
a0573260 271 foreach e [{*}$r lrange $k 0 -1] {
dd3f505f 272 append o [csvstring $e] ,
273 }
274 append o "\n"
275 }
276 set {
a0573260 277 foreach e [lsort [{*}$r smembers $k]] {
dd3f505f 278 append o [csvstring $e] ,
279 }
280 append o "\n"
281 }
282 zset {
a0573260 283 foreach e [{*}$r zrange $k 0 -1 withscores] {
dd3f505f 284 append o [csvstring $e] ,
285 }
286 append o "\n"
287 }
288 hash {
a0573260 289 set fields [{*}$r hgetall $k]
dd3f505f 290 set newfields {}
291 foreach {k v} $fields {
292 lappend newfields [list $k $v]
293 }
294 set fields [lsort -index 0 $newfields]
295 foreach kv $fields {
296 append o [csvstring [lindex $kv 0]] ,
297 append o [csvstring [lindex $kv 1]] ,
298 }
299 append o "\n"
300 }
301 }
302 }
303 return $o
304}
305
306proc csvstring s {
307 return "\"$s\""
308}
bf758397 309
310proc roundFloat f {
311 format "%.10g" $f
312}