OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2012 The Chromium 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 copy | |
7 import ctypes | |
8 from distutils import version | |
9 import fnmatch | |
10 import glob | |
11 import hashlib | |
12 import logging | |
13 import os | |
14 import platform | |
15 import re | |
16 import shutil | |
17 import subprocess | |
18 import sys | |
19 import tempfile | |
20 import urllib2 | |
21 import xml.dom.minidom | |
22 import zipfile | |
23 | |
24 import pyauto_functional # Must be imported before pyauto. | |
25 import pyauto | |
26 import pyauto_utils | |
27 import test_utils | |
28 | |
29 | |
30 class NaClSDKTest(pyauto.PyUITest): | |
31 """Tests for the NaCl SDK.""" | |
32 _isExamplesTest = False | |
33 _extracted_sdk_path = None | |
34 _temp_dir = None | |
35 _updated_pepper_versions = [] | |
36 _latest_updated_pepper_versions = [] | |
37 _settings = { | |
38 'post_sdk_download_url': 'http://code.google.com/chrome/nativeclient/' | |
39 'docs/download.html', | |
40 'post_sdk_zip': 'http://storage.googleapis.com/' | |
41 'nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip', | |
42 'min_required_chrome_build': 14, | |
43 } | |
44 | |
45 def tearDown(self): | |
46 pyauto.PyUITest.tearDown(self) | |
47 if not self._isExamplesTest: | |
48 self._RemoveDownloadedTestFile() | |
49 | |
50 def testNaClSDK(self): | |
51 """Verify that NaCl SDK is working properly.""" | |
52 if not self._HasAllSystemRequirements(): | |
53 logging.info('System does not meet the requirements.') | |
54 return | |
55 self._extracted_sdk_path = tempfile.mkdtemp() | |
56 self._VerifyDownloadLinks() | |
57 self._VerifyNaClSDKInstaller() | |
58 self._VerifyInstall() | |
59 self._VerifyUpdate() | |
60 self._LaunchServerAndVerifyExamplesAllPepperVersions() | |
61 | |
62 def NaClSDKExamples(self): | |
63 """Verify if NaCl SDK examples are working.""" | |
64 self._isExamplesTest = True | |
65 nacl_sdk_root = os.environ.get('NACL_SDK_ROOT', None) | |
66 pepper_version = os.environ.get('PEPPER_VER', None) | |
67 if nacl_sdk_root and pepper_version: | |
68 self._LaunchServerAndVerifyExamples('pepper_' + pepper_version, | |
69 nacl_sdk_root) | |
70 else: | |
71 self.fail(msg='Missing pepper version to be checked or SDK path.') | |
72 | |
73 def _VerifyDownloadLinks(self): | |
74 """Verify the download links. | |
75 | |
76 Simply verify that NaCl download links exist in html page. | |
77 """ | |
78 html = None | |
79 for i in xrange(3): | |
80 try: | |
81 html = urllib2.urlopen(self._settings['post_sdk_download_url']).read() | |
82 break | |
83 except: | |
84 pass | |
85 self.assertTrue(html, | |
86 msg='Cannot open URL: %s' % | |
87 self._settings['post_sdk_download_url']) | |
88 sdk_url = self._settings['post_sdk_zip'] | |
89 self.assertTrue(sdk_url in html, | |
90 msg='Missing SDK download URL: %s' % sdk_url) | |
91 | |
92 def _VerifyNaClSDKInstaller(self): | |
93 """Verify NaCl SDK installer.""" | |
94 search_list = [ | |
95 'sdk_cache/', | |
96 'sdk_tools/', | |
97 ] | |
98 mac_lin_additional_search_items = [ | |
99 'naclsdk', | |
100 ] | |
101 win_additional_search_items = [ | |
102 'naclsdk.bat' | |
103 ] | |
104 self._DownloadNaClSDK() | |
105 self._ExtractNaClSDK() | |
106 if pyauto.PyUITest.IsWin(): | |
107 self._SearchNaClSDKFile( | |
108 search_list + win_additional_search_items) | |
109 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux(): | |
110 self._SearchNaClSDKFile( | |
111 search_list + mac_lin_additional_search_items) | |
112 else: | |
113 self.fail(msg='NaCl SDK does not support this OS.') | |
114 | |
115 def _VerifyInstall(self): | |
116 """Install NACL sdk.""" | |
117 # Executing naclsdk(.bat) list | |
118 if pyauto.PyUITest.IsWin(): | |
119 source_file = os.path.join( | |
120 self._extracted_sdk_path, 'nacl_sdk', 'naclsdk.bat') | |
121 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux(): | |
122 source_file = os.path.join( | |
123 self._extracted_sdk_path, 'nacl_sdk', 'naclsdk') | |
124 subprocess.call(['chmod', '-R', '755', self._extracted_sdk_path]) | |
125 else: | |
126 self.fail(msg='NaCl SDK does not support this OS.') | |
127 subprocess.Popen([source_file, 'list'], | |
128 stdout=subprocess.PIPE, | |
129 stderr=subprocess.PIPE).communicate() | |
130 | |
131 def _VerifyUpdate(self): | |
132 """Update NACL sdk""" | |
133 # Executing naclsdk(.bat) update | |
134 if pyauto.PyUITest.IsWin(): | |
135 source_file = os.path.join(self._extracted_sdk_path, 'nacl_sdk', | |
136 'naclsdk.bat') | |
137 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux(): | |
138 source_file = os.path.join(self._extracted_sdk_path, 'nacl_sdk', | |
139 'naclsdk') | |
140 else: | |
141 self.fail(msg='NaCl SDK does not support this OS.') | |
142 # Executing nacl_sdk(.bat) update to get the latest version. | |
143 updated_output = subprocess.Popen([source_file, 'update'], | |
144 stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] | |
145 self._updated_pepper_versions.extend( | |
146 re.findall('Updating bundle (pepper_[0-9]{2})', updated_output)) | |
147 self._updated_pepper_versions = list(set(self._updated_pepper_versions)) | |
148 self._updated_pepper_versions.sort(key=str.lower) | |
149 updated_pepper_versions_len = len(self._updated_pepper_versions) | |
150 self._latest_updated_pepper_versions = filter( | |
151 lambda x: x >= 'pepper_18', self._updated_pepper_versions) | |
152 | |
153 def _GetURLForExampleName(self, name, toolchain): | |
154 return 'http://localhost:5103/%s/index_%s.html' % (name, toolchain) | |
155 | |
156 def _GetExampleNamesAndURLs(self, examples_path): | |
157 """Get a list of all examples as (name, url) tuples. | |
158 | |
159 Args: | |
160 examples_path: The path to the examples directory in the NaCl SDK. | |
161 """ | |
162 toolchains = ['newlib', 'glibc', 'pnacl'] | |
163 | |
164 examples = [] | |
165 for toolchain in toolchains: | |
166 for example in os.listdir(examples_path): | |
167 html_path = os.path.join(examples_path, example, | |
168 'index_%s.html' % (toolchain,)) | |
169 if os.path.exists(html_path): | |
170 example_url = self._GetURLForExampleName(example, toolchain) | |
171 examples.append((example, example_url)) | |
172 return examples | |
173 | |
174 def _LaunchServerAndVerifyExamplesAllPepperVersions(self): | |
175 for pepper_version in self._latest_updated_pepper_versions: | |
176 pepper_path = os.path.join(self._extracted_sdk_path, | |
177 'nacl_sdk', 'pepper_' + str(pepper_version)) | |
178 self._LaunchServerAndVerifyExamples(pepper_version, pepper_path) | |
179 | |
180 def _LaunchServerAndVerifyExamples(self, pepper_version, pepper_path): | |
181 """Start local HTTP server and verify examples.""" | |
182 if self._ChromeAndPepperVersionMatch(pepper_version): | |
183 # Close server if it's already open. | |
184 if self._IsURLAlive('http://localhost:5103'): | |
185 self._CloseHTTPServer() | |
186 | |
187 examples_path = os.path.join(pepper_path, 'examples') | |
188 | |
189 # Launch local http server. | |
190 proc = subprocess.Popen(['make RUN'], shell=True, cwd=examples_path) | |
191 self.WaitUntil( | |
192 lambda: self._IsURLAlive('http://localhost:5103'), | |
193 timeout=150, retry_sleep=1) | |
194 | |
195 examples = self._GetExampleNamesAndURLs(examples_path) | |
196 try: | |
197 self._OpenExamplesAndStartTest(examples) | |
198 finally: | |
199 self._CloseHTTPServer(proc) | |
200 | |
201 else: | |
202 self.pprint('Pepper Version %s does not match the Chrome version %s.' | |
203 % (pepper_version, | |
204 self.GetBrowserInfo()['properties']['ChromeVersion'])) | |
205 | |
206 def _ChromeAndPepperVersionMatch(self, pepper_version='pepper_18'): | |
207 """Determine if chrome and pepper version match""" | |
208 version_number = re.findall('pepper_([0-9]{2})', pepper_version) | |
209 browser_info = self.GetBrowserInfo() | |
210 chrome_version = browser_info['properties']['ChromeVersion'] | |
211 chrome_build = int(chrome_version.split('.')[0]) | |
212 return int(chrome_build) == int(version_number[0]) | |
213 | |
214 def _RemoveDownloadedTestFile(self): | |
215 """Delete downloaded files and dirs from downloads directory.""" | |
216 if self._extracted_sdk_path and os.path.exists(self._extracted_sdk_path): | |
217 self._CloseHTTPServer() | |
218 | |
219 def _RemoveFile(): | |
220 shutil.rmtree(self._extracted_sdk_path, ignore_errors=True) | |
221 return os.path.exists(self._extracted_sdk_path) | |
222 | |
223 success = self.WaitUntil(_RemoveFile, retry_sleep=2, | |
224 expect_retval=False) | |
225 self.assertTrue(success, | |
226 msg='Cannot remove %s' % self._extracted_sdk_path) | |
227 | |
228 if self._temp_dir: | |
229 pyauto_utils.RemovePath(self._temp_dir) | |
230 | |
231 def _OpenExamplesAndStartTest(self, examples): | |
232 """Open each example and verify that it's working. | |
233 | |
234 Args: | |
235 examples: A list of example (name, url) tuples. | |
236 """ | |
237 example_verify_funcs = { | |
238 'dlopen': self._VerifyDynamicLibraryOpen, | |
239 'file_io': self._VerifyFileIoExample, | |
240 'geturl': self._VerifyGetURLExample, | |
241 'input_events': self._VerifyInputEventsExample, | |
242 'load_progress': self._VerifyLoadProgressExample, | |
243 'mt_input_events': self._VerifyMultithreadedInputEventsExample, | |
244 'pi_generator': self._VerifyPiGeneratorExample, | |
245 'sine_synth': self._VerifySineSynthExample, | |
246 'websocket': self._VerifyWebSocketExample, | |
247 } | |
248 | |
249 # Remove examples that we don't yet verify | |
250 examples = [(name, url) for name, url in examples | |
251 if name in example_verify_funcs] | |
252 | |
253 # Open all examples. | |
254 for name, url in examples: | |
255 self.AppendTab(pyauto.GURL(url)) | |
256 self._CheckForCrashes() | |
257 | |
258 # Verify all examples are working. | |
259 for name, url in examples: | |
260 self._VerifyAnExample(name, url, example_verify_funcs[name]) | |
261 self._CheckForCrashes() | |
262 | |
263 # Close each tab and check for crashes. | |
264 tab_count = self.GetTabCount() | |
265 for index in xrange(tab_count - 1, 0, -1): | |
266 self.CloseTab(tab_index=index) | |
267 self._CheckForCrashes() | |
268 | |
269 def _VerifyAnExample(self, name, url, verify_func): | |
270 """Verify NaCl example is working. | |
271 | |
272 Args: | |
273 name: A string name of the example. | |
274 url: A string url of the example. | |
275 verify_func: The function to verify the example. | |
276 Takes (tab_index, name, url) as parameters. | |
277 """ | |
278 if not verify_func: | |
279 self.fail(msg='No test available for %s.' % name) | |
280 | |
281 info = self.GetBrowserInfo() | |
282 tabs = info['windows'][0]['tabs'] | |
283 tab_index = None | |
284 for tab in tabs: | |
285 if url == tab['url']: | |
286 self.ActivateTab(tab['index']) | |
287 tab_index = tab['index'] | |
288 break | |
289 | |
290 if tab_index: | |
291 verify_func(tab_index, name, url) | |
292 | |
293 def _VerifyElementPresent(self, element_id, expected_value, tab_index, msg, | |
294 attribute='innerHTML', timeout=150): | |
295 """Determine if dom element has the expected value. | |
296 | |
297 Args: | |
298 element_id: Dom element's id. | |
299 expected_value: String to be matched against the Dom element. | |
300 tab_index: Tab index to work on. | |
301 attribute: Attribute to match |expected_value| against, if | |
302 given. Defaults to 'innerHTML'. | |
303 timeout: The max timeout (in secs) for which to wait. | |
304 """ | |
305 js_code = """ | |
306 var output = document.getElementById('%s').%s; | |
307 var result; | |
308 if (output.indexOf('%s') != -1) | |
309 result = 'pass'; | |
310 else | |
311 result = 'fail'; | |
312 window.domAutomationController.send(result); | |
313 """ % (element_id, attribute, expected_value) | |
314 success = self.WaitUntil( | |
315 lambda: self.ExecuteJavascript(js_code, tab_index), | |
316 timeout=timeout, expect_retval='pass') | |
317 self.assertTrue(success, msg=msg) | |
318 | |
319 def _CreateJSToSimulateMouseclick(self): | |
320 """Create javascript to simulate mouse click event.""" | |
321 js_code = """ | |
322 var rightClick = document.createEvent('MouseEvents'); | |
323 rightClick.initMouseEvent( | |
324 'mousedown', true, true, document, | |
325 1, 32, 121, 10, 100, | |
326 false, false, false, false, | |
327 2, common.naclModule | |
328 ); | |
329 common.naclModule.dispatchEvent(rightClick); | |
330 window.domAutomationController.send('done'); | |
331 """ | |
332 return js_code | |
333 | |
334 def _VerifyInputEventsExample(self, tab_index, name, url): | |
335 """Verify Input Events Example. | |
336 | |
337 Args: | |
338 tab_index: Tab index integer that the example is on. | |
339 name: A string name of the example. | |
340 url: A string url of the example. | |
341 """ | |
342 success = self._VerifyElementPresent('eventString', 'DidChangeView', | |
343 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | |
344 | |
345 # Simulate mouse click on event module. | |
346 js_code = self._CreateJSToSimulateMouseclick() | |
347 self.ExecuteJavascript(js_code, tab_index) | |
348 | |
349 # Check if 'eventString' has handled above mouse click. | |
350 success = self.WaitUntil( | |
351 lambda: re.search('DidHandleInputEvent', self.GetDOMValue( | |
352 'document.getElementById("eventString").innerHTML', | |
353 tab_index)).group(), expect_retval='DidHandleInputEvent') | |
354 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
355 | |
356 def _VerifyMultithreadedInputEventsExample(self, tab_index, name, url): | |
357 """Verify Input Events Example. | |
358 | |
359 Args: | |
360 tab_index: Tab index integer that the example is on. | |
361 name: A string name of the example. | |
362 url: A string url of the example. | |
363 """ | |
364 success = self.WaitUntil( | |
365 lambda: bool(self.GetDOMValue( | |
366 'document.getElementById("eventString").innerHTML', | |
367 tab_index).find('DidChangeView') + 1)) | |
368 | |
369 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
370 | |
371 # Simulate mouse click on event module. | |
372 js_code = self._CreateJSToSimulateMouseclick() | |
373 self.ExecuteJavascript(js_code, tab_index) | |
374 | |
375 # Check if above mouse click is handled. | |
376 success = self._VerifyElementPresent('eventString', 'Mouse event', | |
377 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | |
378 | |
379 # Kill worker thread and queue | |
380 js_code = """ | |
381 document.getElementsByTagName('button')[0].click(); | |
382 window.domAutomationController.send('done'); | |
383 """ | |
384 self.ExecuteJavascript(js_code, tab_index) | |
385 | |
386 # Check if main thread has cancelled queue. | |
387 success = self._VerifyElementPresent('eventString', 'Received cancel', | |
388 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | |
389 | |
390 # Simulate mouse click on event module. | |
391 js_code = self._CreateJSToSimulateMouseclick() | |
392 self.ExecuteJavascript(js_code, tab_index) | |
393 | |
394 # Check if above mouse click is not handled after killing worker thread. | |
395 def _CheckMouseClickEventStatus(): | |
396 return self.GetDOMValue( | |
397 'document.getElementById("eventString").innerHTML', | |
398 tab_index).find('Mouse event', self.GetDOMValue( | |
399 'document.getElementById("eventString").innerHTML', tab_index).find( | |
400 'Received cancel')) | |
401 | |
402 success = self.WaitUntil(_CheckMouseClickEventStatus, expect_retval=-1) | |
403 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
404 | |
405 def _VerifyFileIoExample(self, tab_index, name, url): | |
406 """Verify File IO Example. | |
407 | |
408 Args: | |
409 tab_index: Tab index integer that the example is on. | |
410 name: A string name of the example. | |
411 url: A string url of the example. | |
412 """ | |
413 def _CheckStatus(substring_expected, fail_msg): | |
414 self.assertTrue( | |
415 self.WaitUntil( | |
416 lambda: self.GetDOMValue( | |
417 'document.getElementById("statusField").innerHTML', tab_index)\ | |
418 .find(substring_expected) != -1, expect_retval=True), | |
419 msg='Example %s failed. URL: %s. Reason: %s' % (name, url, fail_msg)) | |
420 | |
421 # Give permission to use file system by clicking infobar OK | |
422 infobar_index = test_utils.WaitForInfobarTypeAndGetIndex(self, | |
423 'confirm_infobar', 0, tab_index) | |
424 self.PerformActionOnInfobar('accept', infobar_index, 0, tab_index) | |
425 _CheckStatus('Ready!', 'NaCl module load') | |
426 | |
427 # Check that deleting non-existing files gives file not found | |
428 js_code = """ | |
429 document.getElementById('file_name').value = '/abc'; | |
430 document.getElementById('file_editor').value = 'test'; | |
431 document.getElementById('delete_but').click(); | |
432 window.domAutomationController.send('done'); | |
433 """ | |
434 self.ExecuteJavascript(js_code, tab_index) | |
435 _CheckStatus('File not found', 'Delete non-existing') | |
436 | |
437 # Check that saving works | |
438 js_code = """ | |
439 document.getElementById('save_but').click(); | |
440 window.domAutomationController.send('done'); | |
441 """ | |
442 self.ExecuteJavascript(js_code, tab_index) | |
443 _CheckStatus('Save successful', 'Save test') | |
444 | |
445 # Check that we load what we saved | |
446 js_code = """ | |
447 document.getElementById('file_editor').value = 'different'; | |
448 document.getElementById('load_but').click(); | |
449 window.domAutomationController.send('done'); | |
450 """ | |
451 self.ExecuteJavascript(js_code, tab_index) | |
452 _CheckStatus('Load complete', 'Load test') | |
453 self.assertTrue( | |
454 self.GetDOMValue('document.getElementById("file_editor").value', | |
455 tab_index).find('test') != -1, msg='Loaded wrong text or failed') | |
456 | |
457 # Check that we delete files successfully | |
458 js_code = """ | |
459 document.getElementById('delete_but').click(); | |
460 window.domAutomationController.send('done'); | |
461 """ | |
462 self.ExecuteJavascript(js_code, tab_index) | |
463 _CheckStatus('File deleted', 'Delete test') | |
464 | |
465 # Check that file is deleted and load produces not found | |
466 js_code = """ | |
467 document.getElementById('load_but').click(); | |
468 window.domAutomationController.send('done'); | |
469 """ | |
470 self.ExecuteJavascript(js_code, tab_index) | |
471 _CheckStatus('File not found', 'Load deleted test') | |
472 | |
473 def _VerifyWebSocketExample(self, tab_index, name, url): | |
474 """Verify Web Socket Open Example. | |
475 | |
476 Args: | |
477 tab_index: Tab index integer that the example is on. | |
478 name: A string name of the example. | |
479 url: A string url of the example. | |
480 """ | |
481 # Check if example is loaded. | |
482 success = self.WaitUntil( | |
483 lambda: self.GetDOMValue( | |
484 'document.getElementById("statusField").innerHTML', tab_index), | |
485 expect_retval='SUCCESS') | |
486 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
487 | |
488 # Simulate clicking on Connect button to establish a connection. | |
489 js_code = """ | |
490 document.getElementsByTagName('input')[1].click(); | |
491 window.domAutomationController.send('done'); | |
492 """ | |
493 self.ExecuteJavascript(js_code, tab_index) | |
494 | |
495 # Check if connected | |
496 success = self._VerifyElementPresent('log', 'connected', tab_index, | |
497 msg='Example %s failed. URL: %s' % (name, url)) | |
498 | |
499 # Simulate clicking on Send button to send text message in log. | |
500 js_code = """ | |
501 document.getElementsByTagName('input')[3].click(); | |
502 window.domAutomationController.send('done'); | |
503 """ | |
504 self.ExecuteJavascript(js_code, tab_index) | |
505 success = self.WaitUntil( | |
506 lambda: bool(re.search('send:', self.GetDOMValue( | |
507 'document.getElementById("log").textContent', tab_index)))) | |
508 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
509 | |
510 def _VerifyDynamicLibraryOpen(self, tab_index, name, url): | |
511 """Verify Dynamic Library Open Example. | |
512 | |
513 Args: | |
514 tab_index: Tab index integer that the example is on. | |
515 name: A string name of the example. | |
516 url: A string url of the example. | |
517 """ | |
518 # Check if example is loaded. | |
519 success = self._VerifyElementPresent('log', 'Eightball loaded!', | |
520 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | |
521 | |
522 # Simulate clicking on ASK button and check answer log for desired answer. | |
523 js_code = """ | |
524 document.getElementsByTagName('input')[1].click(); | |
525 window.domAutomationController.send('done'); | |
526 """ | |
527 self.ExecuteJavascript(js_code, tab_index) | |
528 def _CheckAnswerLog(): | |
529 return bool(re.search(r'NO|YES|42|MAYBE NOT|DEFINITELY|' | |
530 'ASK ME TOMORROW|MAYBE|PARTLY CLOUDY', | |
531 self.GetDOMValue('document.getElementById("log").innerHTML', | |
532 tab_index))) | |
533 | |
534 success = self.WaitUntil(_CheckAnswerLog) | |
535 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
536 | |
537 def _VerifyLoadProgressExample(self, tab_index, name, url): | |
538 """Verify Dynamic Library Open Example. | |
539 | |
540 Args: | |
541 tab_index: Tab index integer that the example is on. | |
542 name: A string name of the example. | |
543 url: A string url of the example. | |
544 """ | |
545 # Check if example loads and displays loading progress. | |
546 success = self.WaitUntil( | |
547 lambda: self.GetDOMValue( | |
548 'document.getElementById("statusField").innerHTML', tab_index), | |
549 timeout=150, expect_retval='SUCCESS') | |
550 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
551 | |
552 def _CheckLoadProgressStatus(): | |
553 return re.search( | |
554 r'(loadstart).+(progress:).+(load).+(loadend).+(lastError:)', | |
555 self.GetDOMValue( | |
556 'document.getElementById("log").innerHTML', tab_index)) | |
557 success = self.WaitUntil(_CheckLoadProgressStatus) | |
558 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
559 | |
560 def _VerifyPiGeneratorExample(self, tab_index, name, url): | |
561 """Verify Pi Generator Example. | |
562 | |
563 Args: | |
564 tab_index: Tab index integer that the example is on. | |
565 name: A string name of the example. | |
566 url: A string url of the example. | |
567 """ | |
568 success = self.WaitUntil( | |
569 lambda: self.GetDOMValue('document.getElementById("pi").value', | |
570 tab_index)[0:3], | |
571 expect_retval='3.1') | |
572 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
573 | |
574 def _VerifySineSynthExample(self, tab_index, name, url): | |
575 """Verify Sine Wave Synthesizer Example. | |
576 | |
577 Args: | |
578 tab_index: Tab index integer that the example is on. | |
579 name: A string name of the example. | |
580 url: A string url of the example. | |
581 """ | |
582 success = self.WaitUntil( | |
583 lambda: self.GetDOMValue( | |
584 'document.getElementById("frequency_field").value', | |
585 tab_index), timeout=150, expect_retval='440') | |
586 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
587 self.ExecuteJavascript( | |
588 'document.body.getElementsByTagName("button")[0].click();' | |
589 'window.domAutomationController.send("done")', | |
590 tab_index) | |
591 | |
592 def _VerifyGetURLExample(self, tab_index, name, url): | |
593 """Verify GetURL Example. | |
594 | |
595 Args: | |
596 tab_index: Tab index integer that the example is on. | |
597 name: A string name of the example. | |
598 url: A string url of the example. | |
599 """ | |
600 success = self.WaitUntil( | |
601 lambda: self.GetDOMValue( | |
602 'document.getElementById("statusField").innerHTML', | |
603 tab_index), timeout=150, expect_retval='SUCCESS') | |
604 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
605 self.ExecuteJavascript( | |
606 'document.getElementById("button").click();' | |
607 'window.domAutomationController.send("done")', | |
608 tab_index) | |
609 success = self._VerifyElementPresent('general_output', 'test passed', | |
610 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | |
611 | |
612 def _CheckForCrashes(self): | |
613 """Check for any browser/tab crashes and hangs.""" | |
614 self.assertTrue(self.GetBrowserWindowCount(), | |
615 msg='Browser crashed, no window is open.') | |
616 | |
617 info = self.GetBrowserInfo() | |
618 breakpad_folder = info['properties']['DIR_CRASH_DUMPS'] | |
619 old_dmp_files = glob.glob(os.path.join(breakpad_folder, '*.dmp')) | |
620 | |
621 # Verify there're no crash dump files. | |
622 for dmp_file in glob.glob(os.path.join(breakpad_folder, '*.dmp')): | |
623 self.assertTrue(dmp_file in old_dmp_files, | |
624 msg='Crash dump %s found' % dmp_file) | |
625 | |
626 # Check for any crashed tabs. | |
627 tabs = info['windows'][0]['tabs'] | |
628 for tab in tabs: | |
629 if tab['url'] != 'about:blank': | |
630 if not self.GetDOMValue('document.body.innerHTML', tab['index']): | |
631 self.fail(msg='Tab crashed on %s' % tab['url']) | |
632 | |
633 def _GetPlatformArchitecture(self): | |
634 """Get platform architecture. | |
635 | |
636 Returns: | |
637 A string representing the platform architecture. | |
638 """ | |
639 if pyauto.PyUITest.IsWin(): | |
640 if os.environ['PROGRAMFILES'] == 'C:\\Program Files (x86)': | |
641 return '64bit' | |
642 else: | |
643 return '32bit' | |
644 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux(): | |
645 if platform.machine() == 'x86_64': | |
646 return '64bit' | |
647 else: | |
648 return '32bit' | |
649 return '32bit' | |
650 | |
651 def _HasPathInTree(self, pattern, is_file, root=os.curdir): | |
652 """Recursively checks if a file/directory matching a pattern exists. | |
653 | |
654 Args: | |
655 pattern: Pattern of file or directory name. | |
656 is_file: True if looking for file, or False if looking for directory. | |
657 root: Directory to start looking. | |
658 | |
659 Returns: | |
660 True, if root contains the directory name pattern, or | |
661 False otherwise. | |
662 """ | |
663 for path, dirs, files in os.walk(os.path.abspath(root)): | |
664 if is_file: | |
665 if len(fnmatch.filter(files, pattern)): | |
666 return True | |
667 else: | |
668 if len(fnmatch.filter(dirs, pattern)): | |
669 return True | |
670 return False | |
671 | |
672 def _HasAllSystemRequirements(self): | |
673 """Verify NaCl SDK installation system requirements. | |
674 | |
675 Returns: | |
676 True, if system passed requirements, or | |
677 False otherwise. | |
678 """ | |
679 # Check python version. | |
680 if sys.version_info[0:2] < (2, 6): | |
681 return False | |
682 | |
683 # Check OS requirements. | |
684 if pyauto.PyUITest.IsMac(): | |
685 mac_min_version = version.StrictVersion('10.6') | |
686 mac_version = version.StrictVersion(platform.mac_ver()[0]) | |
687 if mac_version < mac_min_version: | |
688 return False | |
689 elif pyauto.PyUITest.IsWin(): | |
690 if not (self.IsWin7() or self.IsWinVista() or self.IsWinXP()): | |
691 return False | |
692 elif pyauto.PyUITest.IsLinux(): | |
693 pass # TODO(chrisphan): Check Lin requirements. | |
694 else: | |
695 return False | |
696 | |
697 # Check for Chrome version compatibility. | |
698 # NaCl supports Chrome 10 and higher builds. | |
699 min_required_chrome_build = self._settings['min_required_chrome_build'] | |
700 browser_info = self.GetBrowserInfo() | |
701 chrome_version = browser_info['properties']['ChromeVersion'] | |
702 chrome_build = int(chrome_version.split('.')[0]) | |
703 return chrome_build >= min_required_chrome_build | |
704 | |
705 def _DownloadNaClSDK(self): | |
706 """Download NaCl SDK.""" | |
707 self._temp_dir = tempfile.mkdtemp() | |
708 dl_file = urllib2.urlopen(self._settings['post_sdk_zip']) | |
709 file_path = os.path.join(self._temp_dir, 'nacl_sdk.zip') | |
710 | |
711 try: | |
712 f = open(file_path, 'wb') | |
713 f.write(dl_file.read()) | |
714 except IOError: | |
715 self.fail(msg='Cannot open %s.' % file_path) | |
716 finally: | |
717 f.close() | |
718 | |
719 def _ExtractNaClSDK(self): | |
720 """Extract NaCl SDK.""" | |
721 source_file = os.path.join(self._temp_dir, 'nacl_sdk.zip') | |
722 if zipfile.is_zipfile(source_file): | |
723 zip = zipfile.ZipFile(source_file, 'r') | |
724 zip.extractall(self._extracted_sdk_path) | |
725 else: | |
726 self.fail(msg='%s is not a valid zip file' % source_file) | |
727 | |
728 def _IsURLAlive(self, url): | |
729 """Test if URL is alive.""" | |
730 try: | |
731 urllib2.urlopen(url) | |
732 except: | |
733 return False | |
734 return True | |
735 | |
736 def _CloseHTTPServer(self, proc=None): | |
737 """Close HTTP server. | |
738 | |
739 Args: | |
740 proc: Process that opened the HTTP server. | |
741 proc is None when there is no pointer to HTTP server process. | |
742 """ | |
743 if not self._IsURLAlive('http://localhost:5103'): | |
744 return | |
745 response = urllib2.urlopen('http://localhost:5103') | |
746 html = response.read() | |
747 if not 'Native Client' in html: | |
748 self.fail(msg='Port 5103 is in use.') | |
749 | |
750 urllib2.urlopen('http://localhost:5103?quit=1') | |
751 success = self.WaitUntil( | |
752 lambda: self._IsURLAlive('http://localhost:5103'), | |
753 retry_sleep=1, expect_retval=False) | |
754 if not success: | |
755 if not proc: | |
756 self.fail(msg='Failed to close HTTP server.') | |
757 else: | |
758 if proc.poll() == None: | |
759 try: | |
760 proc.kill() | |
761 except: | |
762 self.fail(msg='Failed to close HTTP server.') | |
763 | |
764 def _SearchNaClSDKFile(self, search_list): | |
765 """Search NaCl SDK file for example files and directories in Windows. | |
766 | |
767 Args: | |
768 search_list: A list of strings, representing file and | |
769 directory names for which to search. | |
770 """ | |
771 missing_items = [] | |
772 for name in search_list: | |
773 is_file = name.find('/') < 0 | |
774 if not is_file: | |
775 name = name.replace('/', '') | |
776 if not self._HasPathInTree(name, is_file, self._extracted_sdk_path): | |
777 missing_items.append(name) | |
778 self.assertEqual(len(missing_items), 0, | |
779 msg='Missing files or directories: %s' % | |
780 ', '.join(map(str, missing_items))) | |
781 | |
782 def ExtraChromeFlags(self): | |
783 """Ensures Nacl is enabled. | |
784 | |
785 Returns: | |
786 A list of extra flags to pass to Chrome when it is launched. | |
787 """ | |
788 extra_chrome_flags = [ | |
789 '--enable-nacl', | |
790 '--enable-nacl-exception-handling', | |
791 '--nacl-gdb', | |
792 ] | |
793 return pyauto.PyUITest.ExtraChromeFlags(self) + extra_chrome_flags | |
794 | |
795 if __name__ == '__main__': | |
796 pyauto_functional.Main() | |
OLD | NEW |