|
1 import hotshot |
|
2 import hotshot.log |
|
3 import os |
|
4 import pprint |
|
5 import unittest |
|
6 |
|
7 from test import test_support |
|
8 |
|
9 from hotshot.log import ENTER, EXIT, LINE |
|
10 |
|
11 |
|
12 def shortfilename(fn): |
|
13 # We use a really shortened filename since an exact match is made, |
|
14 # and the source may be either a Python source file or a |
|
15 # pre-compiled bytecode file. |
|
16 if fn: |
|
17 return os.path.splitext(os.path.basename(fn))[0] |
|
18 else: |
|
19 return fn |
|
20 |
|
21 |
|
22 class UnlinkingLogReader(hotshot.log.LogReader): |
|
23 """Extend the LogReader so the log file is unlinked when we're |
|
24 done with it.""" |
|
25 |
|
26 def __init__(self, logfn): |
|
27 self.__logfn = logfn |
|
28 hotshot.log.LogReader.__init__(self, logfn) |
|
29 |
|
30 def next(self, index=None): |
|
31 try: |
|
32 return hotshot.log.LogReader.next(self) |
|
33 except StopIteration: |
|
34 self.close() |
|
35 os.unlink(self.__logfn) |
|
36 raise |
|
37 |
|
38 |
|
39 class HotShotTestCase(unittest.TestCase): |
|
40 def new_profiler(self, lineevents=0, linetimings=1): |
|
41 self.logfn = test_support.TESTFN |
|
42 return hotshot.Profile(self.logfn, lineevents, linetimings) |
|
43 |
|
44 def get_logreader(self): |
|
45 return UnlinkingLogReader(self.logfn) |
|
46 |
|
47 def get_events_wotime(self): |
|
48 L = [] |
|
49 for event in self.get_logreader(): |
|
50 what, (filename, lineno, funcname), tdelta = event |
|
51 L.append((what, (shortfilename(filename), lineno, funcname))) |
|
52 return L |
|
53 |
|
54 def check_events(self, expected): |
|
55 events = self.get_events_wotime() |
|
56 if events != expected: |
|
57 self.fail( |
|
58 "events did not match expectation; got:\n%s\nexpected:\n%s" |
|
59 % (pprint.pformat(events), pprint.pformat(expected))) |
|
60 |
|
61 def run_test(self, callable, events, profiler=None): |
|
62 if profiler is None: |
|
63 profiler = self.new_profiler() |
|
64 self.failUnless(not profiler._prof.closed) |
|
65 profiler.runcall(callable) |
|
66 self.failUnless(not profiler._prof.closed) |
|
67 profiler.close() |
|
68 self.failUnless(profiler._prof.closed) |
|
69 self.check_events(events) |
|
70 |
|
71 def test_addinfo(self): |
|
72 def f(p): |
|
73 p.addinfo("test-key", "test-value") |
|
74 profiler = self.new_profiler() |
|
75 profiler.runcall(f, profiler) |
|
76 profiler.close() |
|
77 log = self.get_logreader() |
|
78 info = log._info |
|
79 list(log) |
|
80 self.failUnless(info["test-key"] == ["test-value"]) |
|
81 |
|
82 def test_line_numbers(self): |
|
83 def f(): |
|
84 y = 2 |
|
85 x = 1 |
|
86 def g(): |
|
87 f() |
|
88 f_lineno = f.func_code.co_firstlineno |
|
89 g_lineno = g.func_code.co_firstlineno |
|
90 events = [(ENTER, ("test_hotshot", g_lineno, "g")), |
|
91 (LINE, ("test_hotshot", g_lineno+1, "g")), |
|
92 (ENTER, ("test_hotshot", f_lineno, "f")), |
|
93 (LINE, ("test_hotshot", f_lineno+1, "f")), |
|
94 (LINE, ("test_hotshot", f_lineno+2, "f")), |
|
95 (EXIT, ("test_hotshot", f_lineno, "f")), |
|
96 (EXIT, ("test_hotshot", g_lineno, "g")), |
|
97 ] |
|
98 self.run_test(g, events, self.new_profiler(lineevents=1)) |
|
99 |
|
100 def test_start_stop(self): |
|
101 # Make sure we don't return NULL in the start() and stop() |
|
102 # methods when there isn't an error. Bug in 2.2 noted by |
|
103 # Anthony Baxter. |
|
104 profiler = self.new_profiler() |
|
105 profiler.start() |
|
106 profiler.stop() |
|
107 profiler.close() |
|
108 os.unlink(self.logfn) |
|
109 |
|
110 def test_bad_sys_path(self): |
|
111 import sys |
|
112 import os |
|
113 orig_path = sys.path |
|
114 coverage = hotshot._hotshot.coverage |
|
115 try: |
|
116 # verify we require a list for sys.path |
|
117 sys.path = 'abc' |
|
118 self.assertRaises(RuntimeError, coverage, test_support.TESTFN) |
|
119 # verify that we require sys.path exists |
|
120 del sys.path |
|
121 self.assertRaises(RuntimeError, coverage, test_support.TESTFN) |
|
122 finally: |
|
123 sys.path = orig_path |
|
124 if os.path.exists(test_support.TESTFN): |
|
125 os.remove(test_support.TESTFN) |
|
126 |
|
127 def test_main(): |
|
128 test_support.run_unittest(HotShotTestCase) |
|
129 |
|
130 |
|
131 if __name__ == "__main__": |
|
132 test_main() |