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
4 # found in the LICENSE file.
13 BASE_PATH
= os
.path
.dirname(os
.path
.dirname(os
.path
.abspath(__file__
)))
14 sys
.path
.append(BASE_PATH
)
16 from lib
.bucket
import Bucket
17 from lib
.ordered_dict
import OrderedDict
18 from lib
.policy
import Policy
19 from lib
.symbol
import SymbolMappingCache
20 from lib
.symbol
import FUNCTION_SYMBOLS
, SOURCEFILE_SYMBOLS
, TYPEINFO_SYMBOLS
25 class SymbolMappingCacheTest(unittest
.TestCase
):
26 class MockBucketSet(object):
27 def __init__(self
, addresses
):
28 self
._addresses
= addresses
30 def iter_addresses(self
, symbol_type
): # pylint: disable=W0613
31 for address
in self
._addresses
:
34 class MockSymbolFinder(object):
35 def __init__(self
, mapping
):
36 self
._mapping
= mapping
38 def find(self
, address_list
):
39 result
= OrderedDict()
40 for address
in address_list
:
41 result
[address
] = self
._mapping
[address
]
44 _TEST_FUNCTION_CACHE
= textwrap
.dedent("""\
46 7fc33eebcaa4 __gnu_cxx::new_allocator::allocate
47 7fc33ef69242 void DispatchToMethod
50 _EXPECTED_TEST_FUNCTION_CACHE
= textwrap
.dedent("""\
52 7fc33eebcaa4 __gnu_cxx::new_allocator::allocate
53 7fc33ef69242 void DispatchToMethod
55 7fc33ef7bc3e std::map::operator[]
56 7fc34411f9d5 WTF::RefCounted::operator new
59 _TEST_FUNCTION_ADDRESS_LIST1
= [
60 0x1, 0x7fc33eebcaa4, 0x7fc33ef69242]
62 _TEST_FUNCTION_ADDRESS_LIST2
= [
63 0x1, 0x2, 0x7fc33eebcaa4, 0x7fc33ef69242, 0x7fc33ef7bc3e, 0x7fc34411f9d5]
65 _TEST_FUNCTION_DICT
= {
66 0x1: '0x0000000000000001',
67 0x2: '0x0000000000000002',
68 0x7fc33eebcaa4: '__gnu_cxx::new_allocator::allocate',
69 0x7fc33ef69242: 'void DispatchToMethod',
70 0x7fc33ef7bc3e: 'std::map::operator[]',
71 0x7fc34411f9d5: 'WTF::RefCounted::operator new',
74 def test_update(self
):
75 symbol_mapping_cache
= SymbolMappingCache()
76 cache_f
= cStringIO
.StringIO()
77 cache_f
.write(self
._TEST
_FUNCTION
_CACHE
)
79 # No update from self._TEST_FUNCTION_CACHE
80 symbol_mapping_cache
.update(
82 self
.MockBucketSet(self
._TEST
_FUNCTION
_ADDRESS
_LIST
1),
83 self
.MockSymbolFinder(self
._TEST
_FUNCTION
_DICT
), cache_f
)
84 for address
in self
._TEST
_FUNCTION
_ADDRESS
_LIST
1:
85 self
.assertEqual(self
._TEST
_FUNCTION
_DICT
[address
],
86 symbol_mapping_cache
.lookup(FUNCTION_SYMBOLS
, address
))
87 self
.assertEqual(self
._TEST
_FUNCTION
_CACHE
, cache_f
.getvalue())
89 # Update to self._TEST_FUNCTION_ADDRESS_LIST2
90 symbol_mapping_cache
.update(
92 self
.MockBucketSet(self
._TEST
_FUNCTION
_ADDRESS
_LIST
2),
93 self
.MockSymbolFinder(self
._TEST
_FUNCTION
_DICT
), cache_f
)
94 for address
in self
._TEST
_FUNCTION
_ADDRESS
_LIST
2:
95 self
.assertEqual(self
._TEST
_FUNCTION
_DICT
[address
],
96 symbol_mapping_cache
.lookup(FUNCTION_SYMBOLS
, address
))
97 self
.assertEqual(self
._EXPECTED
_TEST
_FUNCTION
_CACHE
, cache_f
.getvalue())
100 class PolicyTest(unittest
.TestCase
):
101 class MockSymbolMappingCache(object):
103 self
._symbol
_caches
= {
104 FUNCTION_SYMBOLS
: {},
105 SOURCEFILE_SYMBOLS
: {},
106 TYPEINFO_SYMBOLS
: {},
109 def add(self
, symbol_type
, address
, symbol
):
110 self
._symbol
_caches
[symbol_type
][address
] = symbol
112 def lookup(self
, symbol_type
, address
):
113 symbol
= self
._symbol
_caches
[symbol_type
].get(address
)
114 return symbol
if symbol
else '0x%016x' % address
116 _TEST_POLICY
= textwrap
.dedent("""\
129 "stacktrace": "optional",
130 "allocator": "optional"
134 "stacktrace": ".*v8::.*",
139 "stacktrace": ".*v8::.*",
140 "allocator": "malloc"
143 "name": "malloc-WebKit",
144 "stacktrace": ".*WebKit::.*",
145 "allocator": "malloc"
148 "name": "mmap-catch-all",
153 "name": "malloc-catch-all",
155 "allocator": "malloc"
158 "version": "POLICY_DEEP_3"
163 policy
= Policy
.parse(cStringIO
.StringIO(self
._TEST
_POLICY
), 'json')
164 self
.assertTrue(policy
)
165 self
.assertEqual('POLICY_DEEP_3', policy
.version
)
168 policy
= Policy
.parse(cStringIO
.StringIO(self
._TEST
_POLICY
), 'json')
169 self
.assertTrue(policy
)
171 symbol_mapping_cache
= self
.MockSymbolMappingCache()
172 symbol_mapping_cache
.add(FUNCTION_SYMBOLS
, 0x1212, 'v8::create')
173 symbol_mapping_cache
.add(FUNCTION_SYMBOLS
, 0x1381, 'WebKit::create')
175 bucket1
= Bucket([0x1212, 0x013], 'malloc', 0x29492, '_Z')
176 bucket1
.symbolize(symbol_mapping_cache
)
177 bucket2
= Bucket([0x18242, 0x1381], 'malloc', 0x9492, '_Z')
178 bucket2
.symbolize(symbol_mapping_cache
)
179 bucket3
= Bucket([0x18242, 0x181], 'malloc', 0x949, '_Z')
180 bucket3
.symbolize(symbol_mapping_cache
)
182 self
.assertEqual('malloc-v8', policy
.find_malloc(bucket1
))
183 self
.assertEqual('malloc-WebKit', policy
.find_malloc(bucket2
))
184 self
.assertEqual('malloc-catch-all', policy
.find_malloc(bucket3
))
187 class BucketsCommandTest(unittest
.TestCase
):
189 BUCKETS_PATH
= os
.path
.join(BASE_PATH
, 'tests', 'output', 'buckets')
190 with
open(BUCKETS_PATH
) as output_f
:
191 expected
= output_f
.read()
193 out
= cStringIO
.StringIO()
195 HEAP_PATH
= os
.path
.join(BASE_PATH
, 'tests', 'data', 'heap.01234.0001.heap')
196 subcommand
= subcommands
.BucketsCommand()
197 returncode
= subcommand
.do(['buckets', HEAP_PATH
], out
)
198 self
.assertEqual(0, returncode
)
199 self
.assertEqual(expected
, out
.getvalue())
202 class UploadCommandTest(unittest
.TestCase
):
204 MOCK_GSUTIL_PATH
= os
.path
.join(BASE_PATH
, 'tests', 'mock_gsutil.py')
205 HEAP_PATH
= os
.path
.join(BASE_PATH
, 'tests', 'data', 'heap.01234.0001.heap')
206 subcommand
= subcommands
.UploadCommand()
207 returncode
= subcommand
.do([
212 'gs://test-storage/'])
213 self
.assertEqual(0, returncode
)
216 if __name__
== '__main__':
218 level
=logging
.DEBUG
if '-v' in sys
.argv
else logging
.ERROR
,
219 format
='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s')