xref: /redis-3.2.3/tests/support/util.tcl (revision f166bb1d)
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
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
33    set result {}
34    foreach line $lines {
35        if {[regexp {^\[\d+\]\s+\d+\s+\w+\s+\d{2}:\d{2}:\d{2} \#} $line]} {
36            set matched 1
37        }
38        if {$matched} {
39            lappend result $line
40        }
41    }
42    join $result "\n"
43}
44
45# Return value for INFO property
46proc status {r property} {
47    if {[regexp "\r\n$property:(.*?)\r\n" [$r info] _ value]} {
48        set _ $value
49    }
50}
51
52proc waitForBgsave r {
53    while 1 {
54        if {[status r bgsave_in_progress] eq 1} {
55            puts -nonewline "\nWaiting for background save to finish... "
56            flush stdout
57            after 1000
58        } else {
59            break
60        }
61    }
62}
63
64proc waitForBgrewriteaof r {
65    while 1 {
66        if {[status r bgrewriteaof_in_progress] eq 1} {
67            puts -nonewline "\nWaiting for background AOF rewrite to finish... "
68            flush stdout
69            after 1000
70        } else {
71            break
72        }
73    }
74}
75
76proc wait_for_sync r {
77    while 1 {
78        if {[status r master_link_status] eq "down"} {
79            after 10
80        } else {
81            break
82        }
83    }
84}
85
86proc randomInt {max} {
87    expr {int(rand()*$max)}
88}
89
90proc randpath args {
91    set path [expr {int(rand()*[llength $args])}]
92    uplevel 1 [lindex $args $path]
93}
94
95proc randomValue {} {
96    randpath {
97        # Small enough to likely collide
98        randomInt 1000
99    } {
100        # 32 bit compressible signed/unsigned
101        randpath {randomInt 2000000000} {randomInt 4000000000}
102    } {
103        # 64 bit
104        randpath {randomInt 1000000000000}
105    } {
106        # Random string
107        randpath {randstring 0 256 alpha} \
108                {randstring 0 256 compr} \
109                {randstring 0 256 binary}
110    }
111}
112
113proc randomKey {} {
114    randpath {
115        # Small enough to likely collide
116        randomInt 1000
117    } {
118        # 32 bit compressible signed/unsigned
119        randpath {randomInt 2000000000} {randomInt 4000000000}
120    } {
121        # 64 bit
122        randpath {randomInt 1000000000000}
123    } {
124        # Random string
125        randpath {randstring 1 256 alpha} \
126                {randstring 1 256 compr}
127    }
128}
129
130proc createComplexDataset {r ops} {
131    for {set j 0} {$j < $ops} {incr j} {
132        set k [randomKey]
133        set f [randomValue]
134        set v [randomValue]
135        randpath {
136            set d [expr {rand()}]
137        } {
138            set d [expr {rand()}]
139        } {
140            set d [expr {rand()}]
141        } {
142            set d [expr {rand()}]
143        } {
144            set d [expr {rand()}]
145        } {
146            randpath {set d +inf} {set d -inf}
147        }
148        set t [$r type $k]
149
150        if {$t eq {none}} {
151            randpath {
152                $r set $k $v
153            } {
154                $r lpush $k $v
155            } {
156                $r sadd $k $v
157            } {
158                $r zadd $k $d $v
159            } {
160                $r hset $k $f $v
161            }
162            set t [$r type $k]
163        }
164
165        switch $t {
166            {string} {
167                # Nothing to do
168            }
169            {list} {
170                randpath {$r lpush $k $v} \
171                        {$r rpush $k $v} \
172                        {$r lrem $k 0 $v} \
173                        {$r rpop $k} \
174                        {$r lpop $k}
175            }
176            {set} {
177                randpath {$r sadd $k $v} \
178                        {$r srem $k $v}
179            }
180            {zset} {
181                randpath {$r zadd $k $d $v} \
182                        {$r zrem $k $v}
183            }
184            {hash} {
185                randpath {$r hset $k $f $v} \
186                        {$r hdel $k $f}
187            }
188        }
189    }
190}
191
192proc formatCommand {args} {
193    set cmd "*[llength $args]\r\n"
194    foreach a $args {
195        append cmd "$[string length $a]\r\n$a\r\n"
196    }
197    set _ $cmd
198}
199