]> git.saurik.com Git - redis.git/blame - tests/support/util.tcl
Redis test: include bug report on crash.
[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 {
9cf9e6f1 58 if {[status r 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 {
9cf9e6f1 72 if {[status r bgrewriteaof_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 {
86 if {[status r master_link_status] eq "down"} {
87 after 10
88 } else {
89 break
90 }
91 }
92}
93
98578b57
PN
94proc randomInt {max} {
95 expr {int(rand()*$max)}
96}
97
98proc randpath args {
99 set path [expr {int(rand()*[llength $args])}]
100 uplevel 1 [lindex $args $path]
101}
102
103proc randomValue {} {
104 randpath {
105 # Small enough to likely collide
106 randomInt 1000
107 } {
108 # 32 bit compressible signed/unsigned
109 randpath {randomInt 2000000000} {randomInt 4000000000}
110 } {
111 # 64 bit
112 randpath {randomInt 1000000000000}
113 } {
114 # Random string
115 randpath {randstring 0 256 alpha} \
116 {randstring 0 256 compr} \
117 {randstring 0 256 binary}
118 }
119}
120
121proc randomKey {} {
122 randpath {
123 # Small enough to likely collide
124 randomInt 1000
125 } {
126 # 32 bit compressible signed/unsigned
127 randpath {randomInt 2000000000} {randomInt 4000000000}
128 } {
129 # 64 bit
130 randpath {randomInt 1000000000000}
131 } {
132 # Random string
133 randpath {randstring 1 256 alpha} \
134 {randstring 1 256 compr}
135 }
136}
137
b056ca39 138proc findKeyWithType {r type} {
139 for {set j 0} {$j < 20} {incr j} {
a0573260 140 set k [{*}$r randomkey]
b056ca39 141 if {$k eq {}} {
142 return {}
143 }
a0573260 144 if {[{*}$r type $k] eq $type} {
b056ca39 145 return $k
146 }
147 }
148 return {}
149}
150
6146329f 151proc createComplexDataset {r ops {opt {}}} {
98578b57
PN
152 for {set j 0} {$j < $ops} {incr j} {
153 set k [randomKey]
b056ca39 154 set k2 [randomKey]
98578b57
PN
155 set f [randomValue]
156 set v [randomValue]
6146329f 157
158 if {[lsearch -exact $opt useexpire] != -1} {
159 if {rand() < 0.1} {
160 {*}$r expire [randomKey] [randomInt 2]
161 }
162 }
163
98578b57
PN
164 randpath {
165 set d [expr {rand()}]
166 } {
167 set d [expr {rand()}]
168 } {
169 set d [expr {rand()}]
170 } {
171 set d [expr {rand()}]
172 } {
173 set d [expr {rand()}]
174 } {
175 randpath {set d +inf} {set d -inf}
176 }
a0573260 177 set t [{*}$r type $k]
98578b57
PN
178
179 if {$t eq {none}} {
180 randpath {
a0573260 181 {*}$r set $k $v
98578b57 182 } {
a0573260 183 {*}$r lpush $k $v
98578b57 184 } {
a0573260 185 {*}$r sadd $k $v
98578b57 186 } {
a0573260 187 {*}$r zadd $k $d $v
98578b57 188 } {
a0573260 189 {*}$r hset $k $f $v
b056ca39 190 } {
a0573260 191 {*}$r del $k
98578b57 192 }
a0573260 193 set t [{*}$r type $k]
98578b57
PN
194 }
195
196 switch $t {
197 {string} {
198 # Nothing to do
199 }
200 {list} {
a0573260 201 randpath {{*}$r lpush $k $v} \
202 {{*}$r rpush $k $v} \
203 {{*}$r lrem $k 0 $v} \
204 {{*}$r rpop $k} \
205 {{*}$r lpop $k}
98578b57
PN
206 }
207 {set} {
a0573260 208 randpath {{*}$r sadd $k $v} \
209 {{*}$r srem $k $v} \
b056ca39 210 {
4d7e1255 211 set otherset [findKeyWithType {*}$r set]
b056ca39 212 if {$otherset ne {}} {
a0573260 213 randpath {
214 {*}$r sunionstore $k2 $k $otherset
215 } {
216 {*}$r sinterstore $k2 $k $otherset
217 } {
218 {*}$r sdiffstore $k2 $k $otherset
219 }
b056ca39 220 }
221 }
98578b57
PN
222 }
223 {zset} {
a0573260 224 randpath {{*}$r zadd $k $d $v} \
225 {{*}$r zrem $k $v} \
b056ca39 226 {
4d7e1255 227 set otherzset [findKeyWithType {*}$r zset]
b056ca39 228 if {$otherzset ne {}} {
a0573260 229 randpath {
230 {*}$r zunionstore $k2 2 $k $otherzset
231 } {
232 {*}$r zinterstore $k2 2 $k $otherzset
233 }
b056ca39 234 }
235 }
98578b57
PN
236 }
237 {hash} {
a0573260 238 randpath {{*}$r hset $k $f $v} \
239 {{*}$r hdel $k $f}
98578b57
PN
240 }
241 }
242 }
243}
53cbf66c
PN
244
245proc formatCommand {args} {
246 set cmd "*[llength $args]\r\n"
247 foreach a $args {
248 append cmd "$[string length $a]\r\n$a\r\n"
249 }
250 set _ $cmd
251}
dd3f505f 252
253proc csvdump r {
254 set o {}
a0573260 255 foreach k [lsort [{*}$r keys *]] {
256 set type [{*}$r type $k]
dd3f505f 257 append o [csvstring $k] , [csvstring $type] ,
258 switch $type {
259 string {
a0573260 260 append o [csvstring [{*}$r get $k]] "\n"
dd3f505f 261 }
262 list {
a0573260 263 foreach e [{*}$r lrange $k 0 -1] {
dd3f505f 264 append o [csvstring $e] ,
265 }
266 append o "\n"
267 }
268 set {
a0573260 269 foreach e [lsort [{*}$r smembers $k]] {
dd3f505f 270 append o [csvstring $e] ,
271 }
272 append o "\n"
273 }
274 zset {
a0573260 275 foreach e [{*}$r zrange $k 0 -1 withscores] {
dd3f505f 276 append o [csvstring $e] ,
277 }
278 append o "\n"
279 }
280 hash {
a0573260 281 set fields [{*}$r hgetall $k]
dd3f505f 282 set newfields {}
283 foreach {k v} $fields {
284 lappend newfields [list $k $v]
285 }
286 set fields [lsort -index 0 $newfields]
287 foreach kv $fields {
288 append o [csvstring [lindex $kv 0]] ,
289 append o [csvstring [lindex $kv 1]] ,
290 }
291 append o "\n"
292 }
293 }
294 }
295 return $o
296}
297
298proc csvstring s {
299 return "\"$s\""
300}
bf758397 301
302proc roundFloat f {
303 format "%.10g" $f
304}