439 pass |
440 pass |
440 |
441 |
441 def alarmed(signum, frame): |
442 def alarmed(signum, frame): |
442 raise Timeout |
443 raise Timeout |
443 |
444 |
|
445 def pytest(test, options): |
|
446 py3kswitch = options.py3k_warnings and ' -3' or '' |
|
447 cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test) |
|
448 vlog("# Running", cmd) |
|
449 return run(cmd, options) |
|
450 |
|
451 def shtest(test, options): |
|
452 cmd = '"%s"' % test |
|
453 vlog("# Running", cmd) |
|
454 return run(cmd, options) |
|
455 |
|
456 def battest(test, options): |
|
457 # To reliably get the error code from batch files on WinXP, |
|
458 # the "cmd /c call" prefix is needed. Grrr |
|
459 cmd = 'cmd /c call "%s"' % testpath |
|
460 vlog("# Running", cmd) |
|
461 return run(cmd, options) |
|
462 |
|
463 def tsttest(test, options): |
|
464 t = open(test) |
|
465 out = [] |
|
466 script = [] |
|
467 salt = "SALT" + str(time.time()) |
|
468 |
|
469 pos = prepos = -1 |
|
470 after = {} |
|
471 expected = {} |
|
472 for n, l in enumerate(t): |
|
473 if l.startswith(' $ '): # commands |
|
474 after.setdefault(pos, []).append(l) |
|
475 prepos = pos |
|
476 pos = n |
|
477 script.append('echo %s %s\n' % (salt, n)) |
|
478 script.append(l[4:]) |
|
479 elif l.startswith(' > '): # continuations |
|
480 after.setdefault(prepos, []).append(l) |
|
481 script.append(l[4:]) |
|
482 elif l.startswith(' '): # results |
|
483 # queue up a list of expected results |
|
484 expected.setdefault(pos, []).append(l[2:]) |
|
485 else: |
|
486 # non-command/result - queue up for merged output |
|
487 after.setdefault(pos, []).append(l) |
|
488 |
|
489 fd, name = tempfile.mkstemp(suffix='hg-tst') |
|
490 |
|
491 try: |
|
492 for l in script: |
|
493 os.write(fd, l) |
|
494 os.close(fd) |
|
495 |
|
496 cmd = '/bin/sh "%s"' % name |
|
497 vlog("# Running", cmd) |
|
498 exitcode, output = run(cmd, options) |
|
499 finally: |
|
500 os.remove(name) |
|
501 |
|
502 def rematch(el, l): |
|
503 try: |
|
504 return re.match(el, l) |
|
505 except re.error: |
|
506 # el is an invalid regex |
|
507 return False |
|
508 |
|
509 pos = -1 |
|
510 postout = [] |
|
511 for n, l in enumerate(output): |
|
512 if l.startswith(salt): |
|
513 if pos in after: |
|
514 postout += after.pop(pos) |
|
515 pos = int(l.split()[1]) |
|
516 else: |
|
517 el = None |
|
518 if pos in expected and expected[pos]: |
|
519 el = expected[pos].pop(0) |
|
520 |
|
521 if el == l: # perfect match (fast) |
|
522 postout.append(" " + l) |
|
523 elif el and rematch(el, l): # fallback regex match |
|
524 postout.append(" " + el) |
|
525 else: # mismatch - let diff deal with it |
|
526 postout.append(" " + l) |
|
527 |
|
528 if pos in after: |
|
529 postout += after.pop(pos) |
|
530 |
|
531 return exitcode, postout |
|
532 |
444 def run(cmd, options): |
533 def run(cmd, options): |
445 """Run command in a sub-process, capturing the output (stdout and stderr). |
534 """Run command in a sub-process, capturing the output (stdout and stderr). |
446 Return a tuple (exitcode, output). output is None in debug mode.""" |
535 Return a tuple (exitcode, output). output is None in debug mode.""" |
447 # TODO: Use subprocess.Popen if we're running on Python 2.4 |
536 # TODO: Use subprocess.Popen if we're running on Python 2.4 |
448 if options.debug: |
537 if options.debug: |
535 except: |
624 except: |
536 firstline = '' |
625 firstline = '' |
537 lctest = test.lower() |
626 lctest = test.lower() |
538 |
627 |
539 if lctest.endswith('.py') or firstline == '#!/usr/bin/env python': |
628 if lctest.endswith('.py') or firstline == '#!/usr/bin/env python': |
540 py3kswitch = options.py3k_warnings and ' -3' or '' |
629 runner = pytest |
541 cmd = '%s%s "%s"' % (PYTHON, py3kswitch, testpath) |
|
542 elif lctest.endswith('.bat'): |
630 elif lctest.endswith('.bat'): |
543 # do not run batch scripts on non-windows |
631 # do not run batch scripts on non-windows |
544 if os.name != 'nt': |
632 if os.name != 'nt': |
545 return skip("batch script") |
633 return skip("batch script") |
546 # To reliably get the error code from batch files on WinXP, |
634 runner = battest |
547 # the "cmd /c call" prefix is needed. Grrr |
635 elif lctest.endswith('.t'): |
548 cmd = 'cmd /c call "%s"' % testpath |
636 runner = tsttest |
|
637 ref = testpath |
549 else: |
638 else: |
550 # do not run shell scripts on windows |
639 # do not run shell scripts on windows |
551 if os.name == 'nt': |
640 if os.name == 'nt': |
552 return skip("shell script") |
641 return skip("shell script") |
553 # do not try to run non-executable programs |
642 # do not try to run non-executable programs |
554 if not os.path.exists(testpath): |
643 if not os.path.exists(testpath): |
555 return fail("does not exist") |
644 return fail("does not exist") |
556 elif not os.access(testpath, os.X_OK): |
645 elif not os.access(testpath, os.X_OK): |
557 return skip("not executable") |
646 return skip("not executable") |
558 cmd = '"%s"' % testpath |
647 runner = shtest |
559 |
648 |
560 # Make a tmp subdirectory to work in |
649 # Make a tmp subdirectory to work in |
561 tmpd = os.path.join(HGTMP, test) |
650 tmpd = os.path.join(HGTMP, test) |
562 os.mkdir(tmpd) |
651 os.mkdir(tmpd) |
563 os.chdir(tmpd) |
652 os.chdir(tmpd) |
564 |
653 |
565 if options.timeout > 0: |
654 if options.timeout > 0: |
566 signal.alarm(options.timeout) |
655 signal.alarm(options.timeout) |
567 |
656 |
568 vlog("# Running", cmd) |
657 ret, out = runner(testpath, options) |
569 ret, out = run(cmd, options) |
|
570 vlog("# Ret was:", ret) |
658 vlog("# Ret was:", ret) |
571 |
659 |
572 if options.timeout > 0: |
660 if options.timeout > 0: |
573 signal.alarm(0) |
661 signal.alarm(0) |
574 |
662 |