annotate tests/test-util.py @ 41163:0101a35deae2

phabricator: warn if unable to amend, instead of aborting after posting There was a divergence in behavior here between obsolete and strip based amending. I first noticed the abort when testing outside of the test harness, but then had trouble recreating it here after reverting the code changes. It turns out, strip based amend was successfully amending the public commit after it was posted! It looks like the protection is in the `commit --amend` command, not in the underlying code that it calls. I considered doing a preflight check and aborting. But the locks are only acquired at the end, if amending, and this is too large a section of code to be wrapped in a maybe-it's-held-or-not context manager for my tastes. Additionally, some people do post-push reviews, and amending is the default behavior, so they shouldn't see a misleading error message. The lack of a 'Differential Revision' entry in the commit message breaks a {phabreview} test, so it had to be partially conditionalized.
author Matt Harbison <matt_harbison@yahoo.com>
date Sat, 05 Jan 2019 15:20:33 -0500
parents 331ab85e910b
children 2372284d9457
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
38797
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
1 # unit tests for mercuril.util utilities
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
2 from __future__ import absolute_import
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
3
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
4 import contextlib
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
5 import itertools
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
6 import unittest
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
7
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
8 from mercurial import pycompat, util, utils
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
9
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
10 @contextlib.contextmanager
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
11 def mocktimer(incr=0.1, *additional_targets):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
12 """Replaces util.timer and additional_targets with a mock
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
13
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
14 The timer starts at 0. On each call the time incremented by the value
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
15 of incr. If incr is an iterable, then the time is incremented by the
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
16 next value from that iterable, looping in a cycle when reaching the end.
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
17
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
18 additional_targets must be a sequence of (object, attribute_name) tuples;
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
19 the mock is set with setattr(object, attribute_name, mock).
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
20
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
21 """
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
22 time = [0]
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
23 try:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
24 incr = itertools.cycle(incr)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
25 except TypeError:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
26 incr = itertools.repeat(incr)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
27
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
28 def timer():
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
29 time[0] += next(incr)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
30 return time[0]
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
31
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
32 # record original values
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
33 orig = util.timer
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
34 additional_origs = [(o, a, getattr(o, a)) for o, a in additional_targets]
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
35
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
36 # mock out targets
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
37 util.timer = timer
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
38 for obj, attr in additional_targets:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
39 setattr(obj, attr, timer)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
40
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
41 try:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
42 yield
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
43 finally:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
44 # restore originals
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
45 util.timer = orig
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
46 for args in additional_origs:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
47 setattr(*args)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
48
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
49 # attr.s default factory for util.timedstats.start binds the timer we
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
50 # need to mock out.
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
51 _start_default = (util.timedcmstats.start.default, 'factory')
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
52
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
53 @contextlib.contextmanager
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
54 def capturestderr():
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
55 """Replace utils.procutil.stderr with a pycompat.bytesio instance
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
56
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
57 The instance is made available as the return value of __enter__.
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
58
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
59 This contextmanager is reentrant.
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
60
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
61 """
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
62 orig = utils.procutil.stderr
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
63 utils.procutil.stderr = pycompat.bytesio()
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
64 try:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
65 yield utils.procutil.stderr
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
66 finally:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
67 utils.procutil.stderr = orig
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
68
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
69 class timedtests(unittest.TestCase):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
70 def testtimedcmstatsstr(self):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
71 stats = util.timedcmstats()
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
72 self.assertEqual(str(stats), '<unknown>')
38812
9d49bb117dde util: make new timedcmstats class Python 3 compatible
Martijn Pieters <mj@zopatista.com>
parents: 38797
diff changeset
73 self.assertEqual(bytes(stats), b'<unknown>')
38797
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
74 stats.elapsed = 12.34
38812
9d49bb117dde util: make new timedcmstats class Python 3 compatible
Martijn Pieters <mj@zopatista.com>
parents: 38797
diff changeset
75 self.assertEqual(str(stats), pycompat.sysstr(util.timecount(12.34)))
9d49bb117dde util: make new timedcmstats class Python 3 compatible
Martijn Pieters <mj@zopatista.com>
parents: 38797
diff changeset
76 self.assertEqual(bytes(stats), util.timecount(12.34))
38797
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
77
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
78 def testtimedcmcleanexit(self):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
79 # timestamps 1, 4, elapsed time of 4 - 1 = 3
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
80 with mocktimer([1, 3], _start_default):
39258
331ab85e910b cleanup: make all uses of timedcm specify what they're timing
Augie Fackler <augie@google.com>
parents: 38812
diff changeset
81 with util.timedcm('pass') as stats:
38797
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
82 # actual context doesn't matter
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
83 pass
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
84
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
85 self.assertEqual(stats.start, 1)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
86 self.assertEqual(stats.elapsed, 3)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
87 self.assertEqual(stats.level, 1)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
88
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
89 def testtimedcmnested(self):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
90 # timestamps 1, 3, 6, 10, elapsed times of 6 - 3 = 3 and 10 - 1 = 9
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
91 with mocktimer([1, 2, 3, 4], _start_default):
39258
331ab85e910b cleanup: make all uses of timedcm specify what they're timing
Augie Fackler <augie@google.com>
parents: 38812
diff changeset
92 with util.timedcm('outer') as outer_stats:
331ab85e910b cleanup: make all uses of timedcm specify what they're timing
Augie Fackler <augie@google.com>
parents: 38812
diff changeset
93 with util.timedcm('inner') as inner_stats:
38797
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
94 # actual context doesn't matter
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
95 pass
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
96
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
97 self.assertEqual(outer_stats.start, 1)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
98 self.assertEqual(outer_stats.elapsed, 9)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
99 self.assertEqual(outer_stats.level, 1)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
100
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
101 self.assertEqual(inner_stats.start, 3)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
102 self.assertEqual(inner_stats.elapsed, 3)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
103 self.assertEqual(inner_stats.level, 2)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
104
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
105 def testtimedcmexception(self):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
106 # timestamps 1, 4, elapsed time of 4 - 1 = 3
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
107 with mocktimer([1, 3], _start_default):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
108 try:
39258
331ab85e910b cleanup: make all uses of timedcm specify what they're timing
Augie Fackler <augie@google.com>
parents: 38812
diff changeset
109 with util.timedcm('exceptional') as stats:
38797
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
110 raise ValueError()
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
111 except ValueError:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
112 pass
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
113
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
114 self.assertEqual(stats.start, 1)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
115 self.assertEqual(stats.elapsed, 3)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
116 self.assertEqual(stats.level, 1)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
117
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
118 def testtimeddecorator(self):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
119 @util.timed
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
120 def testfunc(callcount=1):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
121 callcount -= 1
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
122 if callcount:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
123 testfunc(callcount)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
124
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
125 # timestamps 1, 2, 3, 4, elapsed time of 3 - 2 = 1 and 4 - 1 = 3
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
126 with mocktimer(1, _start_default):
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
127 with capturestderr() as out:
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
128 testfunc(2)
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
129
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
130 self.assertEqual(out.getvalue(), (
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
131 b' testfunc: 1.000 s\n'
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
132 b' testfunc: 3.000 s\n'
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
133 ))
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
134
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
135 if __name__ == '__main__':
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
136 import silenttestrunner
8751d1e2a7ff util: create a context manager to handle timing
Martijn Pieters <mj@zopatista.com>
parents:
diff changeset
137 silenttestrunner.main(__name__)