diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-11-02 15:01:32 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-11-18 11:23:06 -0500 |
commit | 2545eb6198e7e1ec50daa0cfc64a4cdfecf24ec9 (patch) | |
tree | d9850318938da4854afe8f1236f3383d787c6aef /tools | |
parent | f6614b7bb405a9b35dd28baea989a749492c46b2 (diff) |
Initial start of ktest.pl
Originally named autotest.pl, but renamed to ktest.pl now because
the autotest name is used by other projects.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/ktest/ktest.pl | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl new file mode 100644 index 000000000000..81fb2e431058 --- /dev/null +++ b/tools/testing/ktest/ktest.pl | |||
@@ -0,0 +1,334 @@ | |||
1 | #!/usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use IPC::Open2; | ||
5 | use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK); | ||
6 | use FileHandle; | ||
7 | |||
8 | $#ARGV >= 0 || die "usage: autotest.pl config-file\n"; | ||
9 | |||
10 | $| = 1; | ||
11 | |||
12 | my %opt; | ||
13 | |||
14 | #default opts | ||
15 | $opt{"NUM_BUILDS"} = 5; | ||
16 | $opt{"DEFAULT_BUILD_TYPE"} = "randconfig"; | ||
17 | $opt{"MAKE_CMD"} = "make"; | ||
18 | $opt{"TIMEOUT"} = 50; | ||
19 | $opt{"TMP_DIR"} = "/tmp/autotest"; | ||
20 | $opt{"SLEEP_TIME"} = 60; # sleep time between tests | ||
21 | |||
22 | my $version; | ||
23 | my $install_mods; | ||
24 | my $grub_number; | ||
25 | my $target; | ||
26 | my $make; | ||
27 | |||
28 | sub read_config { | ||
29 | my ($config) = @_; | ||
30 | |||
31 | open(IN, $config) || die "can't read file $config"; | ||
32 | |||
33 | while (<IN>) { | ||
34 | |||
35 | # ignore blank lines and comments | ||
36 | next if (/^\s*$/ || /\s*\#/); | ||
37 | |||
38 | if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) { | ||
39 | my $lvalue = $1; | ||
40 | my $rvalue = $2; | ||
41 | |||
42 | $opt{$lvalue} = $rvalue; | ||
43 | } | ||
44 | } | ||
45 | |||
46 | close(IN); | ||
47 | } | ||
48 | |||
49 | sub doprint { | ||
50 | print @_; | ||
51 | |||
52 | if (defined($opt{"LOG_FILE"})) { | ||
53 | open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; | ||
54 | print OUT @_; | ||
55 | close(OUT); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | sub run_command { | ||
60 | my ($command) = @_; | ||
61 | my $redirect = ""; | ||
62 | |||
63 | if (defined($opt{"LOG_FILE"})) { | ||
64 | $redirect = " >> $opt{LOG_FILE} 2>&1"; | ||
65 | } | ||
66 | |||
67 | doprint "$command ... "; | ||
68 | `$command $redirect`; | ||
69 | |||
70 | my $failed = $?; | ||
71 | |||
72 | if ($failed) { | ||
73 | doprint "FAILED!\n"; | ||
74 | } else { | ||
75 | doprint "SUCCESS\n"; | ||
76 | } | ||
77 | |||
78 | return $failed; | ||
79 | } | ||
80 | |||
81 | my $timeout = $opt{"TIMEOUT"}; | ||
82 | |||
83 | sub wait_for_input | ||
84 | { | ||
85 | my ($fp, $time) = @_; | ||
86 | my $rin; | ||
87 | my $ready; | ||
88 | my $line; | ||
89 | my $ch; | ||
90 | |||
91 | if (!defined($time)) { | ||
92 | $time = $timeout; | ||
93 | } | ||
94 | |||
95 | $rin = ''; | ||
96 | vec($rin, fileno($fp), 1) = 1; | ||
97 | $ready = select($rin, undef, undef, $time); | ||
98 | |||
99 | $line = ""; | ||
100 | |||
101 | # try to read one char at a time | ||
102 | while (sysread $fp, $ch, 1) { | ||
103 | $line .= $ch; | ||
104 | last if ($ch eq "\n"); | ||
105 | } | ||
106 | |||
107 | if (!length($line)) { | ||
108 | return undef; | ||
109 | } | ||
110 | |||
111 | return $line; | ||
112 | } | ||
113 | |||
114 | sub reboot { | ||
115 | run_command "ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'"; | ||
116 | } | ||
117 | |||
118 | sub monitor { | ||
119 | my $flags; | ||
120 | my $booted = 0; | ||
121 | my $bug = 0; | ||
122 | my $pid; | ||
123 | my $doopen2 = 0; | ||
124 | |||
125 | if ($doopen2) { | ||
126 | $pid = open2(\*IN, \*OUT, $opt{CONSOLE}); | ||
127 | if ($pid < 0) { | ||
128 | die "Failed to connect to the console"; | ||
129 | } | ||
130 | } else { | ||
131 | $pid = open(IN, "$opt{CONSOLE} |"); | ||
132 | } | ||
133 | |||
134 | $flags = fcntl(IN, F_GETFL, 0) or | ||
135 | die "Can't get flags for the socket: $!\n"; | ||
136 | |||
137 | $flags = fcntl(IN, F_SETFL, $flags | O_NONBLOCK) or | ||
138 | die "Can't set flags for the socket: $!\n"; | ||
139 | |||
140 | my $line; | ||
141 | my $full_line = ""; | ||
142 | |||
143 | doprint "Wait for monitor to settle down.\n"; | ||
144 | # read the monitor and wait for the system to calm down | ||
145 | do { | ||
146 | $line = wait_for_input(\*IN, 5); | ||
147 | } while (defined($line)); | ||
148 | |||
149 | reboot; | ||
150 | |||
151 | for (;;) { | ||
152 | |||
153 | $line = wait_for_input(\*IN); | ||
154 | |||
155 | last if (!defined($line)); | ||
156 | |||
157 | doprint $line; | ||
158 | |||
159 | # we are not guaranteed to get a full line | ||
160 | $full_line .= $line; | ||
161 | |||
162 | if ($full_line =~ /login:/) { | ||
163 | $booted = 1; | ||
164 | } | ||
165 | |||
166 | if ($full_line =~ /call trace:/i) { | ||
167 | $bug = 1; | ||
168 | } | ||
169 | |||
170 | if ($line =~ /\n/) { | ||
171 | $full_line = ""; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | doprint "kill child process $pid\n"; | ||
176 | kill 2, $pid; | ||
177 | |||
178 | print "closing!\n"; | ||
179 | close(IN); | ||
180 | |||
181 | if (!$booted) { | ||
182 | die "failed - never got a boot prompt.\n"; | ||
183 | } | ||
184 | |||
185 | if ($bug) { | ||
186 | die "failed - got a bug report\n"; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | sub install { | ||
191 | |||
192 | if (run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}") { | ||
193 | die "failed to copy image"; | ||
194 | } | ||
195 | |||
196 | if ($install_mods) { | ||
197 | my $modlib = "/lib/modules/$version"; | ||
198 | |||
199 | if (run_command "ssh $target rm -rf $modlib") { | ||
200 | die "failed to remove old mods: $modlib"; | ||
201 | } | ||
202 | |||
203 | if (run_command "scp -r $opt{TMP_DIR}/lib $target:/lib/modules/$version") { | ||
204 | die "failed to copy modules"; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | } | ||
209 | |||
210 | sub build { | ||
211 | my ($type) = @_; | ||
212 | |||
213 | unlink "$opt{OUTPUT_DIR}/.config"; | ||
214 | |||
215 | run_command "$make mrproper"; | ||
216 | |||
217 | # add something to distinguish this build | ||
218 | open(OUT, "> $opt{OUTPUT_DIR}/localversion") or die("Can't make localversion file"); | ||
219 | print OUT "$opt{LOCALVERSION}\n"; | ||
220 | close(OUT); | ||
221 | |||
222 | if (run_command "$make $opt{$type}") { | ||
223 | die "failed make config"; | ||
224 | } | ||
225 | |||
226 | if (defined($opt{"MIN_CONFIG"})) { | ||
227 | run_command "cat $opt{MIN_CONFIG} >> $opt{OUTPUT_DIR}/.config"; | ||
228 | run_command "yes '' | $make oldconfig"; | ||
229 | } | ||
230 | |||
231 | if (run_command "$make $opt{BUILD_OPTIONS}") { | ||
232 | die "failed build"; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | read_config $ARGV[0]; | ||
237 | |||
238 | # mandatory configs | ||
239 | die "MACHINE not defined\n" if (!defined($opt{"MACHINE"})); | ||
240 | die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"})); | ||
241 | die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"})); | ||
242 | die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"})); | ||
243 | die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"})); | ||
244 | die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"})); | ||
245 | die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"})); | ||
246 | die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"})); | ||
247 | die "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"})); | ||
248 | |||
249 | chdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}"; | ||
250 | |||
251 | $target = "$opt{SSH_USER}\@$opt{MACHINE}"; | ||
252 | |||
253 | doprint "\n\nSTARTING AUTOMATED TESTS\n"; | ||
254 | |||
255 | doprint "Find grub menu ... "; | ||
256 | $grub_number = -1; | ||
257 | open(IN, "ssh $target cat /boot/grub/menu.lst |") | ||
258 | or die "unable to get menu.lst"; | ||
259 | while (<IN>) { | ||
260 | if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) { | ||
261 | $grub_number++; | ||
262 | last; | ||
263 | } elsif (/^\s*title\s/) { | ||
264 | $grub_number++; | ||
265 | } | ||
266 | } | ||
267 | close(IN); | ||
268 | die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}" | ||
269 | if ($grub_number < 0); | ||
270 | doprint "$grub_number\n"; | ||
271 | |||
272 | $make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}"; | ||
273 | |||
274 | # First we need to do is the builds | ||
275 | for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) { | ||
276 | my $type = "BUILD_TYPE[$i]"; | ||
277 | |||
278 | if (!defined($opt{$type})) { | ||
279 | $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"}; | ||
280 | } | ||
281 | |||
282 | doprint "\n\n"; | ||
283 | doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n"; | ||
284 | |||
285 | if ($opt{$type} ne "nobuild") { | ||
286 | build $type; | ||
287 | } | ||
288 | |||
289 | # get the release name | ||
290 | doprint "$make kernelrelease ... "; | ||
291 | $version = `$make kernelrelease | tail -1`; | ||
292 | chomp($version); | ||
293 | doprint "$version\n"; | ||
294 | |||
295 | # should we process modules? | ||
296 | $install_mods = 0; | ||
297 | open(IN, "$opt{OUTPUT_DIR}/.config") or die("Can't read config file"); | ||
298 | while (<IN>) { | ||
299 | if (/CONFIG_MODULES(=y)?/) { | ||
300 | $install_mods = 1 if (defined($1)); | ||
301 | last; | ||
302 | } | ||
303 | } | ||
304 | close(IN); | ||
305 | |||
306 | if ($install_mods) { | ||
307 | if (run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install") { | ||
308 | die "Failed to install modules"; | ||
309 | } | ||
310 | } else { | ||
311 | doprint "No modules needed\n"; | ||
312 | } | ||
313 | |||
314 | install; | ||
315 | |||
316 | monitor; | ||
317 | |||
318 | doprint "\n\n*******************************************\n"; | ||
319 | doprint "*******************************************\n"; | ||
320 | doprint "** SUCCESS!!!! **\n"; | ||
321 | doprint "*******************************************\n"; | ||
322 | doprint "*******************************************\n"; | ||
323 | |||
324 | # try to reboot normally | ||
325 | |||
326 | if (run_command "ssh $target reboot") { | ||
327 | # nope? power cycle it. | ||
328 | run_command "$opt{POWER_CYCLE}"; | ||
329 | } | ||
330 | |||
331 | sleep "$opt{SLEEP_TIME}"; | ||
332 | } | ||
333 | |||
334 | exit 0; | ||