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

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: rebase 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 re
19 import subprocess
18 import sys 20 import sys
21 import tempfile
22
23 g_temp_dirs = []
24
25
26 def MakeTempDir():
27 global g_temp_dirs
28 new_dir = tempfile.mkdtemp()
29 g_temp_dirs.append(new_dir)
30 return new_dir
31
32
33 def CleanUpTempDirs():
34 global g_temp_dirs
35 for d in g_temp_dirs:
36 subprocess.call(['rmdir', '/s', '/q', d], shell=True)
19 37
20 38
21 def FindInstalledWindowsApplication(app_path): 39 def FindInstalledWindowsApplication(app_path):
22 search_paths = [os.getenv('PROGRAMFILES(X86)'), 40 search_paths = [os.getenv('PROGRAMFILES(X86)'), os.getenv('PROGRAMFILES'),
Mark Mentovai 2015/10/09 18:34:04 I liked this better before, one element per line.
scottmg 2015/10/09 18:49:28 Yeah, I started using https://github.com/google/ya
23 os.getenv('PROGRAMFILES'),
24 os.getenv('LOCALAPPDATA')] 41 os.getenv('LOCALAPPDATA')]
25 search_paths += os.getenv('PATH', '').split(os.pathsep) 42 search_paths += os.getenv('PATH', '').split(os.pathsep)
26 43
27 for search_path in search_paths: 44 for search_path in search_paths:
28 if not search_path: 45 if not search_path:
29 continue 46 continue
30 path = os.path.join(search_path, app_path) 47 path = os.path.join(search_path, app_path)
31 if os.path.isfile(path): 48 if os.path.isfile(path):
32 return path 49 return path
33 50
34 return None 51 return None
35 52
36 53
37 def GetCdbPath(): 54 def GetCdbPath():
55 """Search in some reasonable places to find cdb.exe. Searches x64 before x86
56 and newer versions before older versions.
57 """
38 possible_paths = ( 58 possible_paths = (
39 os.path.join('Windows Kits', '10', 'Debuggers', 'x64'), 59 os.path.join('Windows Kits', '10', 'Debuggers', 'x64'),
40 os.path.join('Windows Kits', '10', 'Debuggers', 'x86'), 60 os.path.join('Windows Kits', '10', 'Debuggers', 'x86'),
41 os.path.join('Windows Kits', '8.1', 'Debuggers', 'x64'), 61 os.path.join('Windows Kits', '8.1', 'Debuggers', 'x64'),
42 os.path.join('Windows Kits', '8.1', 'Debuggers', 'x86'), 62 os.path.join('Windows Kits', '8.1', 'Debuggers', 'x86'),
43 os.path.join('Windows Kits', '8.0', 'Debuggers', 'x64'), 63 os.path.join('Windows Kits', '8.0', 'Debuggers', 'x64'),
44 os.path.join('Windows Kits', '8.0', 'Debuggers', 'x86'), 64 os.path.join('Windows Kits', '8.0', 'Debuggers', 'x86'),
45 'Debugging Tools For Windows (x64)', 65 'Debugging Tools For Windows (x64)', 'Debugging Tools For Windows (x86)',
46 'Debugging Tools For Windows (x86)', 66 'Debugging Tools For Windows',)
47 '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: 67 for possible_path in possible_paths:
54 app_path = os.path.join(possible_path, 'cdb.exe') 68 app_path = os.path.join(possible_path, 'cdb.exe')
55 app_path = FindInstalledWindowsApplication(app_path) 69 app_path = FindInstalledWindowsApplication(app_path)
56 if app_path: 70 if app_path:
57 return app_path 71 return app_path
58 return None 72 return None
59 73
60 74
75 def GetDumpFromCrashyProgram(out_dir):
76 """Initialize a crash database, run crashpad_handler, run crashy_program
77 connecting to the crash_handler. Returns the minidump generated by
78 crash_handler for further testing.
79 """
80 pipe_name = r'\\.\pipe\end-to-end'
Mark Mentovai 2015/10/09 18:34:05 Should this be a little more random? pid + 64 rand
scottmg 2015/10/09 18:49:28 Done.
81
82 test_database = MakeTempDir()
83
84 try:
85 if subprocess.call(
86 [os.path.join(out_dir, 'crashpad_database_util.exe'), '--create',
87 '--database=' + test_database]) != 0:
88 print 'could not initialize report database'
89 return None
90
91 handler = subprocess.Popen([
92 os.path.join(out_dir, 'crashpad_handler.exe'), '--pipe-name=' +
93 pipe_name, '--database=' + test_database
Mark Mentovai 2015/10/09 18:34:05 'pipe_name=' and pipe_name should at least be on t
scottmg 2015/10/09 18:49:28 Done.
94 ])
95
96 subprocess.call([os.path.join(out_dir, 'crashy_program.exe'), pipe_name])
97
98 out = subprocess.check_output([
99 os.path.join(out_dir, 'crashpad_database_util.exe'),
100 '--database=' + test_database,
101 '--show-completed-reports',
102 '--show-all-report-info',
103 ])
104 for line in out.splitlines():
105 if line.strip().startswith('Path:'):
106 return line.partition(':')[2].strip()
107
108 finally:
109 if handler:
110 handler.kill()
111
112
113 class CdbRun(object):
114 """Run cdb.exe passing it the given commands and capturing the output.
115 `Check()` searchs for regex patterns in sequence allowing verification of
Mark Mentovai 2015/10/09 18:34:05 searches
scottmg 2015/10/09 18:49:28 Done.
116 expected output.
117 """
118 def __init__(self, cdb_path, dump_path, *commands):
119 # Run a command line that loads the dump, runs the specified commands, and
120 # then quits, and capture the stdout.
121 self.out = subprocess.check_output([cdb_path, '-z', dump_path, '-c',
122 ';'.join(commands) + ';q'])
Mark Mentovai 2015/10/09 18:34:05 Dunno about how cdb command lines should be escape
Mark Mentovai 2015/10/09 18:34:05 '-c' next to this, since this whole thing applies
scottmg 2015/10/09 18:49:28 Switched to just 'command'.
scottmg 2015/10/09 18:49:28 Done.
123
124 def Check(self, pattern, message):
125 print ' ... ' + message,
126 sys.stdout.flush()
127 match_obj = re.search(pattern, self.out)
128 if match_obj:
129 # Matched. Consume up to end of match.
130 self.out = self.out[match_obj.end(0):]
131 print '\rok - '
Mark Mentovai 2015/10/09 18:34:04 '\rok - ' Not really sure what you’re going for h
scottmg 2015/10/09 18:49:28 I wanted the "ok"s before the names so they're eas
132 sys.stdout.flush()
133 else:
134 print
135 print '-'*80
Mark Mentovai 2015/10/09 18:34:05 Errors to stderr?
scottmg 2015/10/09 18:49:28 Done.
136 print 'did not match:\n %s' % pattern
137 print '-'*80
138 print 'remaining output was:\n %s' % self.out
139 print '-'*80
140 sys.exit(1)
141
142
143 def RunTests(cdb_path, dump_path):
144 """Runs various tests in sequence. Runs a new cdb instance on the dump for
145 each block of tests to reduce the chances that output from one command is
146 confused for output from another.
147 """
148 out = CdbRun(cdb_path, dump_path, '.ecxr')
149 out.Check('This dump file has an exception of interest stored in it',
150 'captured exception')
151 out.Check(
152 'crashy_program!crashpad::`anonymous namespace\'::SomeCrashyFunction',
153 'exception at correct location')
154
155 out = CdbRun(cdb_path, dump_path, '!peb')
156 out.Check(r'PEB at', 'found the PEB')
157 out.Check(r'Ldr\.InMemoryOrderModuleList:.*\d+ \. \d+', 'PEB_LDR_DATA saved')
158 out.Check(r'Base TimeStamp Module', 'module list present')
159 out.Check(r'CommandLine: *\'.*crashy_program.exe *\\\\.\\pipe\\end-to-end',
160 'some PEB data is correct')
161 out.Check(r'SystemRoot=C:\\Windows', 'some of environment captured')
162
163 out = CdbRun(cdb_path, dump_path, '!teb')
164 out.Check(r'TEB at', 'found the TEB')
165 out.Check(r'ExceptionList:\s+[0-9a-fA-F]+', 'some valid teb data')
166 out.Check(r'LastErrorValue:\s+2', 'correct LastErrorValue')
167
168 out = CdbRun(cdb_path, dump_path, '!gle')
169 out.Check('LastErrorValue: \(Win32\) 0x2 \(2\) - The system cannot find the '
170 'file specified.', '!gle gets last error')
171 out.Check('LastStatusValue: \(NTSTATUS\) 0xc000000f - {File Not Found} The '
172 'file %hs does not exist.', '!gle gets last ntstatus')
173
174 # Locks.
175 out = CdbRun(cdb_path, dump_path, '!locks')
176 out.Check(r'CritSec crashy_program!crashpad::`anonymous namespace\'::'
177 r'g_test_critical_section', 'lock was captured')
178 out.Check(r'\*\*\* Locked', 'lock debug info was captured, and is locked')
179
180
61 def main(args): 181 def main(args):
62 cdb_path = GetCdbPath() 182 try:
63 print 'cdb_path:', cdb_path 183 if len(args) != 1:
64 return 0 184 print 'must supply out dir'
Mark Mentovai 2015/10/09 18:34:05 stderr for these
scottmg 2015/10/09 18:49:28 Done.
185 return 1
186
187 cdb_path = GetCdbPath()
188 if not cdb_path:
189 print 'could not find cdb'
190 return 1
191
192 dump_path = GetDumpFromCrashyProgram(args[0])
193 if not dump_path:
194 return 1
195
196 RunTests(cdb_path, dump_path)
197
198 return 0
199 finally:
200 CleanUpTempDirs()
65 201
66 202
67 if __name__ == '__main__': 203 if __name__ == '__main__':
68 sys.exit(main(sys.argv[1:])) 204 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