1
# Copyright (C) 2005, 2006 Canonical Ltd
1
# Copyright (C) 2007, 2009, 2010, 2011 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
"""Tests for profiling data collection."""
24
from bzrlib import tests
27
class _LSProfFeature(tests.Feature):
31
from bzrlib import lsprof
38
LSProfFeature = _LSProfFeature()
21
import cPickle as pickle
27
from .. import errors, tests
41
33
_TXT_HEADER = " CallCount Recursive Total(ms) " + \
50
42
def _collect_stats():
51
43
"Collect and return some dummy profile data."
52
from bzrlib.lsprof import profile
44
from breezy.lsprof import profile
53
45
ret, stats = profile(_junk_callable)
57
49
class TestStatsSave(tests.TestCaseInTempDir):
59
_test_needs_features = [LSProfFeature]
51
_test_needs_features = [features.lsprof_feature]
62
54
super(tests.TestCaseInTempDir, self).setUp()
65
57
def _tempfile(self, ext):
66
58
dir = self.test_dir
67
return bzrlib.osutils.pathjoin(dir, "tmp_profile_data." + ext)
59
return breezy.osutils.pathjoin(dir, "tmp_profile_data." + ext)
69
61
def test_stats_save_to_txt(self):
70
62
f = self._tempfile("txt")
78
70
lines = open(f).readlines()
79
71
self.assertEqual(lines[0], "events: Ticks\n")
80
f = bzrlib.osutils.pathjoin(self.test_dir, "callgrind.out.foo")
72
f = breezy.osutils.pathjoin(self.test_dir, "callgrind.out.foo")
82
74
lines = open(f).readlines()
83
75
self.assertEqual(lines[0], "events: Ticks\n")
90
82
def test_stats_save_to_pickle(self):
91
83
f = self._tempfile("pkl")
93
data1 = cPickle.load(open(f))
94
self.assertEqual(type(data1), bzrlib.lsprof.Stats)
85
data1 = pickle.load(open(f))
86
self.assertEqual(type(data1), breezy.lsprof.Stats)
97
89
class TestBzrProfiler(tests.TestCase):
99
_test_needs_features = [LSProfFeature]
91
_test_needs_features = [features.lsprof_feature]
101
93
def test_start_call_stuff_stop(self):
102
profiler = bzrlib.lsprof.BzrProfiler()
94
profiler = breezy.lsprof.BzrProfiler()
111
103
lines = [str(data) for data in stats.data]
112
104
lines = [line for line in lines if 'a_function' in line]
113
105
self.assertLength(1, lines)
107
def test_block_0(self):
108
# When profiler_block is 0, reentrant profile requests fail.
109
self.overrideAttr(breezy.lsprof.BzrProfiler, 'profiler_block', 0)
112
profiler = breezy.lsprof.BzrProfiler()
113
self.assertRaises(errors.BzrError, profiler.start)
114
inner_calls.append(True)
115
breezy.lsprof.profile(inner)
116
self.assertLength(1, inner_calls)
118
def test_block_1(self):
119
# When profiler_block is 1, concurrent profiles serialise.
120
# This is tested by manually acquiring the profiler lock, then
121
# starting a thread that tries to profile, and releasing the lock.
122
# We know due to test_block_0 that two profiles at once hit the lock,
123
# so while this isn't perfect (we'd want a callback on the lock being
124
# entered to allow lockstep evaluation of the actions), its good enough
125
# to be confident regressions would be caught. Alternatively, if this
126
# is flakey, a fake Lock object can be used to trace the calls made.
129
calls.append('profiled')
131
breezy.lsprof.profile(profiled)
132
calls.append('after_profiled')
133
thread = threading.Thread(target=do_profile)
134
breezy.lsprof.BzrProfiler.profiler_lock.acquire()
139
breezy.lsprof.BzrProfiler.profiler_lock.release()
142
self.assertLength(2, calls)