| 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 |