1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
import py, pytest
from rpython.tool import leakfinder
pytest_plugins = 'rpython.tool.pytest.expecttest'
option = None
def braindead_deindent(self):
"""monkeypatch that wont end up doing stupid in the python tokenizer"""
text = '\n'.join(self.lines)
short = py.std.textwrap.dedent(text)
newsource = py.code.Source()
newsource.lines[:] = short.splitlines()
return newsource
py.code.Source.deindent = braindead_deindent
def pytest_report_header():
return "pytest-%s from %s" %(pytest.__version__, pytest.__file__)
def pytest_configure(config):
global option
option = config.option
from rpython.config.translationoption import PLATFORMS
from rpython.translator.platform import set_platform
platform = config.option.platform
if platform not in PLATFORMS:
raise ValueError("%s not in %s" % (platform, PLATFORMS))
set_platform(platform, None)
def pytest_addoption(parser):
group = parser.getgroup("rpython options")
group.addoption('--view', action="store_true", dest="view", default=False,
help="view translation tests' flow graphs with Pygame")
group.addoption('-P', '--platform', action="store", dest="platform",
type="string", default="host",
help="set up tests to use specified platform as compile/run target")
group = parser.getgroup("JIT options")
group.addoption('--viewloops', action="store_true",
default=False, dest="viewloops",
help="show only the compiled loops")
group.addoption('--viewdeps', action="store_true",
default=False, dest="viewdeps",
help="show the dependencies that have been constructed from a trace")
def pytest_pycollect_makeitem(__multicall__,collector, name, obj):
res = __multicall__.execute()
# work around pytest issue 251
import inspect
if res is None and inspect.isclass(obj) and \
collector.classnamefilter(name):
return py.test.collect.Class(name, parent=collector)
return res
def pytest_addhooks(pluginmanager):
pluginmanager.register(LeakFinder())
class LeakFinder:
"""Track memory allocations during test execution.
So far, only used by the function lltype.malloc(flavor='raw').
"""
def pytest_runtest_setup(self, __multicall__, item):
__multicall__.execute()
if not isinstance(item, py.test.collect.Function):
return
if not getattr(item.obj, 'dont_track_allocations', False):
leakfinder.start_tracking_allocations()
def pytest_runtest_call(self, __multicall__, item):
__multicall__.execute()
if not isinstance(item, py.test.collect.Function):
return
item._success = True
def pytest_runtest_teardown(self, __multicall__, item):
__multicall__.execute()
if not isinstance(item, py.test.collect.Function):
return
if (not getattr(item.obj, 'dont_track_allocations', False)
and leakfinder.TRACK_ALLOCATIONS):
kwds = {}
try:
kwds['do_collection'] = item.track_allocations_collect
except AttributeError:
pass
item._pypytest_leaks = leakfinder.stop_tracking_allocations(False,
**kwds)
else: # stop_tracking_allocations() already called
item._pypytest_leaks = None
# check for leaks, but only if the test passed so far
if getattr(item, '_success', False) and item._pypytest_leaks:
raise leakfinder.MallocMismatch(item._pypytest_leaks)
|