##// END OF EJS Templates
errors: stop passing non-strings to Abort's constructor...
errors: stop passing non-strings to Abort's constructor The next patch will change `Abort`'s constructor and `__bytes__` functions and they will start assuming that the first argument is the messages as `bytes`. Differential Revision: https://phab.mercurial-scm.org/D9178

File last commit:

r43346:2372284d default
r46273:a736ab68 default
Show More
test-util.py
143 lines | 4.2 KiB | text/x-python | PythonLexer
Martijn Pieters
util: create a context manager to handle timing...
r38833 # unit tests for mercuril.util utilities
from __future__ import absolute_import
import contextlib
import itertools
import unittest
from mercurial import pycompat, util, utils
Augie Fackler
formatting: blacken the codebase...
r43346
Martijn Pieters
util: create a context manager to handle timing...
r38833 @contextlib.contextmanager
def mocktimer(incr=0.1, *additional_targets):
"""Replaces util.timer and additional_targets with a mock
The timer starts at 0. On each call the time incremented by the value
of incr. If incr is an iterable, then the time is incremented by the
next value from that iterable, looping in a cycle when reaching the end.
additional_targets must be a sequence of (object, attribute_name) tuples;
the mock is set with setattr(object, attribute_name, mock).
"""
time = [0]
try:
incr = itertools.cycle(incr)
except TypeError:
incr = itertools.repeat(incr)
def timer():
time[0] += next(incr)
return time[0]
# record original values
orig = util.timer
additional_origs = [(o, a, getattr(o, a)) for o, a in additional_targets]
# mock out targets
util.timer = timer
for obj, attr in additional_targets:
setattr(obj, attr, timer)
try:
yield
finally:
# restore originals
util.timer = orig
for args in additional_origs:
setattr(*args)
Augie Fackler
formatting: blacken the codebase...
r43346
Martijn Pieters
util: create a context manager to handle timing...
r38833 # attr.s default factory for util.timedstats.start binds the timer we
# need to mock out.
_start_default = (util.timedcmstats.start.default, 'factory')
Augie Fackler
formatting: blacken the codebase...
r43346
Martijn Pieters
util: create a context manager to handle timing...
r38833 @contextlib.contextmanager
def capturestderr():
"""Replace utils.procutil.stderr with a pycompat.bytesio instance
The instance is made available as the return value of __enter__.
This contextmanager is reentrant.
"""
orig = utils.procutil.stderr
utils.procutil.stderr = pycompat.bytesio()
try:
yield utils.procutil.stderr
finally:
utils.procutil.stderr = orig
Augie Fackler
formatting: blacken the codebase...
r43346
Martijn Pieters
util: create a context manager to handle timing...
r38833 class timedtests(unittest.TestCase):
def testtimedcmstatsstr(self):
stats = util.timedcmstats()
self.assertEqual(str(stats), '<unknown>')
Martijn Pieters
util: make new timedcmstats class Python 3 compatible
r38848 self.assertEqual(bytes(stats), b'<unknown>')
Martijn Pieters
util: create a context manager to handle timing...
r38833 stats.elapsed = 12.34
Martijn Pieters
util: make new timedcmstats class Python 3 compatible
r38848 self.assertEqual(str(stats), pycompat.sysstr(util.timecount(12.34)))
self.assertEqual(bytes(stats), util.timecount(12.34))
Martijn Pieters
util: create a context manager to handle timing...
r38833
def testtimedcmcleanexit(self):
# timestamps 1, 4, elapsed time of 4 - 1 = 3
with mocktimer([1, 3], _start_default):
Augie Fackler
cleanup: make all uses of timedcm specify what they're timing...
r39294 with util.timedcm('pass') as stats:
Martijn Pieters
util: create a context manager to handle timing...
r38833 # actual context doesn't matter
pass
self.assertEqual(stats.start, 1)
self.assertEqual(stats.elapsed, 3)
self.assertEqual(stats.level, 1)
def testtimedcmnested(self):
# timestamps 1, 3, 6, 10, elapsed times of 6 - 3 = 3 and 10 - 1 = 9
with mocktimer([1, 2, 3, 4], _start_default):
Augie Fackler
cleanup: make all uses of timedcm specify what they're timing...
r39294 with util.timedcm('outer') as outer_stats:
with util.timedcm('inner') as inner_stats:
Martijn Pieters
util: create a context manager to handle timing...
r38833 # actual context doesn't matter
pass
self.assertEqual(outer_stats.start, 1)
self.assertEqual(outer_stats.elapsed, 9)
self.assertEqual(outer_stats.level, 1)
self.assertEqual(inner_stats.start, 3)
self.assertEqual(inner_stats.elapsed, 3)
self.assertEqual(inner_stats.level, 2)
def testtimedcmexception(self):
# timestamps 1, 4, elapsed time of 4 - 1 = 3
with mocktimer([1, 3], _start_default):
try:
Augie Fackler
cleanup: make all uses of timedcm specify what they're timing...
r39294 with util.timedcm('exceptional') as stats:
Martijn Pieters
util: create a context manager to handle timing...
r38833 raise ValueError()
except ValueError:
pass
self.assertEqual(stats.start, 1)
self.assertEqual(stats.elapsed, 3)
self.assertEqual(stats.level, 1)
def testtimeddecorator(self):
@util.timed
def testfunc(callcount=1):
callcount -= 1
if callcount:
testfunc(callcount)
# timestamps 1, 2, 3, 4, elapsed time of 3 - 2 = 1 and 4 - 1 = 3
with mocktimer(1, _start_default):
with capturestderr() as out:
testfunc(2)
Augie Fackler
formatting: blacken the codebase...
r43346 self.assertEqual(
out.getvalue(),
(b' testfunc: 1.000 s\n' b' testfunc: 3.000 s\n'),
)
Martijn Pieters
util: create a context manager to handle timing...
r38833
if __name__ == '__main__':
import silenttestrunner
Augie Fackler
formatting: blacken the codebase...
r43346
Martijn Pieters
util: create a context manager to handle timing...
r38833 silenttestrunner.main(__name__)