blob: 692960e418802ad2947790f6644fcec0b204460d [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import glob
import os
import sys
import unittest
import linker_map_parser
import test_util
_SCRIPT_DIR = os.path.dirname(__file__)
_TEST_DATA_DIR = os.path.join(_SCRIPT_DIR, 'testdata', 'linker_map_parser')
_TEST_MAP_PATH = os.path.join(_TEST_DATA_DIR, 'test_lld-lto_v1.map')
def _CompareWithGolden(name=None):
def real_decorator(func):
basename = name
if not basename:
basename = func.__name__.replace('test_', '')
golden_path = os.path.join(_TEST_DATA_DIR, basename + '.golden')
def inner(self):
actual_lines = func(self)
test_util.Golden.CheckOrUpdate(golden_path, actual_lines)
return inner
return real_decorator
def _ReadMapFile(map_file):
ret = []
with open(map_file, 'r') as f:
for line in f:
# Strip blank lines and comments.
stripped_line = line.lstrip()
if not stripped_line or stripped_line.startswith('#'):
continue
ret.append(line)
return ret
class LinkerMapParserTest(unittest.TestCase):
@_CompareWithGolden()
def test_Parser(self):
ret = []
map_file = _ReadMapFile(_TEST_MAP_PATH)
linker_name = linker_map_parser.DetectLinkerNameFromMapFile(iter(map_file))
section_sizes, raw_symbols = (
linker_map_parser.MapFileParser().Parse(linker_name, iter(map_file)))
ret.append('******** section_sizes ********')
for k, v in sorted(section_sizes.iteritems()):
ret.append('%-24s %d' % (k, v))
ret.append('')
ret.append('******** raw_symbols ********')
for sym in raw_symbols:
ret.append(repr(sym))
return ret
def test_ParseArmAnnotations(self):
fun = linker_map_parser.MapFileParserLld.ParseArmAnnotations
# Annotations.
self.assertEquals((True, False), fun('$a'))
self.assertEquals((True, False), fun('$a.0'))
self.assertEquals((True, False), fun('$a.137'))
self.assertEquals((True, True), fun('$t'))
self.assertEquals((True, True), fun('$t.42'))
self.assertEquals((True, None), fun('$d'))
self.assertEquals((True, None), fun('$d.7'))
# Annotations that should not appear, but get handled anyway.
self.assertEquals((True, False), fun('$a.'))
self.assertEquals((True, True), fun('$t.'))
self.assertEquals((True, None), fun('$d.'))
self.assertEquals((True, None), fun('$$.'))
# Non-annotations.
self.assertEquals((False, None), fun('$_21::invoke'))
self.assertEquals((False, None), fun('$aa'))
self.assertEquals((False, None), fun('$tt.'))
self.assertEquals((False, None), fun('$'))
self.assertEquals((False, None), fun(''))
self.assertEquals((False, None), fun('void foo()'))
self.assertEquals((False, None), fun('OUTLINED_FUNCTION_'))
self.assertEquals((False, None), fun('abc'))
@_CompareWithGolden()
def test_Tokenize(self):
ret = []
map_file = _ReadMapFile(_TEST_MAP_PATH)
linker_name = linker_map_parser.DetectLinkerNameFromMapFile(iter(map_file))
parser = linker_map_parser.MapFileParserLld(linker_name)
tokenizer = parser.Tokenize(iter(map_file))
for (_, address, size, level, span, tok) in tokenizer:
ret.append('%8X %8X (%d) %s %s' % (address, size, level, '-' * 8 if
span is None else '%8X' % span, tok))
return ret
def main():
argv = sys.argv
if len(argv) > 1 and argv[1] == '--update':
argv.pop(0)
test_util.Golden.EnableUpdate()
for f in glob.glob(os.path.join(_TEST_DATA_DIR, '*.golden')):
os.unlink(f)
unittest.main(argv=argv, verbosity=2)
if __name__ == '__main__':
main()