Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: snapshot/win/end_to_end_test.py

Issue 1397833004: win: Test some basic ! windbg commands (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@add-pexpect
Patch Set: fixes Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « build/run_tests.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
3 # Copyright 2015 The Crashpad Authors. All rights reserved. 3 # Copyright 2015 The Crashpad Authors. All rights reserved.
4 # 4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License. 6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at 7 # You may obtain a copy of the License at
8 # 8 #
9 # http://www.apache.org/licenses/LICENSE-2.0 9 # http://www.apache.org/licenses/LICENSE-2.0
10 # 10 #
11 # Unless required by applicable law or agreed to in writing, software 11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, 12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and 14 # See the License for the specific language governing permissions and
15 # limitations under the License. 15 # limitations under the License.
16 16
17 import os 17 import os
18 import random
19 import re
20 import subprocess
18 import sys 21 import sys
22 import tempfile
23
24 g_temp_dirs = []
25
26
27 def MakeTempDir():
28 global g_temp_dirs
29 new_dir = tempfile.mkdtemp()
30 g_temp_dirs.append(new_dir)
31 return new_dir
32
33
34 def CleanUpTempDirs():
35 global g_temp_dirs
36 for d in g_temp_dirs:
37 subprocess.call(['rmdir', '/s', '/q', d], shell=True)
19 38
20 39
21 def FindInstalledWindowsApplication(app_path): 40 def FindInstalledWindowsApplication(app_path):
22 search_paths = [os.getenv('PROGRAMFILES(X86)'), 41 search_paths = [os.getenv('PROGRAMFILES(X86)'),
23 os.getenv('PROGRAMFILES'), 42 os.getenv('PROGRAMFILES'),
24 os.getenv('LOCALAPPDATA')] 43 os.getenv('LOCALAPPDATA')]
25 search_paths += os.getenv('PATH', '').split(os.pathsep) 44 search_paths += os.getenv('PATH', '').split(os.pathsep)
26 45
27 for search_path in search_paths: 46 for search_path in search_paths:
28 if not search_path: 47 if not search_path:
29 continue 48 continue
30 path = os.path.join(search_path, app_path) 49 path = os.path.join(search_path, app_path)
31 if os.path.isfile(path): 50 if os.path.isfile(path):
32 return path 51 return path
33 52
34 return None 53 return None
35 54
36 55
37 def GetCdbPath(): 56 def GetCdbPath():
57 """Search in some reasonable places to find cdb.exe. Searches x64 before x86
58 and newer versions before older versions.
59 """
38 possible_paths = ( 60 possible_paths = (
39 os.path.join('Windows Kits', '10', 'Debuggers', 'x64'), 61 os.path.join('Windows Kits', '10', 'Debuggers', 'x64'),
40 os.path.join('Windows Kits', '10', 'Debuggers', 'x86'), 62 os.path.join('Windows Kits', '10', 'Debuggers', 'x86'),
41 os.path.join('Windows Kits', '8.1', 'Debuggers', 'x64'), 63 os.path.join('Windows Kits', '8.1', 'Debuggers', 'x64'),
42 os.path.join('Windows Kits', '8.1', 'Debuggers', 'x86'), 64 os.path.join('Windows Kits', '8.1', 'Debuggers', 'x86'),
43 os.path.join('Windows Kits', '8.0', 'Debuggers', 'x64'), 65 os.path.join('Windows Kits', '8.0', 'Debuggers', 'x64'),
44 os.path.join('Windows Kits', '8.0', 'Debuggers', 'x86'), 66 os.path.join('Windows Kits', '8.0', 'Debuggers', 'x86'),
45 'Debugging Tools For Windows (x64)', 67 'Debugging Tools For Windows (x64)',
46 'Debugging Tools For Windows (x86)', 68 'Debugging Tools For Windows (x86)',
47 'Debugging Tools For Windows', 69 'Debugging Tools For Windows',)
48 os.path.join('win_toolchain', 'vs2013_files', 'win8sdk', 'Debuggers',
49 'x64'),
50 os.path.join('win_toolchain', 'vs2013_files', 'win8sdk', 'Debuggers',
51 'x86'),
52 )
53 for possible_path in possible_paths: 70 for possible_path in possible_paths:
54 app_path = os.path.join(possible_path, 'cdb.exe') 71 app_path = os.path.join(possible_path, 'cdb.exe')
55 app_path = FindInstalledWindowsApplication(app_path) 72 app_path = FindInstalledWindowsApplication(app_path)
56 if app_path: 73 if app_path:
57 return app_path 74 return app_path
58 return None 75 return None
59 76
60 77
78 def GetDumpFromCrashyProgram(out_dir, pipe_name):
79 """Initialize a crash database, run crashpad_handler, run crashy_program
80 connecting to the crash_handler. Returns the minidump generated by
81 crash_handler for further testing.
82 """
83 test_database = MakeTempDir()
84
85 try:
86 if subprocess.call(
87 [os.path.join(out_dir, 'crashpad_database_util.exe'), '--create',
88 '--database=' + test_database]) != 0:
89 print 'could not initialize report database'
90 return None
91
92 handler = subprocess.Popen([
93 os.path.join(out_dir, 'crashpad_handler.exe'),
94 '--pipe-name=' + pipe_name,
95 '--database=' + test_database
96 ])
97
98 subprocess.call([os.path.join(out_dir, 'crashy_program.exe'), pipe_name])
99
100 out = subprocess.check_output([
101 os.path.join(out_dir, 'crashpad_database_util.exe'),
102 '--database=' + test_database,
103 '--show-completed-reports',
104 '--show-all-report-info',
105 ])
106 for line in out.splitlines():
107 if line.strip().startswith('Path:'):
108 return line.partition(':')[2].strip()
109
110 finally:
111 if handler:
112 handler.kill()
113
114
115 class CdbRun(object):
116 """Run cdb.exe passing it a cdb command and capturing the output.
117 `Check()` searches for regex patterns in sequence allowing verification of
118 expected output.
119 """
120
121 def __init__(self, cdb_path, dump_path, command):
122 # Run a command line that loads the dump, runs the specified cdb command,
123 # and then quits, and capturing stdout.
124 self.out = subprocess.check_output([
125 cdb_path,
126 '-z', dump_path,
127 '-c', command + ';q'
128 ])
129
130 def Check(self, pattern, message):
131 match_obj = re.search(pattern, self.out)
132 if match_obj:
133 # Matched. Consume up to end of match.
134 self.out = self.out[match_obj.end(0):]
135 print 'ok - %s' % message
136 else:
137 print >>sys.stderr, '-' * 80
138 print >>sys.stderr, 'FAILED - %s' % message
139 print >>sys.stderr, '-' * 80
140 print >>sys.stderr, 'did not match:\n %s' % pattern
141 print >>sys.stderr, '-' * 80
142 print >>sys.stderr, 'remaining output was:\n %s' % self.out
143 print >>sys.stderr, '-' * 80
144 sys.exit(1)
145
146
147 def RunTests(cdb_path, dump_path, pipe_name):
148 """Runs various tests in sequence. Runs a new cdb instance on the dump for
149 each block of tests to reduce the chances that output from one command is
150 confused for output from another.
151 """
152 out = CdbRun(cdb_path, dump_path, '.ecxr')
153 out.Check('This dump file has an exception of interest stored in it',
154 'captured exception')
155 out.Check(
156 'crashy_program!crashpad::`anonymous namespace\'::SomeCrashyFunction',
157 'exception at correct location')
158
159 out = CdbRun(cdb_path, dump_path, '!peb')
160 out.Check(r'PEB at', 'found the PEB')
161 out.Check(r'Ldr\.InMemoryOrderModuleList:.*\d+ \. \d+', 'PEB_LDR_DATA saved')
162 out.Check(r'Base TimeStamp Module', 'module list present')
163 pipe_name_escaped = pipe_name.replace('\\', '\\\\')
164 out.Check(r'CommandLine: *\'.*crashy_program.exe *' + pipe_name_escaped,
165 'some PEB data is correct')
166 out.Check(r'SystemRoot=C:\\Windows', 'some of environment captured')
167
168 out = CdbRun(cdb_path, dump_path, '!teb')
169 out.Check(r'TEB at', 'found the TEB')
170 out.Check(r'ExceptionList:\s+[0-9a-fA-F]+', 'some valid teb data')
171 out.Check(r'LastErrorValue:\s+2', 'correct LastErrorValue')
172
173 out = CdbRun(cdb_path, dump_path, '!gle')
174 out.Check('LastErrorValue: \(Win32\) 0x2 \(2\) - The system cannot find the '
175 'file specified.', '!gle gets last error')
176 out.Check('LastStatusValue: \(NTSTATUS\) 0xc000000f - {File Not Found} The '
177 'file %hs does not exist.', '!gle gets last ntstatus')
178
179 # Locks.
180 out = CdbRun(cdb_path, dump_path, '!locks')
181 out.Check(r'CritSec crashy_program!crashpad::`anonymous namespace\'::'
182 r'g_test_critical_section', 'lock was captured')
183 out.Check(r'\*\*\* Locked', 'lock debug info was captured, and is locked')
184
185
61 def main(args): 186 def main(args):
62 cdb_path = GetCdbPath() 187 try:
63 print 'cdb_path:', cdb_path 188 if len(args) != 1:
64 return 0 189 print >>sys.stderr, 'must supply out dir'
190 return 1
191
192 cdb_path = GetCdbPath()
193 if not cdb_path:
194 print >>sys.stderr, 'could not find cdb'
195 return 1
196
197 pipe_name = r'\\.\pipe\end-to-end_%s_%s' % (
198 os.getpid(), str(random.getrandbits(64)))
199
200 dump_path = GetDumpFromCrashyProgram(args[0], pipe_name)
201 if not dump_path:
202 return 1
203
204 RunTests(cdb_path, dump_path, pipe_name)
205
206 return 0
207 finally:
208 CleanUpTempDirs()
65 209
66 210
67 if __name__ == '__main__': 211 if __name__ == '__main__':
68 sys.exit(main(sys.argv[1:])) 212 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « build/run_tests.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698