5 use Fcntl
qw(F_GETFL F_SETFL O_NONBLOCK);
8 $#ARGV >= 0 || die "usage: autotest.pl config-file\n";
15 $opt{"NUM_BUILDS"} = 5;
16 $opt{"DEFAULT_BUILD_TYPE"} = "randconfig";
17 $opt{"MAKE_CMD"} = "make";
19 $opt{"TMP_DIR"} = "/tmp/autotest";
20 $opt{"SLEEP_TIME"} = 60; # sleep time between tests
21 $opt{"BUILD_NOCLEAN"} = 0;
22 $opt{"POWEROFF_ON_ERROR"} = 0;
23 $opt{"POWEROFF_ON_SUCCESS"} = 0;
35 open(IN
, $config) || die "can't read file $config";
39 # ignore blank lines and comments
40 next if (/^\s*$/ || /\s*\#/);
42 if (/^\s*(\S+)\s*=\s*(.*?)\s*$/) {
46 $opt{$lvalue} = $rvalue;
56 if (defined($opt{"LOG_FILE"})) {
57 open(OUT
, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
64 doprint
"CRITICAL FAILURE... ", @_;
66 if ($opt{"POWEROFF_ON_ERROR"} && defined($opt{"POWER_OFF"})) {
67 doprint
"POWERING OFF\n";
77 if (defined($opt{"LOG_FILE"})) {
78 $redirect = " >> $opt{LOG_FILE} 2>&1";
81 doprint
"$command ... ";
95 my $timeout = $opt{"TIMEOUT"};
105 if (!defined($time)) {
110 vec($rin, fileno($fp), 1) = 1;
111 $ready = select($rin, undef, undef, $time);
115 # try to read one char at a time
116 while (sysread $fp, $ch, 1) {
118 last if ($ch eq "\n");
121 if (!length($line)) {
129 run_command
"ssh $target '(echo \"savedefault --default=$grub_number --once\" | grub --batch; reboot)'";
138 my $skip_call_trace = 0;
141 $pid = open2
(\
*IN
, \
*OUT
, $opt{CONSOLE
});
143 dodie
"Failed to connect to the console";
146 $pid = open(IN
, "$opt{CONSOLE} |");
149 $flags = fcntl(IN
, F_GETFL
, 0) or
150 dodie
"Can't get flags for the socket: $!\n";
152 $flags = fcntl(IN
, F_SETFL
, $flags | O_NONBLOCK
) or
153 dodie
"Can't set flags for the socket: $!\n";
158 doprint
"Wait for monitor to settle down.\n";
159 # read the monitor and wait for the system to calm down
161 $line = wait_for_input
(\
*IN
, 5);
162 } while (defined($line));
168 $line = wait_for_input
(\
*IN
);
170 last if (!defined($line));
174 # we are not guaranteed to get a full line
177 if ($full_line =~ /login:/) {
181 if ($full_line =~ /\[ backtrace testing \]/) {
182 $skip_call_trace = 1;
185 if ($full_line =~ /call trace:/i) {
186 $bug = 1 if (!$skip_call_trace);
189 if ($full_line =~ /\[ end of backtrace testing \]/) {
190 $skip_call_trace = 0;
193 if ($full_line =~ /Kernel panic -/) {
202 doprint
"kill child process $pid\n";
209 dodie
"failed - never got a boot prompt.\n";
213 dodie
"failed - got a bug report\n";
219 if (run_command
"scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}") {
220 dodie
"failed to copy image";
224 my $modlib = "/lib/modules/$version";
225 my $modtar = "autotest-mods.tar.bz2";
227 if (run_command
"ssh $target rm -rf $modlib") {
228 dodie
"failed to remove old mods: $modlib";
231 # would be nice if scp -r did not follow symbolic links
232 if (run_command
"cd $opt{TMP_DIR}; tar -cjf $modtar lib/modules/$version") {
233 dodie
"making tarball";
236 if (run_command
"scp $opt{TMP_DIR}/$modtar $target:/tmp") {
237 dodie
"failed to copy modules";
240 unlink "$opt{TMP_DIR}/$modtar";
242 if (run_command
"ssh $target '(cd / && tar xf /tmp/$modtar)'") {
243 dodie
"failed to tar modules";
246 run_command
"ssh $target rm -f /tmp/$modtar";
256 # old config can ask questions
257 if ($type eq "oldconfig") {
259 if (run_command
"mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp") {
260 dodie
"moving .config";
263 if (!$noclean && run_command
"$make mrproper") {
264 dodie
"make mrproper";
267 if (run_command
"mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config") {
268 dodie
"moving config_temp";
271 } elsif (!$noclean) {
272 unlink "$opt{OUTPUT_DIR}/.config";
273 if (run_command
"$make mrproper") {
274 dodie
"make mrproper";
278 # add something to distinguish this build
279 open(OUT
, "> $opt{OUTPUT_DIR}/localversion") or dodie
("Can't make localversion file");
280 print OUT
"$opt{LOCALVERSION}\n";
283 if (defined($opt{"MIN_CONFIG"})) {
284 $defconfig = "KCONFIG_ALLCONFIG=$opt{MIN_CONFIG}";
287 if (run_command
"$defconfig $append $make $type") {
288 dodie
"failed make config";
291 if (run_command
"$make $opt{BUILD_OPTIONS}") {
292 dodie
"failed build";
296 read_config
$ARGV[0];
299 die "MACHINE not defined\n" if (!defined($opt{"MACHINE"}));
300 die "SSH_USER not defined\n" if (!defined($opt{"SSH_USER"}));
301 die "BUILD_DIR not defined\n" if (!defined($opt{"BUILD_DIR"}));
302 die "OUTPUT_DIR not defined\n" if (!defined($opt{"OUTPUT_DIR"}));
303 die "BUILD_TARGET not defined\n" if (!defined($opt{"BUILD_TARGET"}));
304 die "POWER_CYCLE not defined\n" if (!defined($opt{"POWER_CYCLE"}));
305 die "CONSOLE not defined\n" if (!defined($opt{"CONSOLE"}));
306 die "LOCALVERSION not defined\n" if (!defined($opt{"LOCALVERSION"}));
307 die "GRUB_MENU not defined\n" if (!defined($opt{"GRUB_MENU"}));
309 chdir $opt{"BUILD_DIR"} || die "can't change directory to $opt{BUILD_DIR}";
311 $target = "$opt{SSH_USER}\@$opt{MACHINE}";
313 doprint
"\n\nSTARTING AUTOMATED TESTS\n";
315 doprint
"Find grub menu ... ";
317 open(IN
, "ssh $target cat /boot/grub/menu.lst |")
318 or die "unable to get menu.lst";
320 if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
323 } elsif (/^\s*title\s/) {
328 die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
329 if ($grub_number < 0);
330 doprint
"$grub_number\n";
332 $make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
334 # First we need to do is the builds
335 for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
336 my $type = "BUILD_TYPE[$i]";
338 if (defined($opt{"BUILD_NOCLEAN[$i]"}) &&
339 $opt{"BUILD_NOCLEAN[$i]"} != 0) {
342 $noclean = $opt{"BUILD_NOCLEAN"};
345 if (!defined($opt{$type})) {
346 $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"};
350 doprint
"RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
352 if ($opt{$type} ne "nobuild") {
356 # get the release name
357 doprint
"$make kernelrelease ... ";
358 $version = `$make kernelrelease | tail -1`;
360 doprint
"$version\n";
362 # should we process modules?
364 open(IN
, "$opt{OUTPUT_DIR}/.config") or dodie
("Can't read config file");
366 if (/CONFIG_MODULES(=y)?/) {
367 $install_mods = 1 if (defined($1));
374 if (run_command
"$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install") {
375 dodie
"Failed to install modules";
378 doprint
"No modules needed\n";
385 doprint
"\n\n*******************************************\n";
386 doprint
"*******************************************\n";
387 doprint
"** SUCCESS!!!! **\n";
388 doprint
"*******************************************\n";
389 doprint
"*******************************************\n";
391 # try to reboot normally
393 if (run_command
"ssh $target reboot") {
394 # nope? power cycle it.
395 run_command
"$opt{POWER_CYCLE}";
398 sleep "$opt{SLEEP_TIME}";
401 if ($opt{"POWEROFF_ON_SUCCESS"}) {
402 if (run_command
"ssh $target halt" && defined($opt{"POWER_OFF"})) {
404 run_command
"$opt{POWER_OFF}";