comparison tests/run-tests.py @ 21534:3ece55d16044

run-tests: make attributes of TestRunner internal There is little reason for the data members of TestRunner to be public, as they are implementation details. Enforce it through naming.
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 25 Apr 2014 15:34:28 -0700
parents aecac8059c00
children ab7e224bc089
comparison
equal deleted inserted replaced
21533:aecac8059c00 21534:3ece55d16044
1336 ('.t', TTest), 1336 ('.t', TTest),
1337 ] 1337 ]
1338 1338
1339 def __init__(self): 1339 def __init__(self):
1340 self.options = None 1340 self.options = None
1341 self.testdir = None 1341 self._testdir = None
1342 self.hgtmp = None 1342 self._hgtmp = None
1343 self.inst = None 1343 self._installdir = None
1344 self.bindir = None 1344 self._bindir = None
1345 self.tmpbinddir = None 1345 self._tmpbinddir = None
1346 self.pythondir = None 1346 self._pythondir = None
1347 self.coveragefile = None 1347 self._coveragefile = None
1348 self._createdfiles = [] 1348 self._createdfiles = []
1349 self._hgpath = None 1349 self._hgpath = None
1350 1350
1351 def run(self, args, parser=None): 1351 def run(self, args, parser=None):
1352 """Run the test suite.""" 1352 """Run the test suite."""
1380 if kw in f: 1380 if kw in f:
1381 val *= 10 1381 val *= 10
1382 return val 1382 return val
1383 tests.sort(key=sortkey) 1383 tests.sort(key=sortkey)
1384 1384
1385 self.testdir = os.environ['TESTDIR'] = os.getcwd() 1385 self._testdir = os.environ['TESTDIR'] = os.getcwd()
1386 1386
1387 if 'PYTHONHASHSEED' not in os.environ: 1387 if 'PYTHONHASHSEED' not in os.environ:
1388 # use a random python hash seed all the time 1388 # use a random python hash seed all the time
1389 # we do the randomness ourself to know what seed is used 1389 # we do the randomness ourself to know what seed is used
1390 os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32)) 1390 os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32))
1410 if os.name == 'nt': 1410 if os.name == 'nt':
1411 # without this, we get the default temp dir location, but 1411 # without this, we get the default temp dir location, but
1412 # in all lowercase, which causes troubles with paths (issue3490) 1412 # in all lowercase, which causes troubles with paths (issue3490)
1413 d = os.getenv('TMP') 1413 d = os.getenv('TMP')
1414 tmpdir = tempfile.mkdtemp('', 'hgtests.', d) 1414 tmpdir = tempfile.mkdtemp('', 'hgtests.', d)
1415 self.hgtmp = os.environ['HGTMP'] = os.path.realpath(tmpdir) 1415 self._hgtmp = os.environ['HGTMP'] = os.path.realpath(tmpdir)
1416 1416
1417 if self.options.with_hg: 1417 if self.options.with_hg:
1418 self.inst = None 1418 self._installdir = None
1419 self.bindir = os.path.dirname(os.path.realpath( 1419 self._bindir = os.path.dirname(os.path.realpath(
1420 self.options.with_hg)) 1420 self.options.with_hg))
1421 self.tmpbindir = os.path.join(self.hgtmp, 'install', 'bin') 1421 self._tmpbindir = os.path.join(self._hgtmp, 'install', 'bin')
1422 os.makedirs(self.tmpbindir) 1422 os.makedirs(self._tmpbindir)
1423 1423
1424 # This looks redundant with how Python initializes sys.path from 1424 # This looks redundant with how Python initializes sys.path from
1425 # the location of the script being executed. Needed because the 1425 # the location of the script being executed. Needed because the
1426 # "hg" specified by --with-hg is not the only Python script 1426 # "hg" specified by --with-hg is not the only Python script
1427 # executed in the test suite that needs to import 'mercurial' 1427 # executed in the test suite that needs to import 'mercurial'
1428 # ... which means it's not really redundant at all. 1428 # ... which means it's not really redundant at all.
1429 self.pythondir = self.bindir 1429 self._pythondir = self._bindir
1430 else: 1430 else:
1431 self.inst = os.path.join(self.hgtmp, "install") 1431 self._installdir = os.path.join(self._hgtmp, "install")
1432 self.bindir = os.environ["BINDIR"] = os.path.join(self.inst, 1432 self._bindir = os.environ["BINDIR"] = \
1433 "bin") 1433 os.path.join(self._installdir, "bin")
1434 self.tmpbindir = self.bindir 1434 self._tmpbindir = self._bindir
1435 self.pythondir = os.path.join(self.inst, "lib", "python") 1435 self._pythondir = os.path.join(self._installdir, "lib", "python")
1436 1436
1437 os.environ["BINDIR"] = self.bindir 1437 os.environ["BINDIR"] = self._bindir
1438 os.environ["PYTHON"] = PYTHON 1438 os.environ["PYTHON"] = PYTHON
1439 1439
1440 path = [self.bindir] + os.environ["PATH"].split(os.pathsep) 1440 path = [self._bindir] + os.environ["PATH"].split(os.pathsep)
1441 if self.tmpbindir != self.bindir: 1441 if self._tmpbindir != self._bindir:
1442 path = [self.tmpbindir] + path 1442 path = [self._tmpbindir] + path
1443 os.environ["PATH"] = os.pathsep.join(path) 1443 os.environ["PATH"] = os.pathsep.join(path)
1444 1444
1445 # Include TESTDIR in PYTHONPATH so that out-of-tree extensions 1445 # Include TESTDIR in PYTHONPATH so that out-of-tree extensions
1446 # can run .../tests/run-tests.py test-foo where test-foo 1446 # can run .../tests/run-tests.py test-foo where test-foo
1447 # adds an extension to HGRC. Also include run-test.py directory to 1447 # adds an extension to HGRC. Also include run-test.py directory to
1448 # import modules like heredoctest. 1448 # import modules like heredoctest.
1449 pypath = [self.pythondir, self.testdir, 1449 pypath = [self._pythondir, self._testdir,
1450 os.path.abspath(os.path.dirname(__file__))] 1450 os.path.abspath(os.path.dirname(__file__))]
1451 # We have to augment PYTHONPATH, rather than simply replacing 1451 # We have to augment PYTHONPATH, rather than simply replacing
1452 # it, in case external libraries are only available via current 1452 # it, in case external libraries are only available via current
1453 # PYTHONPATH. (In particular, the Subversion bindings on OS X 1453 # PYTHONPATH. (In particular, the Subversion bindings on OS X
1454 # are in /opt/subversion.) 1454 # are in /opt/subversion.)
1455 oldpypath = os.environ.get(IMPL_PATH) 1455 oldpypath = os.environ.get(IMPL_PATH)
1456 if oldpypath: 1456 if oldpypath:
1457 pypath.append(oldpypath) 1457 pypath.append(oldpypath)
1458 os.environ[IMPL_PATH] = os.pathsep.join(pypath) 1458 os.environ[IMPL_PATH] = os.pathsep.join(pypath)
1459 1459
1460 self.coveragefile = os.path.join(self.testdir, '.coverage') 1460 self._coveragefile = os.path.join(self._testdir, '.coverage')
1461 1461
1462 vlog("# Using TESTDIR", self.testdir) 1462 vlog("# Using TESTDIR", self._testdir)
1463 vlog("# Using HGTMP", self.hgtmp) 1463 vlog("# Using HGTMP", self._hgtmp)
1464 vlog("# Using PATH", os.environ["PATH"]) 1464 vlog("# Using PATH", os.environ["PATH"])
1465 vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH]) 1465 vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH])
1466 1466
1467 try: 1467 try:
1468 return self._runtests(tests) or 0 1468 return self._runtests(tests) or 0
1489 if os.path.basename(t).startswith('test-') 1489 if os.path.basename(t).startswith('test-')
1490 and (t.endswith('.py') or t.endswith('.t'))] 1490 and (t.endswith('.py') or t.endswith('.t'))]
1491 1491
1492 def _runtests(self, tests): 1492 def _runtests(self, tests):
1493 try: 1493 try:
1494 if self.inst: 1494 if self._installdir:
1495 self._installhg() 1495 self._installhg()
1496 self._checkhglib("Testing") 1496 self._checkhglib("Testing")
1497 else: 1497 else:
1498 self._usecorrectpython() 1498 self._usecorrectpython()
1499 1499
1510 tests = [self._gettest(t, i) for i, t in enumerate(tests)] 1510 tests = [self._gettest(t, i) for i, t in enumerate(tests)]
1511 1511
1512 failed = False 1512 failed = False
1513 warned = False 1513 warned = False
1514 1514
1515 suite = TestSuite(self.testdir, 1515 suite = TestSuite(self._testdir,
1516 jobs=self.options.jobs, 1516 jobs=self.options.jobs,
1517 whitelist=self.options.whitelisted, 1517 whitelist=self.options.whitelisted,
1518 blacklist=self.options.blacklist, 1518 blacklist=self.options.blacklist,
1519 retest=self.options.retest, 1519 retest=self.options.retest,
1520 keywords=self.options.keywords, 1520 keywords=self.options.keywords,
1549 for ext, cls in self.TESTTYPES: 1549 for ext, cls in self.TESTTYPES:
1550 if lctest.endswith(ext): 1550 if lctest.endswith(ext):
1551 testcls = cls 1551 testcls = cls
1552 break 1552 break
1553 1553
1554 refpath = os.path.join(self.testdir, test) 1554 refpath = os.path.join(self._testdir, test)
1555 tmpdir = os.path.join(self.hgtmp, 'child%d' % count) 1555 tmpdir = os.path.join(self._hgtmp, 'child%d' % count)
1556 1556
1557 return testcls(refpath, tmpdir, 1557 return testcls(refpath, tmpdir,
1558 keeptmpdir=self.options.keep_tmpdir, 1558 keeptmpdir=self.options.keep_tmpdir,
1559 debug=self.options.debug, 1559 debug=self.options.debug,
1560 timeout=self.options.timeout, 1560 timeout=self.options.timeout,
1567 """Clean up state from this test invocation.""" 1567 """Clean up state from this test invocation."""
1568 1568
1569 if self.options.keep_tmpdir: 1569 if self.options.keep_tmpdir:
1570 return 1570 return
1571 1571
1572 vlog("# Cleaning up HGTMP", self.hgtmp) 1572 vlog("# Cleaning up HGTMP", self._hgtmp)
1573 shutil.rmtree(self.hgtmp, True) 1573 shutil.rmtree(self._hgtmp, True)
1574 for f in self._createdfiles: 1574 for f in self._createdfiles:
1575 try: 1575 try:
1576 os.remove(f) 1576 os.remove(f)
1577 except OSError: 1577 except OSError:
1578 pass 1578 pass
1582 # same interpreter or bad things will happen. 1582 # same interpreter or bad things will happen.
1583 pyexename = sys.platform == 'win32' and 'python.exe' or 'python' 1583 pyexename = sys.platform == 'win32' and 'python.exe' or 'python'
1584 if getattr(os, 'symlink', None): 1584 if getattr(os, 'symlink', None):
1585 vlog("# Making python executable in test path a symlink to '%s'" % 1585 vlog("# Making python executable in test path a symlink to '%s'" %
1586 sys.executable) 1586 sys.executable)
1587 mypython = os.path.join(self.tmpbindir, pyexename) 1587 mypython = os.path.join(self._tmpbindir, pyexename)
1588 try: 1588 try:
1589 if os.readlink(mypython) == sys.executable: 1589 if os.readlink(mypython) == sys.executable:
1590 return 1590 return
1591 os.unlink(mypython) 1591 os.unlink(mypython)
1592 except OSError, err: 1592 except OSError, err:
1638 ' install --force --prefix="%(prefix)s"' 1638 ' install --force --prefix="%(prefix)s"'
1639 ' --install-lib="%(libdir)s"' 1639 ' --install-lib="%(libdir)s"'
1640 ' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1' 1640 ' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1'
1641 % {'exe': sys.executable, 'py3': py3, 'pure': pure, 1641 % {'exe': sys.executable, 'py3': py3, 'pure': pure,
1642 'compiler': compiler, 1642 'compiler': compiler,
1643 'base': os.path.join(self.hgtmp, "build"), 1643 'base': os.path.join(self._hgtmp, "build"),
1644 'prefix': self.inst, 'libdir': self.pythondir, 1644 'prefix': self._installdir, 'libdir': self._pythondir,
1645 'bindir': self.bindir, 1645 'bindir': self._bindir,
1646 'nohome': nohome, 'logfile': installerrs}) 1646 'nohome': nohome, 'logfile': installerrs})
1647 vlog("# Running", cmd) 1647 vlog("# Running", cmd)
1648 if os.system(cmd) == 0: 1648 if os.system(cmd) == 0:
1649 if not self.options.verbose: 1649 if not self.options.verbose:
1650 os.remove(installerrs) 1650 os.remove(installerrs)
1652 f = open(installerrs) 1652 f = open(installerrs)
1653 for line in f: 1653 for line in f:
1654 print line, 1654 print line,
1655 f.close() 1655 f.close()
1656 sys.exit(1) 1656 sys.exit(1)
1657 os.chdir(self.testdir) 1657 os.chdir(self._testdir)
1658 1658
1659 self._usecorrectpython() 1659 self._usecorrectpython()
1660 1660
1661 if self.options.py3k_warnings and not self.options.anycoverage: 1661 if self.options.py3k_warnings and not self.options.anycoverage:
1662 vlog("# Updating hg command to enable Py3k Warnings switch") 1662 vlog("# Updating hg command to enable Py3k Warnings switch")
1663 f = open(os.path.join(self.bindir, 'hg'), 'r') 1663 f = open(os.path.join(self._bindir, 'hg'), 'r')
1664 lines = [line.rstrip() for line in f] 1664 lines = [line.rstrip() for line in f]
1665 lines[0] += ' -3' 1665 lines[0] += ' -3'
1666 f.close() 1666 f.close()
1667 f = open(os.path.join(self.bindir, 'hg'), 'w') 1667 f = open(os.path.join(self._bindir, 'hg'), 'w')
1668 for line in lines: 1668 for line in lines:
1669 f.write(line + '\n') 1669 f.write(line + '\n')
1670 f.close() 1670 f.close()
1671 1671
1672 hgbat = os.path.join(self.bindir, 'hg.bat') 1672 hgbat = os.path.join(self._bindir, 'hg.bat')
1673 if os.path.isfile(hgbat): 1673 if os.path.isfile(hgbat):
1674 # hg.bat expects to be put in bin/scripts while run-tests.py 1674 # hg.bat expects to be put in bin/scripts while run-tests.py
1675 # installation layout put it in bin/ directly. Fix it 1675 # installation layout put it in bin/ directly. Fix it
1676 f = open(hgbat, 'rb') 1676 f = open(hgbat, 'rb')
1677 data = f.read() 1677 data = f.read()
1684 f.close() 1684 f.close()
1685 else: 1685 else:
1686 print 'WARNING: cannot fix hg.bat reference to python.exe' 1686 print 'WARNING: cannot fix hg.bat reference to python.exe'
1687 1687
1688 if self.options.anycoverage: 1688 if self.options.anycoverage:
1689 custom = os.path.join(self.testdir, 'sitecustomize.py') 1689 custom = os.path.join(self._testdir, 'sitecustomize.py')
1690 target = os.path.join(self.pythondir, 'sitecustomize.py') 1690 target = os.path.join(self._pythondir, 'sitecustomize.py')
1691 vlog('# Installing coverage trigger to %s' % target) 1691 vlog('# Installing coverage trigger to %s' % target)
1692 shutil.copyfile(custom, target) 1692 shutil.copyfile(custom, target)
1693 rc = os.path.join(self.testdir, '.coveragerc') 1693 rc = os.path.join(self._testdir, '.coveragerc')
1694 vlog('# Installing coverage rc to %s' % rc) 1694 vlog('# Installing coverage rc to %s' % rc)
1695 os.environ['COVERAGE_PROCESS_START'] = rc 1695 os.environ['COVERAGE_PROCESS_START'] = rc
1696 fn = os.path.join(self.inst, '..', '.coverage') 1696 fn = os.path.join(self._installdir, '..', '.coverage')
1697 os.environ['COVERAGE_FILE'] = fn 1697 os.environ['COVERAGE_FILE'] = fn
1698 1698
1699 def _checkhglib(self, verb): 1699 def _checkhglib(self, verb):
1700 """Ensure that the 'mercurial' package imported by python is 1700 """Ensure that the 'mercurial' package imported by python is
1701 the one we expect it to be. If not, print a warning to stderr.""" 1701 the one we expect it to be. If not, print a warning to stderr."""
1702 expecthg = os.path.join(self.pythondir, 'mercurial') 1702 expecthg = os.path.join(self._pythondir, 'mercurial')
1703 actualhg = self._gethgpath() 1703 actualhg = self._gethgpath()
1704 if os.path.abspath(actualhg) != os.path.abspath(expecthg): 1704 if os.path.abspath(actualhg) != os.path.abspath(expecthg):
1705 sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n' 1705 sys.stderr.write('warning: %s with unexpected mercurial lib: %s\n'
1706 ' (expected %s)\n' 1706 ' (expected %s)\n'
1707 % (verb, actualhg, expecthg)) 1707 % (verb, actualhg, expecthg))
1720 1720
1721 return self._hgpath 1721 return self._hgpath
1722 1722
1723 def _outputcoverage(self): 1723 def _outputcoverage(self):
1724 vlog('# Producing coverage report') 1724 vlog('# Producing coverage report')
1725 os.chdir(self.pythondir) 1725 os.chdir(self._pythondir)
1726 1726
1727 def covrun(*args): 1727 def covrun(*args):
1728 cmd = 'coverage %s' % ' '.join(args) 1728 cmd = 'coverage %s' % ' '.join(args)
1729 vlog('# Running: %s' % cmd) 1729 vlog('# Running: %s' % cmd)
1730 os.system(cmd) 1730 os.system(cmd)
1731 1731
1732 covrun('-c') 1732 covrun('-c')
1733 omit = ','.join(os.path.join(x, '*') for x in 1733 omit = ','.join(os.path.join(x, '*') for x in
1734 [self.bindir, self.testdir]) 1734 [self._bindir, self._testdir])
1735 covrun('-i', '-r', '"--omit=%s"' % omit) # report 1735 covrun('-i', '-r', '"--omit=%s"' % omit) # report
1736 if self.options.htmlcov: 1736 if self.options.htmlcov:
1737 htmldir = os.path.join(self.testdir, 'htmlcov') 1737 htmldir = os.path.join(self._testdir, 'htmlcov')
1738 covrun('-i', '-b', '"--directory=%s"' % htmldir, 1738 covrun('-i', '-b', '"--directory=%s"' % htmldir,
1739 '"--omit=%s"' % omit) 1739 '"--omit=%s"' % omit)
1740 if self.options.annotate: 1740 if self.options.annotate:
1741 adir = os.path.join(self.testdir, 'annotated') 1741 adir = os.path.join(self._testdir, 'annotated')
1742 if not os.path.isdir(adir): 1742 if not os.path.isdir(adir):
1743 os.mkdir(adir) 1743 os.mkdir(adir)
1744 covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit) 1744 covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit)
1745 1745
1746 def _findprogram(self, program): 1746 def _findprogram(self, program):