OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import cStringIO | 6 import cStringIO |
7 import logging | 7 import logging |
8 import os | 8 import os |
9 import sys | 9 import sys |
| 10 import textwrap |
10 import unittest | 11 import unittest |
11 | 12 |
12 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | 13 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
13 sys.path.insert(0, ROOT_DIR) | 14 sys.path.insert(0, ROOT_DIR) |
14 | 15 |
15 import dmprof | 16 import dmprof |
16 from dmprof import FUNCTION_ADDRESS, TYPEINFO_ADDRESS | 17 from dmprof import FUNCTION_ADDRESS, TYPEINFO_ADDRESS |
17 | 18 |
18 | 19 |
19 class MockSymbolCache(object): | 20 class SymbolMappingCacheTest(unittest.TestCase): |
20 def __init__(self): | 21 class MockBucketSet(object): |
21 self._symbol_caches = {FUNCTION_ADDRESS: {}, TYPEINFO_ADDRESS: {}} | 22 def __init__(self, addresses): |
| 23 self._addresses = addresses |
22 | 24 |
23 def add(self, address_type, address, symbol): | 25 def iter_addresses(self, address_type): # pylint: disable=W0613 |
24 self._symbol_caches[address_type][address] = symbol | 26 for address in self._addresses: |
| 27 yield address |
25 | 28 |
26 def lookup(self, address_type, address): | 29 class MockSymbolFinder(object): |
27 symbol = self._symbol_caches[address_type].get(address) | 30 def __init__(self, mapping): |
28 return symbol if symbol else '0x%016x' % address | 31 self._mapping = mapping |
| 32 |
| 33 def find(self, address_list): |
| 34 return [self._mapping[address] for address in address_list] |
| 35 |
| 36 _TEST_FUNCTION_CACHE = textwrap.dedent("""\ |
| 37 1 0x0000000000000001 |
| 38 7fc33eebcaa4 __gnu_cxx::new_allocator::allocate |
| 39 7fc33ef69242 void DispatchToMethod |
| 40 """) |
| 41 |
| 42 _EXPECTED_TEST_FUNCTION_CACHE = textwrap.dedent("""\ |
| 43 1 0x0000000000000001 |
| 44 7fc33eebcaa4 __gnu_cxx::new_allocator::allocate |
| 45 7fc33ef69242 void DispatchToMethod |
| 46 2 0x0000000000000002 |
| 47 7fc33ef7bc3e std::map::operator[] |
| 48 7fc34411f9d5 WTF::RefCounted::operator new |
| 49 """) |
| 50 |
| 51 _TEST_FUNCTION_ADDRESS_LIST1 = [ |
| 52 0x1, 0x7fc33eebcaa4, 0x7fc33ef69242] |
| 53 |
| 54 _TEST_FUNCTION_ADDRESS_LIST2 = [ |
| 55 0x1, 0x2, 0x7fc33eebcaa4, 0x7fc33ef69242, 0x7fc33ef7bc3e, 0x7fc34411f9d5] |
| 56 |
| 57 _TEST_FUNCTION_DICT = { |
| 58 0x1: '0x0000000000000001', |
| 59 0x2: '0x0000000000000002', |
| 60 0x7fc33eebcaa4: '__gnu_cxx::new_allocator::allocate', |
| 61 0x7fc33ef69242: 'void DispatchToMethod', |
| 62 0x7fc33ef7bc3e: 'std::map::operator[]', |
| 63 0x7fc34411f9d5: 'WTF::RefCounted::operator new', |
| 64 } |
| 65 |
| 66 def test_update(self): |
| 67 symbol_mapping_cache = dmprof.SymbolMappingCache() |
| 68 cache_f = cStringIO.StringIO() |
| 69 cache_f.write(self._TEST_FUNCTION_CACHE) |
| 70 |
| 71 # No update from self._TEST_FUNCTION_CACHE |
| 72 symbol_mapping_cache.update( |
| 73 FUNCTION_ADDRESS, |
| 74 self.MockBucketSet(self._TEST_FUNCTION_ADDRESS_LIST1), |
| 75 self.MockSymbolFinder(self._TEST_FUNCTION_DICT), cache_f) |
| 76 for address in self._TEST_FUNCTION_ADDRESS_LIST1: |
| 77 self.assertEqual(self._TEST_FUNCTION_DICT[address], |
| 78 symbol_mapping_cache.lookup(FUNCTION_ADDRESS, address)) |
| 79 self.assertEqual(self._TEST_FUNCTION_CACHE, cache_f.getvalue()) |
| 80 |
| 81 # Update to self._TEST_FUNCTION_ADDRESS_LIST2 |
| 82 symbol_mapping_cache.update( |
| 83 FUNCTION_ADDRESS, |
| 84 self.MockBucketSet(self._TEST_FUNCTION_ADDRESS_LIST2), |
| 85 self.MockSymbolFinder(self._TEST_FUNCTION_DICT), cache_f) |
| 86 for address in self._TEST_FUNCTION_ADDRESS_LIST2: |
| 87 self.assertEqual(self._TEST_FUNCTION_DICT[address], |
| 88 symbol_mapping_cache.lookup(FUNCTION_ADDRESS, address)) |
| 89 self.assertEqual(self._EXPECTED_TEST_FUNCTION_CACHE, cache_f.getvalue()) |
29 | 90 |
30 | 91 |
31 class PolicyTest(unittest.TestCase): | 92 class PolicyTest(unittest.TestCase): |
32 _TEST_POLICY = """{ | 93 class MockSymbolMappingCache(object): |
33 "components": [ | 94 def __init__(self): |
34 "second", | 95 self._symbol_caches = {FUNCTION_ADDRESS: {}, TYPEINFO_ADDRESS: {}} |
35 "mmap-v8", | 96 |
36 "malloc-v8", | 97 def add(self, address_type, address, symbol): |
37 "malloc-WebKit", | 98 self._symbol_caches[address_type][address] = symbol |
38 "mmap-catch-all", | 99 |
39 "malloc-catch-all" | 100 def lookup(self, address_type, address): |
40 ], | 101 symbol = self._symbol_caches[address_type].get(address) |
41 "rules": [ | 102 return symbol if symbol else '0x%016x' % address |
42 { | 103 |
43 "name": "second", | 104 _TEST_POLICY = textwrap.dedent("""\ |
44 "stacktrace": "optional", | 105 { |
45 "allocator": "optional" | 106 "components": [ |
46 }, | 107 "second", |
47 { | 108 "mmap-v8", |
48 "name": "mmap-v8", | 109 "malloc-v8", |
49 "stacktrace": ".*v8::.*", | 110 "malloc-WebKit", |
50 "allocator": "mmap" | 111 "mmap-catch-all", |
51 }, | 112 "malloc-catch-all" |
52 { | 113 ], |
53 "name": "malloc-v8", | 114 "rules": [ |
54 "stacktrace": ".*v8::.*", | 115 { |
55 "allocator": "malloc" | 116 "name": "second", |
56 }, | 117 "stacktrace": "optional", |
57 { | 118 "allocator": "optional" |
58 "name": "malloc-WebKit", | 119 }, |
59 "stacktrace": ".*WebKit::.*", | 120 { |
60 "allocator": "malloc" | 121 "name": "mmap-v8", |
61 }, | 122 "stacktrace": ".*v8::.*", |
62 { | 123 "allocator": "mmap" |
63 "name": "mmap-catch-all", | 124 }, |
64 "stacktrace": ".*", | 125 { |
65 "allocator": "mmap" | 126 "name": "malloc-v8", |
66 }, | 127 "stacktrace": ".*v8::.*", |
67 { | 128 "allocator": "malloc" |
68 "name": "malloc-catch-all", | 129 }, |
69 "stacktrace": ".*", | 130 { |
70 "allocator": "malloc" | 131 "name": "malloc-WebKit", |
71 } | 132 "stacktrace": ".*WebKit::.*", |
72 ], | 133 "allocator": "malloc" |
73 "version": "POLICY_DEEP_3" | 134 }, |
74 } | 135 { |
75 """ | 136 "name": "mmap-catch-all", |
| 137 "stacktrace": ".*", |
| 138 "allocator": "mmap" |
| 139 }, |
| 140 { |
| 141 "name": "malloc-catch-all", |
| 142 "stacktrace": ".*", |
| 143 "allocator": "malloc" |
| 144 } |
| 145 ], |
| 146 "version": "POLICY_DEEP_3" |
| 147 } |
| 148 """) |
76 | 149 |
77 def test_load(self): | 150 def test_load(self): |
78 policy = dmprof.Policy.parse(cStringIO.StringIO(self._TEST_POLICY), 'json') | 151 policy = dmprof.Policy.parse(cStringIO.StringIO(self._TEST_POLICY), 'json') |
79 self.assertTrue(policy) | 152 self.assertTrue(policy) |
80 self.assertEqual(policy.version, 'POLICY_DEEP_3') | 153 self.assertEqual('POLICY_DEEP_3', policy.version) |
81 | 154 |
82 def test_find(self): | 155 def test_find(self): |
83 policy = dmprof.Policy.parse(cStringIO.StringIO(self._TEST_POLICY), 'json') | 156 policy = dmprof.Policy.parse(cStringIO.StringIO(self._TEST_POLICY), 'json') |
84 self.assertTrue(policy) | 157 self.assertTrue(policy) |
85 | 158 |
86 symbol_cache = MockSymbolCache() | 159 symbol_mapping_cache = self.MockSymbolMappingCache() |
87 symbol_cache.add(FUNCTION_ADDRESS, 0x1212, 'v8::create') | 160 symbol_mapping_cache.add(FUNCTION_ADDRESS, 0x1212, 'v8::create') |
88 symbol_cache.add(FUNCTION_ADDRESS, 0x1381, 'WebKit::create') | 161 symbol_mapping_cache.add(FUNCTION_ADDRESS, 0x1381, 'WebKit::create') |
89 | 162 |
90 bucket1 = dmprof.Bucket([0x1212, 0x013], False, 0x29492, '_Z') | 163 bucket1 = dmprof.Bucket([0x1212, 0x013], False, 0x29492, '_Z') |
91 bucket1.symbolize(symbol_cache) | 164 bucket1.symbolize(symbol_mapping_cache) |
92 bucket2 = dmprof.Bucket([0x18242, 0x1381], False, 0x9492, '_Z') | 165 bucket2 = dmprof.Bucket([0x18242, 0x1381], False, 0x9492, '_Z') |
93 bucket2.symbolize(symbol_cache) | 166 bucket2.symbolize(symbol_mapping_cache) |
94 bucket3 = dmprof.Bucket([0x18242, 0x181], False, 0x949, '_Z') | 167 bucket3 = dmprof.Bucket([0x18242, 0x181], False, 0x949, '_Z') |
95 bucket3.symbolize(symbol_cache) | 168 bucket3.symbolize(symbol_mapping_cache) |
96 | 169 |
97 self.assertEqual(policy.find(bucket1), 'malloc-v8') | 170 self.assertEqual('malloc-v8', policy.find(bucket1)) |
98 self.assertEqual(policy.find(bucket2), 'malloc-WebKit') | 171 self.assertEqual('malloc-WebKit', policy.find(bucket2)) |
99 self.assertEqual(policy.find(bucket3), 'malloc-catch-all') | 172 self.assertEqual('malloc-catch-all', policy.find(bucket3)) |
100 | 173 |
101 | 174 |
102 if __name__ == '__main__': | 175 if __name__ == '__main__': |
103 logging.basicConfig( | 176 logging.basicConfig( |
104 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR, | 177 level=logging.DEBUG if '-v' in sys.argv else logging.ERROR, |
105 format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') | 178 format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s') |
106 unittest.main() | 179 unittest.main() |
OLD | NEW |