File: linker_map_parser_test.py

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (126 lines) | stat: -rwxr-xr-x 3,964 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env python3
# Copyright 2018 The Chromium Authors
# 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')
_TEST_CFI_MAP_PATH = os.path.join(_TEST_DATA_DIR, 'test_lld-lto_v1_cfi.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(path):
  with open(path, '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
      yield line


def _RenderSectionSizesAndRawSymbols(section_sizes, raw_symbols):
  ret = []
  ret.append('******** section_sizes ********')
  for k, (address, size) in sorted(section_sizes.items()):
    address_text = '@%x' % address
    ret.append('%-24s %-9s %d' % (k, address_text, size))
  ret.append('')
  ret.append('******** raw_symbols ********')
  for sym in raw_symbols:
    ret.append(repr(sym))
  return ret


class LinkerMapParserTest(unittest.TestCase):

  @_CompareWithGolden()
  def test_Parser(self):
    lines = _ReadMapFile(_TEST_MAP_PATH)
    section_sizes, raw_symbols, _ = linker_map_parser.ParseLines(lines)
    return _RenderSectionSizesAndRawSymbols(section_sizes, raw_symbols)

  @_CompareWithGolden()
  def test_ParserCfi(self):
    lines = _ReadMapFile(_TEST_CFI_MAP_PATH)
    section_sizes, raw_symbols, _ = linker_map_parser.ParseLines(lines)
    return _RenderSectionSizesAndRawSymbols(section_sizes, raw_symbols)

  def test_ParseArmAnnotations(self):
    fun = linker_map_parser.MapFileParserLld.ParseArmAnnotations

    # Annotations.
    self.assertEqual((True, False), fun('$a'))
    self.assertEqual((True, False), fun('$a.0'))
    self.assertEqual((True, False), fun('$a.137'))
    self.assertEqual((True, True), fun('$t'))
    self.assertEqual((True, True), fun('$t.42'))
    self.assertEqual((True, None), fun('$d'))
    self.assertEqual((True, None), fun('$d.7'))

    # Annotations that should not appear, but get handled anyway.
    self.assertEqual((True, False), fun('$a.'))
    self.assertEqual((True, True), fun('$t.'))
    self.assertEqual((True, None), fun('$d.'))
    self.assertEqual((True, None), fun('$$.'))

    # Non-annotations.
    self.assertEqual((False, None), fun('$_21::invoke'))
    self.assertEqual((False, None), fun('$aa'))
    self.assertEqual((False, None), fun('$tt.'))
    self.assertEqual((False, None), fun('$'))
    self.assertEqual((False, None), fun(''))
    self.assertEqual((False, None), fun('void foo()'))
    self.assertEqual((False, None), fun('OUTLINED_FUNCTION_'))
    self.assertEqual((False, None), fun('abc'))

  @_CompareWithGolden()
  def test_Tokenize(self):
    ret = []
    lines = _ReadMapFile(_TEST_MAP_PATH)
    parser = linker_map_parser.MapFileParserLld('lld-lto_v1')
    tokenizer = parser.Tokenize(lines)
    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()