2 # Copyright 2014 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.
12 sys
.path
.insert(0, os
.path
.dirname(__file__
))
17 _MOCK_A2L_PATH
= os
.path
.join(os
.path
.dirname(mock_addr2line
.__file
__),
19 _INCOMPLETE_MOCK_ADDR
= 1024 * 1024
20 _UNKNOWN_MOCK_ADDR
= 2 * 1024 * 1024
21 _INLINE_MOCK_ADDR
= 3 * 1024 * 1024
24 class ELFSymbolizerTest(unittest
.TestCase
):
26 self
._callback
= functools
.partial(
27 ELFSymbolizerTest
._SymbolizeCallback
, self
)
28 self
._resolved
_addresses
= set()
29 # Mute warnings, we expect them due to the crash/hang tests.
30 logging
.getLogger().setLevel(logging
.ERROR
)
32 def testParallelism1(self
):
33 self
._RunTest
(max_concurrent_jobs
=1, num_symbols
=100)
35 def testParallelism4(self
):
36 self
._RunTest
(max_concurrent_jobs
=4, num_symbols
=100)
38 def testParallelism8(self
):
39 self
._RunTest
(max_concurrent_jobs
=8, num_symbols
=100)
42 os
.environ
['MOCK_A2L_CRASH_EVERY'] = '99'
43 self
._RunTest
(max_concurrent_jobs
=1, num_symbols
=100)
44 os
.environ
['MOCK_A2L_CRASH_EVERY'] = '0'
47 os
.environ
['MOCK_A2L_HANG_EVERY'] = '99'
48 self
._RunTest
(max_concurrent_jobs
=1, num_symbols
=100)
49 os
.environ
['MOCK_A2L_HANG_EVERY'] = '0'
51 def testInlines(self
):
52 """Stimulate the inline processing logic."""
53 symbolizer
= elf_symbolizer
.ELFSymbolizer(
54 elf_file_path
='/path/doesnt/matter/mock_lib1.so',
55 addr2line_path
=_MOCK_A2L_PATH
,
56 callback
=self
._callback
,
58 max_concurrent_jobs
=4)
60 for addr
in xrange(1000):
64 # First 100 addresses with inlines.
66 addr
+= _INLINE_MOCK_ADDR
69 # Followed by 100 without inlines.
73 # Followed by 100 interleaved inlines and not inlines.
76 addr
+= _INLINE_MOCK_ADDR
79 # Followed by 100 interleaved inlines and unknonwn.
82 addr
+= _INLINE_MOCK_ADDR
85 addr
+= _UNKNOWN_MOCK_ADDR
88 exp_name
= 'mock_sym_for_addr_%d' % addr
if not exp_unknown
else None
89 exp_source_path
= 'mock_src/mock_lib1.so.c' if not exp_unknown
else None
90 exp_source_line
= addr
if not exp_unknown
else None
91 cb_arg
= (addr
, exp_name
, exp_source_path
, exp_source_line
, exp_inline
)
92 symbolizer
.SymbolizeAsync(addr
, cb_arg
)
96 def testIncompleteSyminfo(self
):
97 """Stimulate the symbol-not-resolved logic."""
98 symbolizer
= elf_symbolizer
.ELFSymbolizer(
99 elf_file_path
='/path/doesnt/matter/mock_lib1.so',
100 addr2line_path
=_MOCK_A2L_PATH
,
101 callback
=self
._callback
,
102 max_concurrent_jobs
=1)
104 # Test symbols with valid name but incomplete path.
105 addr
= _INCOMPLETE_MOCK_ADDR
106 exp_name
= 'mock_sym_for_addr_%d' % addr
107 exp_source_path
= None
108 exp_source_line
= None
109 cb_arg
= (addr
, exp_name
, exp_source_path
, exp_source_line
, False)
110 symbolizer
.SymbolizeAsync(addr
, cb_arg
)
112 # Test symbols with no name or sym info.
113 addr
= _UNKNOWN_MOCK_ADDR
115 exp_source_path
= None
116 exp_source_line
= None
117 cb_arg
= (addr
, exp_name
, exp_source_path
, exp_source_line
, False)
118 symbolizer
.SymbolizeAsync(addr
, cb_arg
)
122 def _RunTest(self
, max_concurrent_jobs
, num_symbols
):
123 symbolizer
= elf_symbolizer
.ELFSymbolizer(
124 elf_file_path
='/path/doesnt/matter/mock_lib1.so',
125 addr2line_path
=_MOCK_A2L_PATH
,
126 callback
=self
._callback
,
127 max_concurrent_jobs
=max_concurrent_jobs
,
128 addr2line_timeout
=0.5)
130 for addr
in xrange(num_symbols
):
131 exp_name
= 'mock_sym_for_addr_%d' % addr
132 exp_source_path
= 'mock_src/mock_lib1.so.c'
133 exp_source_line
= addr
134 cb_arg
= (addr
, exp_name
, exp_source_path
, exp_source_line
, False)
135 symbolizer
.SymbolizeAsync(addr
, cb_arg
)
139 # Check that all the expected callbacks have been received.
140 for addr
in xrange(num_symbols
):
141 self
.assertIn(addr
, self
._resolved
_addresses
)
142 self
._resolved
_addresses
.remove(addr
)
144 # Check for unexpected callbacks.
145 self
.assertEqual(len(self
._resolved
_addresses
), 0)
147 def _SymbolizeCallback(self
, sym_info
, cb_arg
):
148 self
.assertTrue(isinstance(sym_info
, elf_symbolizer
.ELFSymbolInfo
))
149 self
.assertTrue(isinstance(cb_arg
, tuple))
150 self
.assertEqual(len(cb_arg
), 5)
152 # Unpack expectations from the callback extra argument.
153 (addr
, exp_name
, exp_source_path
, exp_source_line
, exp_inlines
) = cb_arg
155 self
.assertIsNone(sym_info
.name
)
157 self
.assertTrue(sym_info
.name
.startswith(exp_name
))
158 self
.assertEqual(sym_info
.source_path
, exp_source_path
)
159 self
.assertEqual(sym_info
.source_line
, exp_source_line
)
162 self
.assertEqual(sym_info
.name
, exp_name
+ '_inner')
163 self
.assertEqual(sym_info
.inlined_by
.name
, exp_name
+ '_middle')
164 self
.assertEqual(sym_info
.inlined_by
.inlined_by
.name
,
167 # Check against duplicate callbacks.
168 self
.assertNotIn(addr
, self
._resolved
_addresses
)
169 self
._resolved
_addresses
.add(addr
)
172 if __name__
== '__main__':