11#!/usr/bin/env python
22
3- # This script uses a regex to validate the output of our backtraces.
4- # The layout we assume is:
5- #
6- # <frame number> <library name> <address> <demangled name> + <offset>
7- #
8- # It currently just checks that the backtrace results in at least one correctly
9- # formatted entry. It does not directly validate the input since the output
10- # would not be robust against standard library changes.
11- #
12- # TODO: We could have the user pass in the frame number, library name, and
13- # demangled name. These we can always validate as true in a robust way. On the
14- # other hand, address and offset are more difficult to validate in a robust way
15- # in the face of small codegen differences, so without any further thought I
16- # imagine we can just check the format.
17- #
18- # 11 libswiftCore.dylib 0x000000000dce84d0l _fatalErrorMessage(StaticString,
19- # StaticString, StaticString, UInt, flags : UInt32) -> () + 444
20-
21- from __future__ import print_function
3+
4+ """
5+ This script uses a regex to validate the output of our backtraces.
6+ The layout we assume is:
7+
8+ <frame number> <library name> <address> <demangled name> + <offset>
9+
10+ It currently just checks that the backtrace results in at least one correctly
11+ formatted entry. It does not directly validate the input since the output
12+ would not be robust against standard library changes.
13+
14+ TODO: We could have the user pass in the frame number, library name, and
15+ demangled name. These we can always validate as true in a robust way. On the
16+ other hand, address and offset are more difficult to validate in a robust way
17+ in the face of small codegen differences, so without any further thought I
18+ imagine we can just check the format.
19+
20+ 11 libswiftCore.dylib 0x000000000dce84d0l _fatalErrorMessage(StaticString,
21+ StaticString, StaticString, UInt, flags : UInt32) -> () + 444
22+ """
23+
24+
25+ from __future__ import absolute_import , print_function , unicode_literals
2226
2327import argparse
2428import re
2529import sys
2630
2731
28- def main ():
32+ # -----------------------------------------------------------------------------
33+ # Constants
34+
35+ DESCRIPTION = """
36+ Checks that a stacktrace dump follows canonical formatting.
37+ """
38+
39+ TARGET_PATTERN = re .compile (
40+ r'(?P<index>\d+) +(?P<object>\S+) +(?P<address>0x[0-9a-fA-F]{16}) '
41+ r'(?P<routine>[^+]+) [+] (?P<offset>\d+)' )
42+
43+ RESULTS_FORMAT = """Stack Trace Entry:
44+ \t Index: '%(index)s'
45+ \t Object File: '%(object)s'
46+ \t Address: '%(address)s'
47+ \t Routine: '%(routine)s'
48+ \t Offset: '%(offset)s'
49+ """
50+
51+
52+ # -----------------------------------------------------------------------------
53+
54+ def parse_args ():
2955 parser = argparse .ArgumentParser (
3056 formatter_class = argparse .RawDescriptionHelpFormatter ,
31- description = """Checks that a stacktrace dump follows canonical
32- formatting.""" )
57+ description = DESCRIPTION )
58+
3359 parser .add_argument (
34- "-u" , " --check-unavailable" , action = 'store_true ' ,
35- help = "Checks if any symbols were unavailable" )
36- args = parser . parse_args ( )
60+ '-u' , ' --check-unavailable' ,
61+ action = 'store_true' ,
62+ help = 'Checks if any symbols were unavailable' )
3763
38- TARGET_RE = re .compile (
39- r"(?P<index>\d+) +(?P<object>\S+) +(?P<address>0x[0-9a-fA-F]{16}) "
40- r"(?P<routine>[^+]+) [+] (?P<offset>\d+)" )
64+ return parser .parse_args ()
65+
66+
67+ def main ():
68+ args = parse_args ()
4169
4270 lines = sys .stdin .readlines ()
4371
4472 found_stack_trace_start = False
4573 found_stack_trace_entry = False
4674 for line in lines :
47- line = line .rstrip (" \n " )
75+ line = line .rstrip (' \n ' )
4876
4977 # First see if we found the start of our stack trace start. If so, set
5078 # the found stack trace flag and continue.
51- if line == " Current stack trace:" :
79+ if line == ' Current stack trace:' :
5280 assert (not found_stack_trace_start )
5381 found_stack_trace_start = True
5482 continue
@@ -59,21 +87,19 @@ formatting.""")
5987 continue
6088
6189 # Ok, we are in the middle of matching a stack trace entry.
62- m = TARGET_RE .match (line )
90+ matches = TARGET_PATTERN .match (line )
91+
6392 # If we fail to match, we have exited the stack trace entry region
64- if m is None :
93+ if matches is None :
6594 break
6695
6796 # At this point, we know that we have some sort of match.
6897 found_stack_trace_entry = True
69- print ("Stack Trace Entry:" )
70- print ("\t Index: '%(index)s'\n \t Object File: '%(object)s'\n \t Address: "
71- "'%(address)s'\n \t Routine: '%(routine)s'\n \t Offset: '%(offset)s'"
72- "\n " % m .groupdict ())
98+ print (RESULTS_FORMAT .format (** matches .groupdict ()))
7399
74100 # Check for unavailable symbols, if that was requested.
75101 if args .check_unavailable :
76- assert (" unavailable" not in m .group (" routine" ))
102+ assert (' unavailable' not in matches .group (' routine' ))
77103
78104 # Once we have processed all of the lines, make sure that we found at least
79105 # one stack trace entry.
0 commit comments