def setUp(self): self.cc = collector.Collector() self.a = self.cc.add_symbol("a", "a", type=collector.TYPE_FUNCTION, stack_size=1) self.b = self.cc.add_symbol("b", "b", type=collector.TYPE_FUNCTION, stack_size=10) self.c = self.cc.add_symbol("c", "c", type=collector.TYPE_FUNCTION, stack_size=100) self.d = self.cc.add_symbol("d", "d", type=collector.TYPE_FUNCTION, stack_size=1000) self.e = self.cc.add_symbol("e", "e", type=collector.TYPE_FUNCTION, stack_size=10000) self.f = self.cc.add_symbol("f", "f", type=collector.TYPE_FUNCTION) self.cc.enhance_call_tree() self.cc.add_function_call(self.a, self.b) self.cc.add_function_call(self.a, self.c) self.cc.add_function_call(self.b, self.a) self.cc.add_function_call(self.c, self.b) self.cc.add_function_call(self.c, self.d) self.cc.add_function_call(self.d, self.e) self.cc.add_function_call(self.d, self.f) self.h = BacktraceHelper(self.cc)
def dispatch_request(self, symbol_name=None): if request.method == "POST": helper = BacktraceHelper(self.collector) snippet = request.form["snippet"] self.template_vars["snippet"] = snippet self.template_vars["functions"] = helper.derive_function_symbols(snippet) return self.render_template("rack.html.jinja", "rack")
def test_transform_known_symbols(self): r = BacktraceHelper(TestBacktraceHelper.FakeCollector([ "a", "c", "d", ])) def f(symbol): return symbol[collector.NAME] + symbol[collector.NAME] actual = r.transform_known_symbols("0 1 a b c d e f 0 2", f) self.assertEqual("0 1 aa b cc dd e f 0 2", actual)
def test_returns_known_symbols(self): r = BacktraceHelper(TestBacktraceHelper.FakeCollector([ "codepoint_get_horizontal_advance", "text_walk_lines", ])) actual = r.derive_function_symbols(""" fontinfo=0x200010ec <s_system_fonts_info_table+200>) 16 at ../src/fw/applib/graphics/text_resources.c:347 #4 0x08012220 in codepoint_get_horizontal_advance () 16 #5 0x08012602 in walk_line () 112 #6 0x080128d6 in text_walk_lines.constprop.8 () (inlined) """) self.assertEqual(["codepoint_get_horizontal_advance", "text_walk_lines"], [f[collector.NAME] for f in actual])
def test_transform_known_symbols(self): r = BacktraceHelper( TestBacktraceHelper.FakeCollector([ "a", "c", "d", ])) def f(symbol): return symbol[collector.NAME] + symbol[collector.NAME] actual = r.transform_known_symbols("0 1 a b c d e f 0 2", f) self.assertEqual("0 1 aa b cc dd e f 0 2", actual)
def symbols_filter(context, value): renderer = renderer_from_context(context) if renderer: helper = BacktraceHelper(renderer.collector) def make_links(s): name = s[collector.NAME] url = renderer.url_for_symbol_name(name, context) return '<a href="%s">%s</a>' % (url, name) if isinstance(value, markupsafe.Markup): value = value.__html__().unescape() return helper.transform_known_symbols(value, make_links) return value
def test_returns_known_symbols(self): r = BacktraceHelper( TestBacktraceHelper.FakeCollector([ "codepoint_get_horizontal_advance", "text_walk_lines", ])) actual = r.derive_function_symbols(""" fontinfo=0x200010ec <s_system_fonts_info_table+200>) 16 at ../src/fw/applib/graphics/text_resources.c:347 #4 0x08012220 in codepoint_get_horizontal_advance () 16 #5 0x08012602 in walk_line () 112 #6 0x080128d6 in text_walk_lines.constprop.8 () (inlined) """) self.assertEqual( ["codepoint_get_horizontal_advance", "text_walk_lines"], [f[collector.NAME] for f in actual])
class Builder: def __init__(self, collector, src_root): self.files = {} self.collector = collector self.backtrace_helper = BacktraceHelper(collector) self.src_root = src_root def store_file_time(self, path, store_empty=False): self.files[path] = 0 if store_empty else os.path.getmtime(path) def build(self): for f in self.files.keys(): self.store_file_time(f) self.collector.reset() self.collector.parse_elf(self.get_elf_path()) self.collector.enhance(self.src_root) self.collector.parse_su_dir(self.get_su_dir()) self.build_call_trees() def needs_build(self): return any([os.path.getmtime(f) > t for f,t in self.files.items()]) def build_if_needed(self): if self.needs_build(): self.build() @abc.abstractmethod def get_elf_path(self): pass @abc.abstractmethod def get_su_dir(self): pass def build_call_trees(self): for f in self.collector.all_functions(): self.backtrace_helper.deepest_callee_tree(f) self.backtrace_helper.deepest_caller_tree(f)
def setUp(self): self.cc = collector.Collector(None) self.a = self.cc.add_symbol("a", "a", type=collector.TYPE_FUNCTION, stack_size=1) self.b = self.cc.add_symbol("b", "b", type=collector.TYPE_FUNCTION, stack_size=10) self.c = self.cc.add_symbol("c", "c", type=collector.TYPE_FUNCTION, stack_size=100) self.d = self.cc.add_symbol("d", "d", type=collector.TYPE_FUNCTION, stack_size=1000) self.e = self.cc.add_symbol("e", "e", type=collector.TYPE_FUNCTION, stack_size=10000) self.f = self.cc.add_symbol("f", "f", type=collector.TYPE_FUNCTION) self.cc.enhance_call_tree() self.cc.add_function_call(self.a, self.b) self.cc.add_function_call(self.a, self.c) self.cc.add_function_call(self.b, self.a) self.cc.add_function_call(self.c, self.b) self.cc.add_function_call(self.c, self.d) self.cc.add_function_call(self.d, self.e) self.cc.add_function_call(self.d, self.f) self.h = BacktraceHelper(self.cc)
class TestBacktraceHelperTreeSizes(unittest.TestCase): def setUp(self): self.cc = collector.Collector(None) self.a = self.cc.add_symbol("a", "a", type=collector.TYPE_FUNCTION, stack_size=1) self.b = self.cc.add_symbol("b", "b", type=collector.TYPE_FUNCTION, stack_size=10) self.c = self.cc.add_symbol("c", "c", type=collector.TYPE_FUNCTION, stack_size=100) self.d = self.cc.add_symbol("d", "d", type=collector.TYPE_FUNCTION, stack_size=1000) self.e = self.cc.add_symbol("e", "e", type=collector.TYPE_FUNCTION, stack_size=10000) self.f = self.cc.add_symbol("f", "f", type=collector.TYPE_FUNCTION) self.cc.enhance_call_tree() self.cc.add_function_call(self.a, self.b) self.cc.add_function_call(self.a, self.c) self.cc.add_function_call(self.b, self.a) self.cc.add_function_call(self.c, self.b) self.cc.add_function_call(self.c, self.d) self.cc.add_function_call(self.d, self.e) self.cc.add_function_call(self.d, self.f) self.h = BacktraceHelper(self.cc) def test_leaf_with_stack(self): self.assertEqual((10000, [self.e]), self.h.deepest_callee_tree(self.e)) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.e) def test_leaf_without_stack(self): self.assertEqual((0, [self.f]), self.h.deepest_callee_tree(self.f)) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.f) def test_cached_value(self): self.f[collector.DEEPEST_CALLEE_TREE] = "cached" self.assertEqual("cached", self.h.deepest_callee_tree(self.f)) def test_non_leaf(self): self.assertEqual((11000, [self.d, self.e]), self.h.deepest_callee_tree(self.d)) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.f) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.e) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.d) def test_cycle_2(self): self.a[collector.CALLEES].remove(self.c) expected = (11, [self.a, self.b]) actual = self.h.deepest_callee_tree(self.a) self.assertEqual(expected, actual) expected = (10, [self.b]) actual = self.h.deepest_callee_tree(self.b) self.assertEqual(expected, actual) def test_cycle_3(self): self.c[collector.CALLEES].remove(self.d) self.assertEqual(111, self.h.deepest_callee_tree(self.a)[0]) self.assertEqual(10, self.h.deepest_callee_tree(self.b)[0]) self.assertEqual(110, self.h.deepest_callee_tree(self.c)[0]) def test_caller(self): self.d[collector.CALLERS] = [] self.assertEqual(1000, self.h.deepest_caller_tree(self.f)[0]) self.assertEqual(11000, self.h.deepest_caller_tree(self.e)[0]) def test_caller_cycle(self): self.assertEqual(1111, self.h.deepest_caller_tree(self.f)[0]) self.assertEqual(11111, self.h.deepest_caller_tree(self.e)[0])
def test_returns_empty_list(self): r = BacktraceHelper(None) self.assertEqual([], r.derive_function_symbols(""))
def __init__(self, collector, src_root): self.files = {} self.collector = collector self.backtrace_helper = BacktraceHelper(collector) self.src_root = src_root
class TestBacktraceHelperTreeSizes(unittest.TestCase): def setUp(self): self.cc = collector.Collector() self.a = self.cc.add_symbol("a", "a", type=collector.TYPE_FUNCTION, stack_size=1) self.b = self.cc.add_symbol("b", "b", type=collector.TYPE_FUNCTION, stack_size=10) self.c = self.cc.add_symbol("c", "c", type=collector.TYPE_FUNCTION, stack_size=100) self.d = self.cc.add_symbol("d", "d", type=collector.TYPE_FUNCTION, stack_size=1000) self.e = self.cc.add_symbol("e", "e", type=collector.TYPE_FUNCTION, stack_size=10000) self.f = self.cc.add_symbol("f", "f", type=collector.TYPE_FUNCTION) self.cc.enhance_call_tree() self.cc.add_function_call(self.a, self.b) self.cc.add_function_call(self.a, self.c) self.cc.add_function_call(self.b, self.a) self.cc.add_function_call(self.c, self.b) self.cc.add_function_call(self.c, self.d) self.cc.add_function_call(self.d, self.e) self.cc.add_function_call(self.d, self.f) self.h = BacktraceHelper(self.cc) def test_leaf_with_stack(self): self.assertEqual((10000, [self.e]), self.h.deepest_callee_tree(self.e)) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.e) def test_leaf_without_stack(self): self.assertEqual((0, [self.f]), self.h.deepest_callee_tree(self.f)) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.f) def test_cached_value(self): self.f[collector.DEEPEST_CALLEE_TREE] = "cached" self.assertEqual("cached", self.h.deepest_callee_tree(self.f)) def test_non_leaf(self): self.assertEqual((11000, [self.d, self.e]), self.h.deepest_callee_tree(self.d)) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.f) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.e) self.assertIn(collector.DEEPEST_CALLEE_TREE, self.d) def test_cycle_2(self): self.a[collector.CALLEES].remove(self.c) expected = (11, [self.a, self.b]) actual = self.h.deepest_callee_tree(self.a) self.assertEqual(expected, actual) expected = (10, [self.b]) actual = self.h.deepest_callee_tree(self.b) self.assertEqual(expected, actual) def test_cycle_3(self): self.c[collector.CALLEES].remove(self.d) self.assertEqual(111, self.h.deepest_callee_tree(self.a)[0]) self.assertEqual(10, self.h.deepest_callee_tree(self.b)[0]) self.assertEqual(110, self.h.deepest_callee_tree(self.c)[0]) def test_caller(self): self.d[collector.CALLERS] = [] self.assertEqual(1000, self.h.deepest_caller_tree(self.f)[0]) self.assertEqual(11000, self.h.deepest_caller_tree(self.e)[0]) def test_caller_cycle(self): self.assertEqual(1111, self.h.deepest_caller_tree(self.f)[0]) self.assertEqual(11111, self.h.deepest_caller_tree(self.e)[0])