示例#1
0
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)
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])