1 #!/usr/bin/env python 2 # 3 # Copyright 2013 The Chromium Authors. All rights reserved. 4 # Use of this source code is governed by a BSD-style license that can be 5 # found in the LICENSE file. 6 7 """Unittest for symbolize.py. 8 9 This test uses test libraries generated by the Android g++ toolchain. 10 11 Should things break you can recreate the libraries and get the updated 12 addresses and demangled names by running the following: 13 cd test/symbolize/ 14 make 15 nm -gC *.so 16 """ 17 18 import sys 19 import StringIO 20 import unittest 21 22 import symbolize 23 24 LIB_A_PATH = '/build/android/tests/symbolize/liba.so' 25 LIB_B_PATH = '/build/android/tests/symbolize/libb.so' 26 27 def RunSymbolizer(text): 28 output = StringIO.StringIO() 29 s = symbolize.Symbolizer(output) 30 s.write(text) 31 return output.getvalue() 32 33 34 class SymbolizerUnittest(unittest.TestCase): 35 def testSingleLineNoMatch(self): 36 # Leading '#' is required. 37 expected = '00 0x00000000 ' + LIB_A_PATH + '+0x00000254\n' 38 self.assertEqual(expected, RunSymbolizer(expected)) 39 40 # Whitespace should be exactly one space. 41 expected = '#00 0x00000000 ' + LIB_A_PATH + '+0x00000254\n' 42 self.assertEqual(expected, RunSymbolizer(expected)) 43 expected = '#00 0x00000000 ' + LIB_A_PATH + '+0x00000254\n' 44 self.assertEqual(expected, RunSymbolizer(expected)) 45 46 # Decimal stack frame numbers are required. 47 expected = '#0a 0x00000000 ' + LIB_A_PATH + '+0x00000254\n' 48 self.assertEqual(expected, RunSymbolizer(expected)) 49 50 # Hexadecimal addresses are required. 51 expected = '#00 0xghijklmn ' + LIB_A_PATH + '+0x00000254\n' 52 self.assertEqual(expected, RunSymbolizer(expected)) 53 expected = '#00 0x00000000 ' + LIB_A_PATH + '+0xghijklmn\n' 54 self.assertEqual(expected, RunSymbolizer(expected)) 55 56 # Addresses must be exactly 8 characters. 57 expected = '#00 0x0000000 ' + LIB_A_PATH + '+0x00000254\n' 58 self.assertEqual(expected, RunSymbolizer(expected)) 59 expected = '#00 0x000000000 ' + LIB_A_PATH + '+0x00000254\n' 60 self.assertEqual(expected, RunSymbolizer(expected)) 61 62 expected = '#00 0x0000000 ' + LIB_A_PATH + '+0x0000254\n' 63 self.assertEqual(expected, RunSymbolizer(expected)) 64 expected = '#00 0x000000000 ' + LIB_A_PATH + '+0x000000254\n' 65 self.assertEqual(expected, RunSymbolizer(expected)) 66 67 # Addresses must be prefixed with '0x'. 68 expected = '#00 00000000 ' + LIB_A_PATH + '+0x00000254\n' 69 self.assertEqual(expected, RunSymbolizer(expected)) 70 expected = '#00 0x00000000 ' + LIB_A_PATH + '+00000254\n' 71 self.assertEqual(expected, RunSymbolizer(expected)) 72 73 # Library name is required. 74 expected = '#00 0x00000000\n' 75 self.assertEqual(expected, RunSymbolizer(expected)) 76 expected = '#00 0x00000000 +0x00000254\n' 77 self.assertEqual(expected, RunSymbolizer(expected)) 78 79 # Library name must be followed by offset with no spaces around '+'. 80 expected = '#00 0x00000000 ' + LIB_A_PATH + ' +0x00000254\n' 81 self.assertEqual(expected, RunSymbolizer(expected)) 82 expected = '#00 0x00000000 ' + LIB_A_PATH + '+ 0x00000254\n' 83 self.assertEqual(expected, RunSymbolizer(expected)) 84 expected = '#00 0x00000000 ' + LIB_A_PATH + ' 0x00000254\n' 85 self.assertEqual(expected, RunSymbolizer(expected)) 86 expected = '#00 0x00000000 ' + LIB_A_PATH + '+\n' 87 self.assertEqual(expected, RunSymbolizer(expected)) 88 89 def testSingleLine(self): 90 text = '#00 0x00000000 ' + LIB_A_PATH + '+0x00000254\n' 91 expected = '#00 0x00000000 A::Bar(char const*)\n' 92 actual = RunSymbolizer(text) 93 self.assertEqual(expected, actual) 94 95 def testSingleLineWithSurroundingText(self): 96 text = 'LEFT #00 0x00000000 ' + LIB_A_PATH + '+0x00000254 RIGHT\n' 97 expected = 'LEFT #00 0x00000000 A::Bar(char const*) RIGHT\n' 98 actual = RunSymbolizer(text) 99 self.assertEqual(expected, actual) 100 101 def testMultipleLinesSameLibrary(self): 102 text = '#00 0x00000000 ' + LIB_A_PATH + '+0x00000254\n' 103 text += '#01 0x00000000 ' + LIB_A_PATH + '+0x00000234\n' 104 expected = '#00 0x00000000 A::Bar(char const*)\n' 105 expected += '#01 0x00000000 A::Foo(int)\n' 106 actual = RunSymbolizer(text) 107 self.assertEqual(expected, actual) 108 109 def testMultipleLinesDifferentLibrary(self): 110 text = '#00 0x00000000 ' + LIB_A_PATH + '+0x00000254\n' 111 text += '#01 0x00000000 ' + LIB_B_PATH + '+0x00000234\n' 112 expected = '#00 0x00000000 A::Bar(char const*)\n' 113 expected += '#01 0x00000000 B::Baz(float)\n' 114 actual = RunSymbolizer(text) 115 self.assertEqual(expected, actual) 116 117 def testMultipleLinesWithSurroundingTextEverywhere(self): 118 text = 'TOP\n' 119 text += 'LEFT #00 0x00000000 ' + LIB_A_PATH + '+0x00000254 RIGHT\n' 120 text += 'LEFT #01 0x00000000 ' + LIB_B_PATH + '+0x00000234 RIGHT\n' 121 text += 'BOTTOM\n' 122 expected = 'TOP\n' 123 expected += 'LEFT #00 0x00000000 A::Bar(char const*) RIGHT\n' 124 expected += 'LEFT #01 0x00000000 B::Baz(float) RIGHT\n' 125 expected += 'BOTTOM\n' 126 actual = RunSymbolizer(text) 127 self.assertEqual(expected, actual) 128 129 130 if __name__ == '__main__': 131 unittest.main() 132