OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/python | |
2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 import optparse | |
7 import os | |
8 import re | |
9 import sys | |
10 import tempfile | |
11 | |
12 import corpus_utils | |
13 | |
14 | |
15 BAD_MANIFEST = r'^BAD MANIFEST!$' | |
Nick Bray
2012/04/03 20:34:29
Gratuitous raw string.
bradn
2012/04/12 17:45:54
Done.
| |
16 NACL_MODULE_CRASHED = '^nacl module crashed$' | |
17 NACL_MODULE_DIDNT_START = '^nacl module not started$' | |
18 KNOWN_BAD = { | |
Nick Bray
2012/04/03 20:34:29
Very optional: you could split this config stuff o
bradn
2012/04/12 17:45:54
Done.
| |
19 # Bad manifest | |
20 '0937b653af5553856532454ec340d0e0075bc0b4': BAD_MANIFEST, | |
21 '09ffe3793113fe564b71800a5844189c00bd8210': BAD_MANIFEST, | |
22 '14f389a8c406d60e0fc05a1ec0189a652a1f006e': BAD_MANIFEST, | |
23 '2f97cec9f13b0f774d1f49490f26f32213e4e0a5': BAD_MANIFEST, | |
24 '3d6832749c8c1346c65b30f4b191930dec5f04a3': BAD_MANIFEST, | |
25 '612a5aaa821b4b636168025f027e721c0f046e7c': BAD_MANIFEST, | |
26 '81a4a3de69dd4ad169b1d4a7268b44c78ea5ffa8': BAD_MANIFEST, | |
27 'a8aa42d699dbef3e1403e4fdc49325e89a91f653': BAD_MANIFEST, | |
28 'c6d40d4f3c8dccc710d8c09bfd074b2d20a504d2': BAD_MANIFEST, | |
29 'ced1fea90b71b0a8da08c1a1e6cb35975cc84f52': BAD_MANIFEST, | |
30 # Bad permissions | |
31 '8de65668cc7280ffb70ffd2fa5b2a22112156966': ( | |
32 r'^unknown error: :ERROR:extension_error_reporter.cc\(.*\)\] ' | |
33 r'Extension error: Could not load extension from \'.*\'\. ' | |
34 r'Access to permission \'terminalPrivate\' denied\.$'), | |
35 # No nacl module | |
36 '1f861c0d8c173b64df3e70cfa1a5cd710ba59430': NACL_MODULE_DIDNT_START, | |
37 '48ac71edfeac0c79d5e2b651e082abfa76da25f9': NACL_MODULE_DIDNT_START, | |
38 '4beecff67651f13e013c12a5bf3661041ded323c': NACL_MODULE_DIDNT_START, | |
39 '57be161e5ff7011d2283e507a70f9005c448002b': NACL_MODULE_DIDNT_START, | |
40 '5b9f0f7f7401cb666015090908d97346f5b6bccb': NACL_MODULE_DIDNT_START, | |
41 'cfd62adf6790eed0520da2deb2246fc02e70c57e': NACL_MODULE_DIDNT_START, | |
42 'd1f33ad38f9f6e78150d30c2103b5c77a9f0adcd': NACL_MODULE_DIDNT_START, | |
43 'd51802b12a503f7fdfbec60d96e27a5ffa09d002': NACL_MODULE_DIDNT_START, | |
44 # Nacl module crash | |
45 'ab0692192976dc6693212582364c6f23b6551d1a': NACL_MODULE_CRASHED, | |
46 'b458cd57c8b4e6c313b18f370fad59779f573afc': NACL_MODULE_CRASHED, | |
47 } | |
48 # Precompile the above regexs. | |
49 for key in KNOWN_BAD: | |
50 KNOWN_BAD[key] = re.compile(KNOWN_BAD[key]) | |
51 | |
52 | |
53 def ExpectedResult(path): | |
54 """Checks what the expected result for this app is. | |
55 | |
56 Args: | |
57 path: path to the crx. | |
58 Returns: | |
59 Reg-ex that matches the expected status. | |
60 """ | |
61 return KNOWN_BAD.get( | |
62 corpus_utils.Sha1FromFilename(path), re.compile('^GOOD$')) | |
63 | |
64 | |
65 def TestAppStartup(options, crx_path, app_path, profile_path): | |
66 """Run the validator on a nexe, check if the result is expected. | |
67 | |
68 Args: | |
69 options: bag of options. | |
70 crx_path: path to the crx. | |
71 app_path: path to the extracted crx. | |
72 profile_path: path to a temporary profile dir. | |
73 """ | |
74 expected_result = ExpectedResult(crx_path) | |
75 try: | |
76 manifest = corpus_utils.LoadManifest(app_path) | |
77 start_path = manifest.get('app').get('launch').get('local_path') | |
78 except: | |
79 if expected_result.match('BAD MANIFEST!'): | |
Nick Bray
2012/04/03 20:34:29
This is a little sketchy, but I don't have a good
bradn
2012/04/12 17:45:54
Added a CrxResult class.
| |
80 return True | |
81 else: | |
82 print "'%s': 'BAD MANIFEST!'," % corpus_utils.Sha1FromFilename(crx_path) | |
83 return False | |
84 start_url = 'chrome-extension://%s/%s' % ( | |
85 corpus_utils.ChromeAppIdFromPath(app_path), start_path) | |
86 cmd = [options.browser, | |
87 '--enable-nacl', | |
Nick Bray
2012/04/03 20:34:29
Check out toosl/browser_tester/browsertester/brows
bradn
2012/04/12 17:45:54
Done.
| |
88 '--load-extension=' + app_path, | |
89 '--user-data-dir=' + profile_path, start_url] | |
90 process_stdout, process_stderr, retcode = corpus_utils.RunWithTimeout( | |
91 cmd, options.duration) | |
92 # Check for errors we don't like. | |
93 result = 'GOOD' | |
94 if 'NaCl process exited with' in process_stderr: | |
95 result = 'nacl module crashed' | |
96 errs = re.findall(':ERROR:[^\n]+', process_stderr) | |
97 if result == 'GOOD': | |
98 for err in errs: | |
99 if ('extension_prefs.cc' not in err and | |
100 'gles2_cmd_decoder.cc' not in err): | |
101 result = 'unknown error: ' + err | |
102 break | |
103 if result == 'GOOD' and 'NaClMakePcrelThunk:' not in process_stderr: | |
104 result = 'nacl module not started' | |
105 # Check if result is what we expect. | |
106 if not expected_result.match(result): | |
107 print "'%s': '%s'," % (corpus_utils.Sha1FromFilename(crx_path), result) | |
108 if options.verbose: | |
109 print '-' * 70 | |
110 print 'Return code: %s' % retcode | |
111 print '>>> STDOUT' | |
112 print process_stdout | |
113 print '>>> STDERR' | |
114 print process_stderr | |
115 print '-' * 70 | |
116 return False | |
117 return True | |
118 | |
119 | |
120 def TestApps(options, work_dir): | |
121 """Test a browser on a corpus of crxs. | |
122 | |
123 Args: | |
124 options: bag of options. | |
125 work_dir: directory to operate in. | |
126 """ | |
127 profile_path = os.path.join(work_dir, 'profile_temp') | |
128 app_path = os.path.join(work_dir, 'app_temp') | |
129 | |
130 list_filename = os.path.join(work_dir, 'naclapps.all') | |
131 filenames = corpus_utils.DownloadCorpusTotalList(list_filename) | |
132 progress = corpus_utils.Progress(len(filenames)) | |
133 for filename in filenames: | |
134 progress.Tally() | |
135 corpus_utils.PrimeCache(options, filename) | |
136 # Stop here if downloading only. | |
137 if options.download_only: | |
138 continue | |
139 # Stop here if isn't a bad app but testing only bad apps. | |
140 if options.bad_only and ExpectedResult(filename) == 'GOOD': | |
141 continue | |
142 # Unzip the app. | |
143 corpus_utils.ExtractFromCache(options, filename, app_path) | |
144 try: | |
145 progress.Result( | |
146 TestAppStartup(options, filename, app_path, profile_path)) | |
147 finally: | |
148 corpus_utils.RemoveDir(app_path) | |
149 corpus_utils.RemoveDir(profile_path) | |
150 progress.Summary() | |
151 | |
152 | |
153 def Main(): | |
154 if sys.platform in ['cygwin', 'win32']: | |
155 raise Exception('Platform not yet supported') | |
Nick Bray
2012/04/03 20:34:29
Comment: why?
bradn
2012/04/12 17:45:54
Done.
| |
156 | |
157 parser = optparse.OptionParser() | |
158 corpus_utils.SetupOptions(parser) | |
159 parser.add_option( | |
160 '--download-only', dest='download_only', | |
161 default=False, action='store_true', | |
162 help='download to cache without running the tests') | |
163 parser.add_option( | |
164 '--duration', dest='duration', default=30, | |
165 help='how long to run each app for') | |
166 parser.add_option( | |
167 '--browser', dest='browser', | |
168 help='browser to run') | |
169 parser.add_option( | |
170 '-v', '--verbose', dest='verbose', default=False, action='store_true', | |
171 help='run in verbose mode') | |
172 parser.add_option( | |
173 '--bad-only', dest='bad_only', default=False, action='store_true', | |
174 help='test only known bad apps') | |
175 options, args = parser.parse_args() | |
176 if args: | |
177 parser.error('unused arguments') | |
178 if not options.download_only: | |
179 if not options.browser: | |
180 parser.error('no browser specified') | |
181 | |
182 work_dir = tempfile.mkdtemp(suffix='startup_crxs', prefix='tmp') | |
183 work_dir = os.path.realpath(work_dir) | |
184 try: | |
185 TestApps(options, work_dir) | |
186 finally: | |
187 corpus_utils.RemoveDir(work_dir) | |
188 | |
189 | |
190 if __name__ == '__main__': | |
191 Main() | |
OLD | NEW |