aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/ktest/ktest.pl
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/ktest/ktest.pl')
-rw-r--r--tools/testing/ktest/ktest.pl321
1 files changed, 227 insertions, 94 deletions
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index 79da57f3023b..a34f6f4193df 100644
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -25,11 +25,13 @@ $opt{"POWEROFF_ON_SUCCESS"} = 0;
25$opt{"BUILD_OPTIONS"} = ""; 25$opt{"BUILD_OPTIONS"} = "";
26 26
27my $version; 27my $version;
28my $install_mods;
29my $grub_number; 28my $grub_number;
30my $target; 29my $target;
31my $make; 30my $make;
32my $noclean; 31my $noclean;
32my $minconfig;
33my $in_bisect = 0;
34my $bisect_bad = "";
33 35
34sub read_config { 36sub read_config {
35 my ($config) = @_; 37 my ($config) = @_;
@@ -52,9 +54,7 @@ sub read_config {
52 close(IN); 54 close(IN);
53} 55}
54 56
55sub doprint { 57sub logit {
56 print @_;
57
58 if (defined($opt{"LOG_FILE"})) { 58 if (defined($opt{"LOG_FILE"})) {
59 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}"; 59 open(OUT, ">> $opt{LOG_FILE}") or die "Can't write to $opt{LOG_FILE}";
60 print OUT @_; 60 print OUT @_;
@@ -62,6 +62,11 @@ sub doprint {
62 } 62 }
63} 63}
64 64
65sub doprint {
66 print @_;
67 logit @_;
68}
69
65sub dodie { 70sub dodie {
66 doprint "CRITICAL FAILURE... ", @_; 71 doprint "CRITICAL FAILURE... ", @_;
67 72
@@ -96,7 +101,30 @@ sub run_command {
96 doprint "SUCCESS\n"; 101 doprint "SUCCESS\n";
97 } 102 }
98 103
99 return $failed; 104 return !$failed;
105}
106
107sub get_grub_index {
108
109 return if ($grub_number >= 0);
110
111 doprint "Find grub menu ... ";
112 $grub_number = -1;
113 open(IN, "ssh $target cat /boot/grub/menu.lst |")
114 or die "unable to get menu.lst";
115 while (<IN>) {
116 if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
117 $grub_number++;
118 last;
119 } elsif (/^\s*title\s/) {
120 $grub_number++;
121 }
122 }
123 close(IN);
124
125 die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
126 if ($grub_number < 0);
127 doprint "$grub_number\n";
100} 128}
101 129
102my $timeout = $opt{"TIMEOUT"}; 130my $timeout = $opt{"TIMEOUT"};
@@ -213,46 +241,63 @@ sub monitor {
213 close(IN); 241 close(IN);
214 242
215 if (!$booted) { 243 if (!$booted) {
244 return 1 if (!$in_bisect);
216 dodie "failed - never got a boot prompt.\n"; 245 dodie "failed - never got a boot prompt.\n";
217 } 246 }
218 247
219 if ($bug) { 248 if ($bug) {
249 return 1 if (!$in_bisect);
220 dodie "failed - got a bug report\n"; 250 dodie "failed - got a bug report\n";
221 } 251 }
252
253 return 0;
222} 254}
223 255
224sub install { 256sub install {
225 257
226 if (run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}") { 258 run_command "scp $opt{OUTPUT_DIR}/$opt{BUILD_TARGET} $target:$opt{TARGET_IMAGE}" or
227 dodie "failed to copy image"; 259 dodie "failed to copy image";
228 }
229 260
230 if ($install_mods) { 261 my $install_mods = 0;
231 my $modlib = "/lib/modules/$version";
232 my $modtar = "autotest-mods.tar.bz2";
233 262
234 if (run_command "ssh $target rm -rf $modlib") { 263 # should we process modules?
235 dodie "failed to remove old mods: $modlib"; 264 $install_mods = 0;
265 open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file");
266 while (<IN>) {
267 if (/CONFIG_MODULES(=y)?/) {
268 $install_mods = 1 if (defined($1));
269 last;
236 } 270 }
271 }
272 close(IN);
237 273
238 # would be nice if scp -r did not follow symbolic links 274 if (!$install_mods) {
239 if (run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version") { 275 doprint "No modules needed\n";
240 dodie "making tarball"; 276 return;
241 } 277 }
242 278
243 if (run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp") { 279 run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install" or
244 dodie "failed to copy modules"; 280 dodie "Failed to install modules";
245 }
246 281
247 unlink "$opt{TMP_DIR}/$modtar"; 282 my $modlib = "/lib/modules/$version";
283 my $modtar = "autotest-mods.tar.bz2";
248 284
249 if (run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'") { 285 run_command "ssh $target rm -rf $modlib" or
250 dodie "failed to tar modules"; 286 dodie "failed to remove old mods: $modlib";
251 }
252 287
253 run_command "ssh $target rm -f /tmp/$modtar"; 288 # would be nice if scp -r did not follow symbolic links
254 } 289 run_command "cd $opt{TMP_DIR} && tar -cjf $modtar lib/modules/$version" or
290 dodie "making tarball";
291
292 run_command "scp $opt{TMP_DIR}/$modtar $target:/tmp" or
293 dodie "failed to copy modules";
294
295 unlink "$opt{TMP_DIR}/$modtar";
296
297 run_command "ssh $target '(cd / && tar xf /tmp/$modtar)'" or
298 dodie "failed to tar modules";
255 299
300 run_command "ssh $target rm -f /tmp/$modtar";
256} 301}
257 302
258sub build { 303sub build {
@@ -261,9 +306,9 @@ sub build {
261 my $append = ""; 306 my $append = "";
262 307
263 if ($type =~ /^useconfig:(.*)/) { 308 if ($type =~ /^useconfig:(.*)/) {
264 if (run_command "cp $1 $opt{OUTPUT_DIR}/.config") { 309 run_command "cp $1 $opt{OUTPUT_DIR}/.config" or
265 dodie "could not copy $1 to .config"; 310 dodie "could not copy $1 to .config";
266 } 311
267 $type = "oldconfig"; 312 $type = "oldconfig";
268 } 313 }
269 314
@@ -274,23 +319,20 @@ sub build {
274 # allow for empty configs 319 # allow for empty configs
275 run_command "touch $opt{OUTPUT_DIR}/.config"; 320 run_command "touch $opt{OUTPUT_DIR}/.config";
276 321
277 if (run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp") { 322 run_command "mv $opt{OUTPUT_DIR}/.config $opt{OUTPUT_DIR}/config_temp" or
278 dodie "moving .config"; 323 dodie "moving .config";
279 }
280 324
281 if (!$noclean && run_command "$make mrproper") { 325 if (!$noclean && !run_command "$make mrproper") {
282 dodie "make mrproper"; 326 dodie "make mrproper";
283 } 327 }
284 328
285 if (run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config") { 329 run_command "mv $opt{OUTPUT_DIR}/config_temp $opt{OUTPUT_DIR}/.config" or
286 dodie "moving config_temp"; 330 dodie "moving config_temp";
287 }
288 331
289 } elsif (!$noclean) { 332 } elsif (!$noclean) {
290 unlink "$opt{OUTPUT_DIR}/.config"; 333 unlink "$opt{OUTPUT_DIR}/.config";
291 if (run_command "$make mrproper") { 334 run_command "$make mrproper" or
292 dodie "make mrproper"; 335 dodie "make mrproper";
293 }
294 } 336 }
295 337
296 # add something to distinguish this build 338 # add something to distinguish this build
@@ -298,34 +340,162 @@ sub build {
298 print OUT "$opt{LOCALVERSION}\n"; 340 print OUT "$opt{LOCALVERSION}\n";
299 close(OUT); 341 close(OUT);
300 342
301 if (defined($opt{"MIN_CONFIG"})) { 343 if (defined($minconfig)) {
302 $defconfig = "KCONFIG_ALLCONFIG=$opt{MIN_CONFIG}"; 344 $defconfig = "KCONFIG_ALLCONFIG=$minconfig";
303 } 345 }
304 346
305 if (run_command "$defconfig $append $make $type") { 347 run_command "$defconfig $append $make $type" or
306 dodie "failed make config"; 348 dodie "failed make config";
307 }
308 349
309 if (run_command "$make $opt{BUILD_OPTIONS}") { 350 if (!run_command "$make $opt{BUILD_OPTIONS}") {
351 # bisect may need this to pass
352 return 1 if ($in_bisect);
310 dodie "failed build"; 353 dodie "failed build";
311 } 354 }
355
356 return 0;
312} 357}
313 358
314sub reboot { 359sub reboot {
315 # try to reboot normally 360 # try to reboot normally
316 if (run_command "ssh $target reboot") { 361 if (!run_command "ssh $target reboot") {
317 # nope? power cycle it. 362 # nope? power cycle it.
318 run_command "$opt{POWER_CYCLE}"; 363 run_command "$opt{POWER_CYCLE}";
319 } 364 }
320} 365}
321 366
322sub halt { 367sub halt {
323 if ((run_command "ssh $target halt") or defined($opt{"POWER_OFF"})) { 368 if (!run_command "ssh $target halt" or defined($opt{"POWER_OFF"})) {
324 # nope? the zap it! 369 # nope? the zap it!
325 run_command "$opt{POWER_OFF}"; 370 run_command "$opt{POWER_OFF}";
326 } 371 }
327} 372}
328 373
374sub success {
375 my ($i) = @_;
376
377 doprint "\n\n*******************************************\n";
378 doprint "*******************************************\n";
379 doprint "** SUCCESS!!!! **\n";
380 doprint "*******************************************\n";
381 doprint "*******************************************\n";
382
383 if ($i != $opt{"NUM_BUILDS"}) {
384 reboot;
385 doprint "Sleeping $opt{SLEEP_TIME} seconds\n";
386 sleep "$opt{SLEEP_TIME}";
387 }
388}
389
390sub get_version {
391 # get the release name
392 doprint "$make kernelrelease ... ";
393 $version = `$make kernelrelease | tail -1`;
394 chomp($version);
395 doprint "$version\n";
396}
397
398sub run_bisect {
399 my ($type) = @_;
400
401 my $failed;
402 my $result;
403 my $output;
404 my $ret;
405
406
407 if (defined($minconfig)) {
408 $failed = build "useconfig:$minconfig";
409 } else {
410 # ?? no config to use?
411 $failed = build "oldconfig";
412 }
413
414 if ($type ne "build") {
415 dodie "Failed on build" if $failed;
416
417 # Now boot the box
418 get_grub_index;
419 get_version;
420 install;
421 $failed = monitor;
422
423 if ($type ne "boot") {
424 dodie "Failed on boot" if $failed;
425 }
426 }
427
428 if ($failed) {
429 $result = "bad";
430 } else {
431 $result = "good";
432 }
433
434 doprint "git bisect $result ... ";
435 $output = `git bisect $result 2>&1`;
436 $ret = $?;
437
438 logit $output;
439
440 if ($ret) {
441 doprint "FAILED\n";
442 dodie "Failed to git bisect";
443 }
444
445 doprint "SUCCESS\n";
446 if ($output =~ m/^(Bisecting: .*\(roughly \d+ steps?\)) \[([[:xdigit:]]+)\]/) {
447 doprint "$1 [$2]\n";
448 } elsif ($output =~ m/^([[:xdigit:]]+) is the first bad commit/) {
449 $bisect_bad = $1;
450 doprint "Found bad commit... $1\n";
451 return 0;
452 }
453
454
455 return 1;
456}
457
458sub bisect {
459 my ($i) = @_;
460
461 my $result;
462
463 die "BISECT_GOOD[$i] not defined\n" if (!defined($opt{"BISECT_GOOD[$i]"}));
464 die "BISECT_BAD[$i] not defined\n" if (!defined($opt{"BISECT_BAD[$i]"}));
465 die "BISECT_TYPE[$i] not defined\n" if (!defined($opt{"BISECT_TYPE[$i]"}));
466
467 my $good = $opt{"BISECT_GOOD[$i]"};
468 my $bad = $opt{"BISECT_BAD[$i]"};
469 my $type = $opt{"BISECT_TYPE[$i]"};
470
471 $in_bisect = 1;
472
473 run_command "git bisect start" or
474 dodie "could not start bisect";
475
476 run_command "git bisect good $good" or
477 dodie "could not set bisect good to $good";
478
479 run_command "git bisect bad $bad" or
480 dodie "could not set bisect good to $bad";
481
482 do {
483 $result = run_bisect $type;
484 } while ($result);
485
486 run_command "git bisect log" or
487 dodie "could not capture git bisect log";
488
489 run_command "git bisect reset" or
490 dodie "could not reset git bisect";
491
492 doprint "Bad commit was [$bisect_bad]\n";
493
494 $in_bisect = 0;
495
496 success $i;
497}
498
329read_config $ARGV[0]; 499read_config $ARGV[0];
330 500
331# mandatory configs 501# mandatory configs
@@ -346,22 +516,6 @@ $target = "$opt{SSH_USER}\@$opt{MACHINE}";
346 516
347doprint "\n\nSTARTING AUTOMATED TESTS\n"; 517doprint "\n\nSTARTING AUTOMATED TESTS\n";
348 518
349doprint "Find grub menu ... ";
350$grub_number = -1;
351open(IN, "ssh $target cat /boot/grub/menu.lst |")
352 or die "unable to get menu.lst";
353while (<IN>) {
354 if (/^\s*title\s+$opt{GRUB_MENU}\s*$/) {
355 $grub_number++;
356 last;
357 } elsif (/^\s*title\s/) {
358 $grub_number++;
359 }
360}
361close(IN);
362die "Could not find '$opt{GRUB_MENU}' in /boot/grub/menu on $opt{MACHINE}"
363 if ($grub_number < 0);
364doprint "$grub_number\n";
365 519
366$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}"; 520$make = "$opt{MAKE_CMD} O=$opt{OUTPUT_DIR}";
367 521
@@ -376,6 +530,14 @@ for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
376 $noclean = $opt{"BUILD_NOCLEAN"}; 530 $noclean = $opt{"BUILD_NOCLEAN"};
377 } 531 }
378 532
533 if (defined($opt{"MIN_CONFIG[$i]"})) {
534 $minconfig = $opt{"MIN_CONFIG[$i]"};
535 } elsif (defined($opt{"MIN_CONFIG"})) {
536 $minconfig = $opt{"MIN_CONFIG"};
537 } else {
538 undef $minconfig;
539 }
540
379 if (!defined($opt{$type})) { 541 if (!defined($opt{$type})) {
380 $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"}; 542 $opt{$type} = $opt{"DEFAULT_BUILD_TYPE"};
381 } 543 }
@@ -383,49 +545,20 @@ for (my $i = 1; $i <= $opt{"NUM_BUILDS"}; $i++) {
383 doprint "\n\n"; 545 doprint "\n\n";
384 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n"; 546 doprint "RUNNING TEST $i of $opt{NUM_BUILDS} with option $opt{$type}\n\n";
385 547
386 if ($opt{$type} ne "nobuild") { 548 if ($opt{$type} eq "bisect") {
387 build $opt{$type}; 549 bisect $i;
388 } 550 next;
389
390 # get the release name
391 doprint "$make kernelrelease ... ";
392 $version = `$make kernelrelease | tail -1`;
393 chomp($version);
394 doprint "$version\n";
395
396 # should we process modules?
397 $install_mods = 0;
398 open(IN, "$opt{OUTPUT_DIR}/.config") or dodie("Can't read config file");
399 while (<IN>) {
400 if (/CONFIG_MODULES(=y)?/) {
401 $install_mods = 1 if (defined($1));
402 last;
403 }
404 } 551 }
405 close(IN);
406 552
407 if ($install_mods) { 553 if ($opt{$type} ne "nobuild") {
408 if (run_command "$make INSTALL_MOD_PATH=$opt{TMP_DIR} modules_install") { 554 build $opt{$type};
409 dodie "Failed to install modules";
410 }
411 } else {
412 doprint "No modules needed\n";
413 } 555 }
414 556
557 get_grub_index;
558 get_version;
415 install; 559 install;
416
417 monitor; 560 monitor;
418 561 success $i;
419 doprint "\n\n*******************************************\n";
420 doprint "*******************************************\n";
421 doprint "** SUCCESS!!!! **\n";
422 doprint "*******************************************\n";
423 doprint "*******************************************\n";
424
425 if ($i != $opt{"NUM_BUILDS"}) {
426 reboot;
427 sleep "$opt{SLEEP_TIME}";
428 }
429} 562}
430 563
431if ($opt{"POWEROFF_ON_SUCCESS"}) { 564if ($opt{"POWEROFF_ON_SUCCESS"}) {