53 import tempfile |
53 import tempfile |
54 import time |
54 import time |
55 import re |
55 import re |
56 import threading |
56 import threading |
57 |
57 |
|
58 processlock = threading.Lock() |
|
59 |
58 closefds = os.name == 'posix' |
60 closefds = os.name == 'posix' |
59 def Popen4(cmd, timeout): |
61 def Popen4(cmd, wd, timeout): |
|
62 processlock.acquire() |
|
63 orig = os.getcwd() |
|
64 os.chdir(wd) |
60 p = subprocess.Popen(cmd, shell=True, bufsize=-1, |
65 p = subprocess.Popen(cmd, shell=True, bufsize=-1, |
61 close_fds=closefds, |
66 close_fds=closefds, |
62 stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
67 stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
63 stderr=subprocess.STDOUT) |
68 stderr=subprocess.STDOUT) |
|
69 os.chdir(orig) |
|
70 processlock.release() |
|
71 |
64 p.fromchild = p.stdout |
72 p.fromchild = p.stdout |
65 p.tochild = p.stdin |
73 p.tochild = p.stdin |
66 p.childerr = p.stderr |
74 p.childerr = p.stderr |
67 |
75 |
68 if timeout: |
76 if timeout: |
455 adir = os.path.join(TESTDIR, 'annotated') |
463 adir = os.path.join(TESTDIR, 'annotated') |
456 if not os.path.isdir(adir): |
464 if not os.path.isdir(adir): |
457 os.mkdir(adir) |
465 os.mkdir(adir) |
458 covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit) |
466 covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit) |
459 |
467 |
460 def pytest(test, options, replacements): |
468 def pytest(test, wd, options, replacements): |
461 py3kswitch = options.py3k_warnings and ' -3' or '' |
469 py3kswitch = options.py3k_warnings and ' -3' or '' |
462 cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test) |
470 cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test) |
463 vlog("# Running", cmd) |
471 vlog("# Running", cmd) |
464 return run(cmd, options, replacements) |
472 return run(cmd, wd, options, replacements) |
465 |
473 |
466 def shtest(test, options, replacements): |
474 def shtest(test, wd, options, replacements): |
467 cmd = '"%s"' % test |
475 cmd = '"%s"' % test |
468 vlog("# Running", cmd) |
476 vlog("# Running", cmd) |
469 return run(cmd, options, replacements) |
477 return run(cmd, wd, options, replacements) |
470 |
478 |
471 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search |
479 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search |
472 escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub |
480 escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub |
473 escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256)) |
481 escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256)) |
474 escapemap.update({'\\': '\\\\', '\r': r'\r'}) |
482 escapemap.update({'\\': '\\\\', '\r': r'\r'}) |
475 def escapef(m): |
483 def escapef(m): |
476 return escapemap[m.group(0)] |
484 return escapemap[m.group(0)] |
477 def stringescape(s): |
485 def stringescape(s): |
478 return escapesub(escapef, s) |
486 return escapesub(escapef, s) |
479 |
487 |
480 def tsttest(test, options, replacements): |
488 def tsttest(test, wd, options, replacements): |
481 t = open(test) |
489 t = open(test) |
482 out = [] |
490 out = [] |
483 script = [] |
491 script = [] |
484 salt = "SALT" + str(time.time()) |
492 salt = "SALT" + str(time.time()) |
485 |
493 |
516 os.write(fd, l) |
524 os.write(fd, l) |
517 os.close(fd) |
525 os.close(fd) |
518 |
526 |
519 cmd = '/bin/sh "%s"' % name |
527 cmd = '/bin/sh "%s"' % name |
520 vlog("# Running", cmd) |
528 vlog("# Running", cmd) |
521 exitcode, output = run(cmd, options, replacements) |
529 exitcode, output = run(cmd, wd, options, replacements) |
522 # do not merge output if skipped, return hghave message instead |
530 # do not merge output if skipped, return hghave message instead |
523 # similarly, with --debug, output is None |
531 # similarly, with --debug, output is None |
524 if exitcode == SKIPPED_STATUS or output is None: |
532 if exitcode == SKIPPED_STATUS or output is None: |
525 return exitcode, output |
533 return exitcode, output |
526 finally: |
534 finally: |
595 postout += after.pop(pos) |
603 postout += after.pop(pos) |
596 |
604 |
597 return exitcode, postout |
605 return exitcode, postout |
598 |
606 |
599 wifexited = getattr(os, "WIFEXITED", lambda x: False) |
607 wifexited = getattr(os, "WIFEXITED", lambda x: False) |
600 def run(cmd, options, replacements): |
608 def run(cmd, wd, options, replacements): |
601 """Run command in a sub-process, capturing the output (stdout and stderr). |
609 """Run command in a sub-process, capturing the output (stdout and stderr). |
602 Return a tuple (exitcode, output). output is None in debug mode.""" |
610 Return a tuple (exitcode, output). output is None in debug mode.""" |
603 # TODO: Use subprocess.Popen if we're running on Python 2.4 |
611 # TODO: Use subprocess.Popen if we're running on Python 2.4 |
604 if options.debug: |
612 if options.debug: |
605 proc = subprocess.Popen(cmd, shell=True) |
613 proc = subprocess.Popen(cmd, shell=True) |
773 # Make a tmp subdirectory to work in |
781 # Make a tmp subdirectory to work in |
774 testtmp = os.environ["TESTTMP"] = os.environ["HOME"] = \ |
782 testtmp = os.environ["TESTTMP"] = os.environ["HOME"] = \ |
775 os.path.join(HGTMP, test) |
783 os.path.join(HGTMP, test) |
776 |
784 |
777 os.mkdir(testtmp) |
785 os.mkdir(testtmp) |
778 os.chdir(testtmp) |
786 ret, out = runner(testpath, testtmp, options, [ |
779 |
|
780 ret, out = runner(testpath, options, [ |
|
781 (re.escape(testtmp), '$TESTTMP'), |
787 (re.escape(testtmp), '$TESTTMP'), |
782 (r':%s\b' % options.port, ':$HGPORT'), |
788 (r':%s\b' % options.port, ':$HGPORT'), |
783 (r':%s\b' % (options.port + 1), ':$HGPORT1'), |
789 (r':%s\b' % (options.port + 1), ':$HGPORT1'), |
784 (r':%s\b' % (options.port + 2), ':$HGPORT2'), |
790 (r':%s\b' % (options.port + 2), ':$HGPORT2'), |
785 ]) |
791 ]) |