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 6import copy 7import ctypes 8from distutils import version 9import fnmatch 10import glob 11import hashlib 12import logging 13import os 14import platform 15import re 16import shutil 17import subprocess 18import sys 19import tempfile 20import urllib2 21import xml.dom.minidom 22import zipfile 23 24import pyauto_functional # Must be imported before pyauto. 25import pyauto 26import pyauto_utils 27import test_utils 28 29 30class 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 795if __name__ == '__main__': 796 pyauto_functional.Main() 797