blob: c04be50796957a474329ac513904b05c7f233174 [file] [log] [blame]
Alexander Belopolskyca237842010-07-28 14:29:34 +00001import imp
2import os
3import sys
4from test import test_support
5import unittest
6
7import trace
8from trace import CoverageResults, Trace
9
10
11#------------------------------- Utilities -----------------------------------#
12
13def make_fake_module():
14 """Creates a fake module named 'fakemodule'.
15
16 The new module has a single function named 'foo', and it's placed in
17 sys.modules
18 The file this fake module "comes from" is fakefile.py
19
20 """
21
22 # Prepare the function to import from the fake module
23 #
24 _fake_foo_src = r'''
25def foo(a_):
26 b = a_ + 1
27 return b + 2
28'''.lstrip()
29
30 _fake_foo = compile(_fake_foo_src, 'fakefile.py', 'exec')
31
32 # Create a new module, place the function into it and add it to sys.modules
33 #
34 fakemodule = imp.new_module('fakemodule')
35 exec _fake_foo in fakemodule.__dict__
36 fakemodule.__file__ = 'fakefile.py'
37 sys.modules['fakemodule'] = fakemodule
38
39
40def modname(filename):
41 """Infer a module name from a containing file name"""
42 base = os.path.basename(filename)
43 mod, ext = os.path.splitext(base)
44 return mod
45
46
47def my_file_and_modname():
48 """The file and module name of this file (__file__)"""
49 return __file__, modname(__file__)
50
51
52#-------------------- Target functions for tracing ---------------------------#
53
54def _traced_func_linear(a_, b_):
55 a = a_
56 b = b_
57 c = a + b
58 return c
59
60def _traced_func_loop(a_, b_):
61 c = a_
62 for i in range(5):
63 c += b_
64 return c
65
66# Expects the 'fakemodule' module to exist and have a 'foo' function in it
67#
68def _traced_func_importing(a_, b_):
69 from fakemodule import foo
70 return a_ + b_ + foo(1)
71
72def _traced_func_simple_caller(a_):
73 c = _traced_func_linear(a_, a_)
74 return c + a_
75
76def _traced_func_importing_caller(a_):
77 k = _traced_func_simple_caller(a_)
78 k += _traced_func_importing(k, a_)
79 return k
80
81
82#------------------------------ Test cases -----------------------------------#
83
84
85class TestLineCounts(unittest.TestCase):
86 """White-box testing of line-counting, via runfunc"""
87 def setUp(self):
88 self.tr = Trace(count=1, trace=0, countfuncs=0, countcallers=0)
89
90 def test_traced_func_linear(self):
91 result = self.tr.runfunc(_traced_func_linear, 2, 5)
92 self.assertEqual(result, 7)
93
94 # all lines are executed once
95 expected = {}
96 firstlineno = _traced_func_linear.__code__.co_firstlineno
97 for i in range(1, 5):
98 expected[(__file__, firstlineno + i)] = 1
99
100 self.assertEqual(self.tr.results().counts, expected)
101
102 def test_traced_func_loop(self):
103 self.tr.runfunc(_traced_func_loop, 2, 3)
104
105 firstlineno = _traced_func_loop.__code__.co_firstlineno
106 expected = {
107 (__file__, firstlineno + 1): 1,
108 (__file__, firstlineno + 2): 6,
109 (__file__, firstlineno + 3): 5,
110 (__file__, firstlineno + 4): 1,
111 }
112 self.assertEqual(self.tr.results().counts, expected)
113
114 def test_traced_func_importing(self):
115 make_fake_module()
116 self.tr.runfunc(_traced_func_importing, 2, 5)
117
118 firstlineno = _traced_func_importing.__code__.co_firstlineno
119 expected = {
120 (__file__, firstlineno + 1): 1,
121 (__file__, firstlineno + 2): 1,
122 ('fakefile.py', 2): 1,
123 ('fakefile.py', 3): 1,
124 }
125 self.assertEqual(self.tr.results().counts, expected)
126
127
128class TestRunExecCounts(unittest.TestCase):
129 """A simple sanity test of line-counting, via run (exec)"""
130 def test_tt(self):
131 self.tr = Trace(count=1, trace=0, countfuncs=0, countcallers=0)
132 code = r'''_traced_func_loop(2, 5)'''
133 code = compile(code, __file__, 'exec')
134 self.tr.run(code)
135
136 firstlineno = _traced_func_loop.__code__.co_firstlineno
137 expected = {
138 (__file__, firstlineno + 1): 1,
139 (__file__, firstlineno + 2): 6,
140 (__file__, firstlineno + 3): 5,
141 (__file__, firstlineno + 4): 1,
142 }
143
144 # When used through 'run', some other spurios counts are produced, like
145 # the settrace of threading, which we ignore, just making sure that the
146 # counts fo _traced_func_loop were right.
147 #
148 for k in expected.keys():
149 self.assertEqual(self.tr.results().counts[k], expected[k])
150
151
152class TestFuncs(unittest.TestCase):
153 """White-box testing of funcs tracing"""
154 def setUp(self):
155 self.tr = Trace(count=0, trace=0, countfuncs=1)
156 self.filemod = my_file_and_modname()
157
158 def test_simple_caller(self):
159 self.tr.runfunc(_traced_func_simple_caller, 1)
160
161 expected = {
162 self.filemod + ('_traced_func_simple_caller',): 1,
163 self.filemod + ('_traced_func_linear',): 1,
164 }
165 self.assertEqual(self.tr.results().calledfuncs, expected)
166
167 def test_loop_caller_importing(self):
168 make_fake_module()
169 self.tr.runfunc(_traced_func_importing_caller, 1)
170
171 expected = {
172 self.filemod + ('_traced_func_simple_caller',): 1,
173 self.filemod + ('_traced_func_linear',): 1,
174 self.filemod + ('_traced_func_importing_caller',): 1,
175 self.filemod + ('_traced_func_importing',): 1,
176 ('fakefile.py', 'fakefile', 'foo'): 1,
177 }
178 self.assertEqual(self.tr.results().calledfuncs, expected)
179
180
181class TestCallers(unittest.TestCase):
182 """White-box testing of callers tracing"""
183 def setUp(self):
184 self.tr = Trace(count=0, trace=0, countcallers=1)
185 self.filemod = my_file_and_modname()
186
187 def test_loop_caller_importing(self):
188 make_fake_module()
189 self.tr.runfunc(_traced_func_importing_caller, 1)
190
191 expected = {
192 ((os.path.splitext(trace.__file__)[0] + '.py', 'trace', 'Trace.runfunc'),
193 (self.filemod + ('_traced_func_importing_caller',))): 1,
194 ((self.filemod + ('_traced_func_simple_caller',)),
195 (self.filemod + ('_traced_func_linear',))): 1,
196 ((self.filemod + ('_traced_func_importing_caller',)),
197 (self.filemod + ('_traced_func_simple_caller',))): 1,
198 ((self.filemod + ('_traced_func_importing_caller',)),
199 (self.filemod + ('_traced_func_importing',))): 1,
200 ((self.filemod + ('_traced_func_importing',)),
201 ('fakefile.py', 'fakefile', 'foo')): 1,
202 }
203 self.assertEqual(self.tr.results().callers, expected)
204
205
206#------------------------------ Driver ---------------------------------------#
207
208def test_main():
209 print(__name__, type(__name__))
210 test_support.run_unittest(__name__)
211
212
213if __name__ == '__main__':
214 test_main()