[Python-checkins] python/dist/src/Lib/test regrtest.py,1.156,1.157
mwh at users.sourceforge.net
mwh at users.sourceforge.net
Tue Aug 3 13:33:31 CEST 2004
Update of /cvsroot/python/python/dist/src/Lib/test
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32643
Modified Files:
regrtest.py
Log Message:
Check in my refleak hunting code.
It's not the 100% solution -- it may not even be the 90% solution -- but
it does seem to help.
Index: regrtest.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/regrtest.py,v
retrieving revision 1.156
retrieving revision 1.157
diff -C2 -d -r1.156 -r1.157
*** regrtest.py 26 Jul 2004 12:09:13 -0000 1.156
--- regrtest.py 3 Aug 2004 11:33:28 -0000 1.157
***************
*** 9,25 ****
Command line options:
! -v: verbose -- run tests in verbose mode with output to stdout
! -q: quiet -- don't print anything except if a test fails
! -g: generate -- write the output file for a test instead of comparing it
! -x: exclude -- arguments are tests to *exclude*
! -s: single -- run only a single test (see below)
! -r: random -- randomize test execution order
! -f: fromfile -- read names of tests to run from a file (see below)
! -l: findleaks -- if GC is available detect tests that leak memory
! -u: use -- specify which special resource intensive tests to run
! -h: help -- print this text and exit
! -t: threshold -- call gc.set_threshold(N)
! -T: coverage -- turn on code coverage using the trace module
! -L: runleaks -- run the leaks(1) command just before exit
If non-option arguments are present, they are names for tests to run,
--- 9,26 ----
Command line options:
! -v: verbose -- run tests in verbose mode with output to stdout
! -q: quiet -- don't print anything except if a test fails
! -g: generate -- write the output file for a test instead of comparing it
! -x: exclude -- arguments are tests to *exclude*
! -s: single -- run only a single test (see below)
! -r: random -- randomize test execution order
! -f: fromfile -- read names of tests to run from a file (see below)
! -l: findleaks -- if GC is available detect tests that leak memory
! -u: use -- specify which special resource intensive tests to run
! -h: help -- print this text and exit
! -t: threshold -- call gc.set_threshold(N)
! -T: coverage -- turn on code coverage using the trace module
! -L: runleaks -- run the leaks(1) command just before exit
! -R: huntrleaks -- search for reference leaks (needs debug build, v. slow)
If non-option arguments are present, they are names for tests to run,
***************
*** 48,51 ****
--- 49,60 ----
FreeBSD-derived systems.
+ -R runs each test several times and examines sys.gettotalrefcount() to
+ see if the test appears to be leaking references. The argument should
+ be of the form stab:run:fname where 'stab' is the number of times the
+ test is run to let gettotalrefcount settle down, 'run' is the number
+ of times further it is run and 'fname' is the name of the file the
+ reports are written to. These parameters all have defaults (5, 4 and
+ "reflog.txt" respectively), so the minimal invocation is '-R ::'.
+
-u is used to specify which special resource intensive tests to run,
such as those requiring large file support or network connectivity.
***************
*** 85,88 ****
--- 94,98 ----
import random
import warnings
+ import sre
import cStringIO
import traceback
***************
*** 128,132 ****
def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False,
exclude=False, single=False, randomize=False, fromfile=None,
! findleaks=False, use_resources=None, trace=False, runleaks=False):
"""Execute a test suite.
--- 138,143 ----
def main(tests=None, testdir=None, verbose=0, quiet=False, generate=False,
exclude=False, single=False, randomize=False, fromfile=None,
! findleaks=False, use_resources=None, trace=False, runleaks=False,
! huntrleaks=False):
"""Execute a test suite.
***************
*** 153,161 ****
test_support.record_original_stdout(sys.stdout)
try:
! opts, args = getopt.getopt(sys.argv[1:], 'hvgqxsrf:lu:t:TL',
['help', 'verbose', 'quiet', 'generate',
'exclude', 'single', 'random', 'fromfile',
'findleaks', 'use=', 'threshold=', 'trace',
! 'runleaks'
])
except getopt.error, msg:
--- 164,172 ----
test_support.record_original_stdout(sys.stdout)
try:
! opts, args = getopt.getopt(sys.argv[1:], 'hvgqxsrf:lu:t:TLR:',
['help', 'verbose', 'quiet', 'generate',
'exclude', 'single', 'random', 'fromfile',
'findleaks', 'use=', 'threshold=', 'trace',
! 'runleaks', 'huntrleaks='
])
except getopt.error, msg:
***************
*** 192,195 ****
--- 203,221 ----
elif o in ('-T', '--coverage'):
trace = True
+ elif o in ('-R', '--huntrleaks'):
+ huntrleaks = a.split(':')
+ if len(huntrleaks) != 3:
+ print a, huntrleaks
+ usage(2, '-R takes three colon-separated arguments')
+ if len(huntrleaks[0]) == 0:
+ huntrleaks[0] = 5
+ else:
+ huntrleaks[0] = int(huntrleaks[0])
+ if len(huntrleaks[1]) == 0:
+ huntrleaks[1] = 4
+ else:
+ huntrleaks[1] = int(huntrleaks[1])
+ if len(huntrleaks[2]) == 0:
+ huntrleaks[2] = "reflog.txt"
elif o in ('-u', '--use'):
u = [x.lower() for x in a.split(',')]
***************
*** 289,293 ****
globals=globals(), locals=vars())
else:
! ok = runtest(test, generate, verbose, quiet, testdir)
if ok > 0:
good.append(test)
--- 315,319 ----
globals=globals(), locals=vars())
else:
! ok = runtest(test, generate, verbose, quiet, testdir, huntrleaks)
if ok > 0:
good.append(test)
***************
*** 398,402 ****
return stdtests + tests
! def runtest(test, generate, verbose, quiet, testdir=None):
"""Run a single test.
test -- the name of the test
--- 424,428 ----
return stdtests + tests
! def runtest(test, generate, verbose, quiet, testdir=None, huntrleaks=False):
"""Run a single test.
test -- the name of the test
***************
*** 416,419 ****
--- 442,447 ----
else:
cfp = cStringIO.StringIO()
+ if huntrleaks:
+ refrep = open(huntrleaks[2], "a")
try:
save_stdout = sys.stdout
***************
*** 436,439 ****
--- 464,511 ----
if indirect_test is not None:
indirect_test()
+ if huntrleaks:
+ # This code *is* hackish and inelegant, yes.
+ # But it seems to do the job.
+ import copy_reg
+ fs = warnings.filters[:]
+ ps = copy_reg.dispatch_table.copy()
+ pic = sys.path_importer_cache.copy()
+ import gc
+ def cleanup():
+ import _strptime, urlparse, warnings, dircache
+ from distutils.dir_util import _path_created
+ _path_created.clear()
+ warnings.filters[:] = fs
+ gc.collect()
+ sre.purge()
+ _strptime._regex_cache.clear()
+ urlparse.clear_cache()
+ copy_reg.dispatch_table.clear()
+ copy_reg.dispatch_table.update(ps)
+ sys.path_importer_cache.clear()
+ sys.path_importer_cache.update(pic)
+ dircache.reset()
+ if indirect_test:
+ def run_the_test():
+ indirect_test()
+ else:
+ def run_the_test():
+ reload(the_module)
+ deltas = []
+ repcount = huntrleaks[0] + huntrleaks[1]
+ print >> sys.stderr, "beginning", repcount, "repetitions"
+ print >> sys.stderr, \
+ ("1234567890"*(repcount//10 + 1))[:repcount]
+ for i in range(repcount):
+ rc = sys.gettotalrefcount()
+ run_the_test()
+ sys.stderr.write('.')
+ cleanup()
+ deltas.append(sys.gettotalrefcount() - rc - 2)
+ print >>sys.stderr
+ if max(map(abs, deltas[-huntrleaks[1]:])) > 0:
+ print >>refrep, test, 'leaked', \
+ deltas[-huntrleaks[1]:], 'references'
+ # The end of the huntrleaks hackishness.
finally:
sys.stdout = save_stdout
***************
*** 487,491 ****
else:
expected = test + "\n"
! if output == expected:
return 1
print "test", test, "produced unexpected output:"
--- 559,563 ----
else:
expected = test + "\n"
! if output == expected or huntrleaks:
return 1
print "test", test, "produced unexpected output:"
More information about the Python-checkins
mailing list