OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import copy | 6 import copy |
7 import ctypes | 7 import ctypes |
8 from distutils import version | 8 from distutils import version |
9 import fnmatch | 9 import fnmatch |
10 import glob | 10 import glob |
11 import hashlib | 11 import hashlib |
12 import logging | 12 import logging |
13 import os | 13 import os |
14 import platform | 14 import platform |
15 import re | |
16 import shutil | 15 import shutil |
17 import subprocess | 16 import subprocess |
18 import sys | 17 import sys |
| 18 import tarfile |
19 import tempfile | 19 import tempfile |
20 import urllib2 | 20 import urllib2 |
21 import xml.dom.minidom | 21 import xml.dom.minidom |
22 import zipfile | |
23 | 22 |
24 import pyauto_functional # Must be imported before pyauto. | 23 import pyauto_functional # Must be imported before pyauto. |
25 import pyauto | 24 import pyauto |
26 import pyauto_utils | 25 import pyauto_utils |
27 | 26 |
28 | 27 |
29 class NaClSDKTest(pyauto.PyUITest): | 28 class NaClSDKTest(pyauto.PyUITest): |
30 """Tests for the NaCl SDK.""" | 29 """Tests for the NaCl SDK.""" |
31 _extracted_sdk_path = None | 30 _extracted_sdk_path = None |
32 _temp_dir = None | 31 _temp_dir = None |
33 _pepper_versions = [] | |
34 _updated_pepper_versions = [] | |
35 _latest_updated_pepper_versions = [] | |
36 _settings = { | 32 _settings = { |
| 33 'release_win_sdk_url': 'http://commondatastorage.googleapis.com/' |
| 34 'nativeclient-mirror/nacl/nacl_sdk/staging/naclsdk_win.exe', |
| 35 'release_mac_sdk_url': 'http://commondatastorage.googleapis.com/' |
| 36 'nativeclient-mirror/nacl/nacl_sdk/staging/naclsdk_mac.tgz', |
| 37 'release_lin_sdk_url': 'http://commondatastorage.googleapis.com/' |
| 38 'nativeclient-mirror/nacl/nacl_sdk/staging/naclsdk_linux.tgz', |
| 39 'expected_md5_url': 'http://commondatastorage.googleapis.com/' |
| 40 'nativeclient-mirror', |
| 41 'release_win_expected_md5_key': 'nacl/nacl_sdk/staging/naclsdk_win.exe', |
| 42 'release_mac_expected_md5_key': 'nacl/nacl_sdk/staging/naclsdk_mac.tgz', |
| 43 'release_lin_expected_md5_key': 'nacl/nacl_sdk/staging/' |
| 44 'naclsdk_linux.tgz', |
37 'post_sdk_download_url': 'http://code.google.com/chrome/nativeclient/' | 45 'post_sdk_download_url': 'http://code.google.com/chrome/nativeclient/' |
38 'docs/download.html', | 46 'docs/download.html', |
39 'post_sdk_zip': 'http://commondatastorage.googleapis.com/' | 47 'post_win_sdk_url': 'http://commondatastorage.googleapis.com/' |
40 'nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip', | 48 'nativeclient-mirror/nacl/nacl_sdk/naclsdk_win.exe', |
| 49 'post_mac_sdk_url': 'http://commondatastorage.googleapis.com/' |
| 50 'nativeclient-mirror/nacl/nacl_sdk/naclsdk_mac.tgz', |
| 51 'post_lin_sdk_url': 'http://commondatastorage.googleapis.com/' |
| 52 'nativeclient-mirror/nacl/nacl_sdk/naclsdk_linux.tgz', |
41 'min_required_chrome_build': 14, | 53 'min_required_chrome_build': 14, |
| 54 'gallery_examples': { |
| 55 'life': 'http://nacl-gallery.appspot.com/life/life.html', |
| 56 'hello_world': 'http://nacl-gallery.appspot.com/hello_world/' |
| 57 'hello_world.html', |
| 58 'pi_generator': 'http://nacl-gallery.appspot.com/pi_generator/' |
| 59 'pi_generator.html', |
| 60 'sine_synth': 'http://nacl-gallery.appspot.com/sine_synth/' |
| 61 'sine_synth.html' |
| 62 }, |
| 63 'prerelease_gallery': { |
| 64 'hello_world': 'http://4.nacl-gallery.appspot.com/hello_world/' |
| 65 'hello_world.html', |
| 66 'hello_world_c': 'http://4.nacl-gallery.appspot.com/hello_world_c/' |
| 67 'hello_world.html', |
| 68 'life': 'http://4.nacl-gallery.appspot.com/life/life.html', |
| 69 'pi_generator': 'http://4.nacl-gallery.appspot.com/pi_generator/' |
| 70 'pi_generator.html', |
| 71 'sine_synth': 'http://4.nacl-gallery.appspot.com/sine_synth/' |
| 72 'sine_synth.html', |
| 73 'geturl': 'http://4.nacl-gallery.appspot.com/geturl/geturl.html' |
| 74 } |
42 } | 75 } |
43 | 76 |
44 def tearDown(self): | 77 def tearDown(self): |
45 pyauto.PyUITest.tearDown(self) | 78 pyauto.PyUITest.tearDown(self) |
46 self._RemoveDownloadedTestFile() | 79 self._RemoveDownloadedTestFile() |
47 | 80 |
48 def testNaClSDK(self): | 81 def testNaClSDK(self): |
49 """Verify that NaCl SDK is working properly.""" | 82 """Verify that NaCl SDK is working properly.""" |
50 if not self._HasAllSystemRequirements(): | 83 if not self._HasAllSystemRequirements(): |
51 logging.info('System does not meet the requirements.') | 84 logging.info('System does not meet the requirements.') |
52 return | 85 return |
53 self._extracted_sdk_path = tempfile.mkdtemp() | 86 self._extracted_sdk_path = tempfile.mkdtemp() |
| 87 |
54 self._VerifyDownloadLinks() | 88 self._VerifyDownloadLinks() |
55 self._VerifyNaClSDKInstaller() | 89 self._VerifyNaClSDKInstaller() |
56 self._VerifyInstall() | 90 self._VerifyBuildStubProject() |
57 self._VerifyUpdate() | |
58 self._LaunchServerAndVerifyExamples() | 91 self._LaunchServerAndVerifyExamples() |
| 92 self._VerifyRebuildExamples() |
| 93 self._VerifySelldrAndNcval() |
| 94 |
| 95 def testVerifyNaClSDKChecksum(self): |
| 96 """Verify NaCl SDK Checksum.""" |
| 97 if not self._HasAllSystemRequirements(): |
| 98 logging.info('System does not meet the requirements.') |
| 99 return |
| 100 |
| 101 self._DownloadNaClSDK() |
| 102 |
| 103 if pyauto.PyUITest.IsWin(): |
| 104 expected_md5_key = self._settings['release_win_expected_md5_key'] |
| 105 file_path = os.path.join(self._temp_dir, 'naclsdk_win.exe') |
| 106 elif pyauto.PyUITest.IsMac(): |
| 107 expected_md5_key = self._settings['release_mac_expected_md5_key'] |
| 108 file_path = os.path.join(self._temp_dir, 'naclsdk_mac.tgz') |
| 109 elif pyauto.PyUITest.IsLinux(): |
| 110 expected_md5_key = self._settings['release_lin_expected_md5_key'] |
| 111 file_path = os.path.join(self._temp_dir, 'naclsdk_linux.tgz') |
| 112 else: |
| 113 self.fail(msg='NaCl SDK does not support this OS.') |
| 114 |
| 115 # Get expected MD5. |
| 116 expected_md5_url = self._settings['expected_md5_url'] |
| 117 response = urllib2.urlopen(expected_md5_url) |
| 118 dom = xml.dom.minidom.parseString(response.read()) |
| 119 dom_content = dom.getElementsByTagName('Contents') |
| 120 expected_md5 = None |
| 121 for con in dom_content: |
| 122 if (self._GetXMLNodeData(con.getElementsByTagName('Key')[0].childNodes) |
| 123 == expected_md5_key): |
| 124 node = con.getElementsByTagName('ETag')[0].childNodes |
| 125 expected_md5 = self._GetXMLNodeData(node).strip('"') |
| 126 self.assertTrue(expected_md5, |
| 127 msg='Cannot get expected MD5 from %s.' % expected_md5_url) |
| 128 |
| 129 md5 = hashlib.md5() |
| 130 md5.update(open(file_path).read()) |
| 131 md5_sum = md5.hexdigest() |
| 132 self.assertEqual(expected_md5, md5_sum, |
| 133 msg='Unexpected checksum. Expected: %s, got: %s' |
| 134 % (expected_md5, md5_sum)) |
| 135 |
| 136 def testVerifyNaClPlugin(self): |
| 137 """Verify NaCl plugin.""" |
| 138 if not self._HasAllSystemRequirements(): |
| 139 logging.info('System does not meet the requirements.') |
| 140 return |
| 141 self._OpenExamplesAndStartTest( |
| 142 self._settings['gallery_examples']) |
| 143 |
| 144 def testVerifyPrereleaseGallery(self): |
| 145 """Verify Pre-release gallery examples.""" |
| 146 if not self._HasAllSystemRequirements(): |
| 147 logging.info('System does not meet the requirements.') |
| 148 return |
| 149 self._OpenExamplesAndStartTest( |
| 150 self._settings['prerelease_gallery']) |
59 | 151 |
60 def _VerifyDownloadLinks(self): | 152 def _VerifyDownloadLinks(self): |
61 """Verify the download links. | 153 """Verify the download links.""" |
62 | |
63 Simply verify that NaCl download links exist in html page. | |
64 """ | |
65 html = None | 154 html = None |
66 for i in xrange(3): | 155 for i in xrange(3): |
67 try: | 156 try: |
68 html = urllib2.urlopen(self._settings['post_sdk_download_url']).read() | 157 html = urllib2.urlopen(self._settings['post_sdk_download_url']).read() |
69 break | 158 break |
70 except: | 159 except: |
71 pass | 160 pass |
72 self.assertTrue(html, | 161 self.assertTrue(html, |
73 msg='Cannot open URL: %s' % | 162 msg='Cannot open URL: %s' % |
74 self._settings['post_sdk_download_url']) | 163 self._settings['post_sdk_download_url']) |
75 sdk_url = self._settings['post_sdk_zip'] | 164 |
76 self.assertTrue(sdk_url in html, | 165 # Make sure the correct URL is under the correct label. |
77 msg='Missing SDK download URL: %s' % sdk_url) | 166 if pyauto.PyUITest.IsWin(): |
| 167 win_sdk_url = self._settings['post_win_sdk_url'] |
| 168 win_url_index = html.find(win_sdk_url) |
| 169 self.assertTrue(win_url_index > -1, |
| 170 msg='Missing SDK download URL: %s' % win_sdk_url) |
| 171 win_keyword_index = html.rfind('Windows', 0, win_url_index) |
| 172 self.assertTrue(win_keyword_index > -1, |
| 173 msg='Misplaced download link: %s' % win_sdk_url) |
| 174 elif pyauto.PyUITest.IsMac(): |
| 175 mac_sdk_url = self._settings['post_mac_sdk_url'] |
| 176 mac_url_index = html.find(mac_sdk_url) |
| 177 self.assertTrue(mac_url_index > -1, |
| 178 msg='Missing SDK download URL: %s' % mac_sdk_url) |
| 179 mac_keyword_index = html.rfind('Macintosh', 0, mac_url_index) |
| 180 self.assertTrue(mac_keyword_index > -1, |
| 181 msg='Misplaced download link: %s' % mac_sdk_url) |
| 182 elif pyauto.PyUITest.IsLinux(): |
| 183 lin_sdk_url = self._settings['post_lin_sdk_url'] |
| 184 lin_url_index = html.find(lin_sdk_url) |
| 185 self.assertTrue(lin_url_index > -1, |
| 186 msg='Missing SDK download URL: %s' % lin_sdk_url) |
| 187 lin_keyword_index = html.rfind('Linux', 0, lin_url_index) |
| 188 self.assertTrue(lin_keyword_index > -1, |
| 189 msg='Misplaced download link: %s' % lin_sdk_url) |
| 190 else: |
| 191 self.fail(msg='NaCl SDK does not support this OS.') |
78 | 192 |
79 def _VerifyNaClSDKInstaller(self): | 193 def _VerifyNaClSDKInstaller(self): |
80 """Verify NaCl SDK installer.""" | 194 """Verify NaCl SDK installer.""" |
81 search_list = [ | 195 search_list = [ |
82 'sdk_cache/', | 196 'build.scons', |
83 'sdk_tools/', | 197 'favicon.ico', |
84 ] | 198 'geturl/', |
| 199 'hello_world/', |
| 200 'hello_world_c/', |
| 201 'httpd.py', |
| 202 'index.html', |
| 203 'nacl_sdk_scons/', |
| 204 'pi_generator/', |
| 205 'scons', |
| 206 'sine_synth/' |
| 207 ] |
| 208 |
85 mac_lin_additional_search_items = [ | 209 mac_lin_additional_search_items = [ |
86 'naclsdk', | 210 'sel_ldr_x86_32', |
87 ] | 211 'sel_ldr_x86_64', |
| 212 'ncval_x86_32', |
| 213 'ncval_x86_64' |
| 214 ] |
| 215 |
88 win_additional_search_items = [ | 216 win_additional_search_items = [ |
89 'naclsdk.bat' | 217 'httpd.cmd', |
90 ] | 218 'sel_ldr_x86_32.exe', |
| 219 'sel_ldr_x86_64.exe', |
| 220 'ncval_x86_32.exe', |
| 221 'ncval_x86_64.exe' |
| 222 ] |
| 223 |
91 self._DownloadNaClSDK() | 224 self._DownloadNaClSDK() |
92 self._ExtractNaClSDK() | 225 |
93 if pyauto.PyUITest.IsWin(): | 226 if pyauto.PyUITest.IsWin(): |
94 self._SearchNaClSDKFile( | 227 self._ExtractNaClSDK() |
| 228 self._SearchNaClSDKFileWindows( |
95 search_list + win_additional_search_items) | 229 search_list + win_additional_search_items) |
96 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux(): | 230 elif pyauto.PyUITest.IsMac(): |
97 self._SearchNaClSDKFile( | 231 source_file = os.path.join(self._temp_dir, 'naclsdk_mac.tgz') |
98 search_list + mac_lin_additional_search_items) | 232 self._SearchNaClSDKTarFile(search_list + mac_lin_additional_search_items, |
| 233 source_file) |
| 234 self._ExtractNaClSDK() |
| 235 elif pyauto.PyUITest.IsLinux(): |
| 236 source_file = os.path.join(self._temp_dir, 'naclsdk_linux.tgz') |
| 237 self._SearchNaClSDKTarFile(search_list + mac_lin_additional_search_items, |
| 238 source_file) |
| 239 self._ExtractNaClSDK() |
99 else: | 240 else: |
100 self.fail(msg='NaCl SDK does not support this OS.') | 241 self.fail(msg='NaCl SDK does not support this OS.') |
101 | 242 |
102 def _VerifyInstall(self): | 243 def _VerifyBuildStubProject(self): |
103 """Install NACL sdk.""" | 244 """Build stub project.""" |
104 # Executing naclsdk(.bat) list | 245 stub_project_files = [ |
105 if pyauto.PyUITest.IsWin(): | 246 'build.scons', |
106 source_file = os.path.join( | 247 'scons' |
107 self._extracted_sdk_path, 'nacl_sdk', 'naclsdk.bat') | 248 ] |
108 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux(): | 249 project_template_path = self._GetDirectoryPath('project_templates', |
109 source_file = os.path.join( | 250 self._extracted_sdk_path) |
110 self._extracted_sdk_path, 'nacl_sdk', 'naclsdk') | 251 examples_path = self._GetDirectoryPath('examples', |
111 subprocess.call(['chmod', '-R', '755', self._extracted_sdk_path]) | 252 self._extracted_sdk_path) |
112 else: | 253 init_project_path = os.path.join(project_template_path, 'init_project.py') |
113 self.fail(msg='NaCl SDK does not support this OS.') | 254 |
114 subprocess.Popen([source_file, 'list'], | 255 # Build a C project. |
115 stdout=subprocess.PIPE, | 256 subprocess.call( |
116 stderr=subprocess.PIPE).communicate() | 257 ['python', init_project_path, '-n', 'hello_c', '-c', '-d', |
117 | 258 examples_path], stdout=subprocess.PIPE) |
118 def _VerifyUpdate(self): | 259 |
119 """Update NACL sdk""" | 260 hello_c_path = os.path.join(examples_path, 'hello_c') |
120 # Executing naclsdk(.bat) update | 261 for file in stub_project_files: |
121 if pyauto.PyUITest.IsWin(): | 262 self.assertTrue(self._HasFile(file, hello_c_path), |
122 source_file = os.path.join(self._extracted_sdk_path, 'nacl_sdk', | 263 msg='Cannot build C stub project.') |
123 'naclsdk.bat') | 264 |
124 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux(): | 265 # Build a C++ project. |
125 source_file = os.path.join(self._extracted_sdk_path, 'nacl_sdk', | 266 subprocess.call( |
126 'naclsdk') | 267 ['python', init_project_path, '-n', 'hello_cc', '-d', |
127 else: | 268 examples_path], stdout=subprocess.PIPE) |
128 self.fail(msg='NaCl SDK does not support this OS.') | 269 |
129 # Executing nacl_sdk(.bat) update to get the latest version. | 270 hello_cc_path = os.path.join(examples_path, 'hello_cc') |
130 updated_output = subprocess.Popen([source_file, 'update'], | 271 for file in stub_project_files: |
131 stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] | 272 self.assertTrue(self._HasFile(file, hello_cc_path), |
132 self._updated_pepper_versions.extend( | 273 msg='Cannot build C++ stub project.') |
133 re.findall('Updating bundle (pepper_[0-9]{2})', updated_output)) | |
134 self._updated_pepper_versions = list(set(self._updated_pepper_versions)) | |
135 self._updated_pepper_versions.sort(key=str.lower) | |
136 updated_pepper_versions_len = len(self._updated_pepper_versions) | |
137 self._latest_updated_pepper_versions = filter( | |
138 lambda x: x >= 'pepper_18', self._updated_pepper_versions) | |
139 | 274 |
140 def _LaunchServerAndVerifyExamples(self): | 275 def _LaunchServerAndVerifyExamples(self): |
141 """Start local HTTP server and verify examples.""" | 276 """Start local HTTP server and verify examples.""" |
142 if self._ChromeAndPepperVersion(self._latest_updated_pepper_versions[0]): | 277 # Make sure server is not open. |
143 examples_path = os.path.join(self._extracted_sdk_path, 'nacl_sdk', | 278 if self._IsURLAlive('http://localhost:5103'): |
144 self._latest_updated_pepper_versions[0], | 279 self._CloseHTTPServer() |
145 'examples') | 280 |
146 # Close server if it's already open. | 281 # Start HTTP server. |
147 if self._IsURLAlive('http://localhost:5103'): | 282 examples_path = self._GetDirectoryPath('examples', |
148 self._CloseHTTPServer() | 283 self._extracted_sdk_path) |
149 # Launch local http server. | 284 if pyauto.PyUITest.IsWin(): |
150 proc = subprocess.Popen(['make RUN'], shell=True, cwd=examples_path) | 285 http_path = os.path.join(examples_path, 'httpd.cmd') |
151 self.WaitUntil( | 286 proc = subprocess.Popen([http_path], cwd=examples_path) |
152 lambda: self._IsURLAlive('http://localhost:5103'), | 287 else: |
153 timeout=150, retry_sleep=1) | 288 http_path = os.path.join(examples_path, 'httpd.py') |
154 | 289 proc = subprocess.Popen(['python', http_path], cwd=examples_path) |
155 examples = { | 290 |
156 'dynamic_library_open': 'http://localhost:5103/dlopen/dlopen.html', | 291 success = self.WaitUntil( |
157 'geturl': 'http://localhost:5103/geturl/geturl.html', | 292 lambda: self._IsURLAlive('http://localhost:5103'), |
158 'input_events': 'http://localhost:5103/input_events' | 293 timeout=30, retry_sleep=1, expect_retval=True) |
159 '/input_events.html', | 294 self.assertTrue(success, |
160 'load_progress': | 295 msg='Cannot open HTTP server. %s' % |
161 'http://localhost:5103/load_progress/load_progress.html', | 296 self.GetActiveTabTitle()) |
162 'multithreaded_input_events': | 297 |
163 'http://localhost:5103/multithreaded_input_events' | 298 examples = { |
164 '/mt_input_events.html', | 299 'hello_world_c': 'http://localhost:5103/hello_world_c/' |
165 'pi_generator': | 300 'hello_world.html', |
166 'http://localhost:5103/pi_generator/pi_generator.html', | 301 'hello_world': 'http://localhost:5103/hello_world/hello_world.html', |
167 'sine_synth': 'http://localhost:5103/sine_synth/sine_synth.html', | 302 'geturl': 'http://localhost:5103/geturl/geturl.html', |
168 'web_socket': | 303 'pi_generator': 'http://localhost:5103/pi_generator/pi_generator.html', |
169 'http://localhost:5103/websocket/websocket.html', | 304 'sine_synth': 'http://localhost:5103/sine_synth/sine_synth.html', |
170 } | 305 } |
171 try: | 306 try: |
172 self._OpenExamplesAndStartTest(examples) | 307 self._OpenExamplesAndStartTest(examples) |
173 finally: | 308 finally: |
174 self._CloseHTTPServer(proc) | 309 self._CloseHTTPServer(proc) |
175 | 310 |
176 else: | 311 def _VerifyRebuildExamples(self): |
177 self.fail(msg='Pepper Version %s doesnot match the Chrome version %s.' | 312 """Re-build the examples and verify they are as expected.""" |
178 % (self._latest_updated_pepper_versions[0], | 313 example_dirs = [ |
179 self.GetBrowserInfo()['properties']['ChromeVersion'])) | 314 'geturl', |
180 | 315 'hello_world', |
181 def _ChromeAndPepperVersion(self, pepper_version='pepper_18'): | 316 'hello_world_c', |
182 """Determine if chrome and pepper version matach""" | 317 'pi_generator', |
183 version_number = re.findall('pepper_([0-9]{2})', pepper_version) | 318 'sine_synth' |
184 browser_info = self.GetBrowserInfo() | 319 ] |
185 chrome_version = browser_info['properties']['ChromeVersion'] | 320 examples_path = self._GetDirectoryPath('examples', |
186 chrome_build = int(chrome_version.split('.')[0]) | 321 self._extracted_sdk_path) |
187 return int(chrome_build) == int(version_number[0]) | 322 |
| 323 scons_path = os.path.join(examples_path, 'scons -c') |
| 324 subprocess.call([scons_path], cwd=examples_path, shell=True) |
| 325 for x in example_dirs: |
| 326 ex_path = os.path.join(examples_path, x) |
| 327 self.assertFalse(self._HasFile('*.nmf', ex_path), |
| 328 msg='Failed running scons -c.') |
| 329 |
| 330 scons_path = os.path.join(examples_path, 'scons') |
| 331 proc = subprocess.Popen([scons_path], cwd=examples_path, |
| 332 stdout=subprocess.PIPE, shell=True) |
| 333 proc.communicate() |
| 334 |
| 335 # Verify each example directory contains .nmf file. |
| 336 for dir in example_dirs: |
| 337 dir = os.path.join(examples_path, dir) |
| 338 if not self._HasFile('*.nmf', dir): |
| 339 self.fail(msg='Failed running scons.') |
| 340 |
| 341 self._LaunchServerAndVerifyExamples() |
| 342 |
| 343 def _VerifySelldrAndNcval(self): |
| 344 """Verify sel_ldr and ncval.""" |
| 345 architecture = self._GetPlatformArchitecture() |
| 346 scons_arg = None |
| 347 if pyauto.PyUITest.IsWin(): |
| 348 if architecture == '64bit': |
| 349 scons_arg = 'test64' |
| 350 else: |
| 351 scons_arg = 'test32' |
| 352 elif pyauto.PyUITest.IsMac(): |
| 353 scons_arg = 'test64' |
| 354 elif pyauto.PyUITest.IsLinux(): |
| 355 scons_arg = 'test64' |
| 356 |
| 357 examples_path = self._GetDirectoryPath('examples', |
| 358 self._extracted_sdk_path) |
| 359 scons_path = os.path.join(examples_path, 'scons ' + scons_arg) |
| 360 |
| 361 # Build and run the unit test. |
| 362 proc = subprocess.Popen([scons_path], stdout=subprocess.PIPE, |
| 363 shell=True, cwd=examples_path) |
| 364 lines = proc.communicate()[0].splitlines() |
| 365 test_ran = False |
| 366 |
| 367 for line in lines: |
| 368 if 'Check:' in line: |
| 369 self.assertTrue('passed' in line, |
| 370 msg='Nacl-sel_ldr unit test failed.') |
| 371 test_ran = True |
| 372 self.assertTrue(test_ran, |
| 373 msg='Failed to build and run nacl-sel_ldr unit test.') |
| 374 |
| 375 if architecture == '64bit': |
| 376 self.assertTrue( |
| 377 self._HasPathInTree('hello_world_x86_64.nexe', |
| 378 True, root=examples_path), |
| 379 msg='Missing file: hello_world_x86_64.nexe.') |
| 380 else: |
| 381 self.assertTrue( |
| 382 self._HasPathInTree('hello_world_x86_32.nexe', |
| 383 True, root=examples_path), |
| 384 msg='Missing file: hello_world_x86_32.nexe.') |
| 385 |
| 386 # Verify that a mismatch of sel_ldr and .nexe produces an error. |
| 387 toolchain_path = self._GetDirectoryPath('toolchain', |
| 388 self._extracted_sdk_path) |
| 389 bin_path = self._GetDirectoryPath('bin', toolchain_path) |
| 390 hello_world_path = self._GetDirectoryPath('hello_world', examples_path) |
| 391 sel_32_path = os.path.join(bin_path, 'sel_ldr_x86_32') |
| 392 sel_64_path = os.path.join(bin_path, 'sel_ldr_x86_64') |
| 393 nexe_32_path = os.path.join(hello_world_path, 'hello_world_x86_32.nexe') |
| 394 nexe_64_path = os.path.join(hello_world_path, 'hello_world_x86_64.nexe') |
| 395 |
| 396 if architecture == '64bit': |
| 397 success = self._RunProcessAndCheckOutput( |
| 398 [sel_64_path, nexe_32_path], 'Error while loading') |
| 399 else: |
| 400 success = self._RunProcessAndCheckOutput( |
| 401 [sel_32_path, nexe_64_path], 'Error while loading') |
| 402 self.assertTrue(success, |
| 403 msg='Failed to verify sel_ldr and .nexe mismatch.') |
| 404 |
| 405 # Run the appropriate ncval for the platform on the matching .nexe. |
| 406 ncval_32_path = os.path.join(bin_path, 'ncval_x86_32') |
| 407 ncval_64_path = os.path.join(bin_path, 'ncval_x86_64') |
| 408 |
| 409 if architecture == '64bit': |
| 410 success = self._RunProcessAndCheckOutput( |
| 411 [ncval_64_path, nexe_64_path], 'is safe') |
| 412 else: |
| 413 success = self._RunProcessAndCheckOutput( |
| 414 [ncval_32_path, nexe_32_path], 'is safe') |
| 415 self.assertTrue(success, msg='Failed to verify ncval.') |
| 416 |
| 417 # Verify that a mismatch of ncval and .nexe produces an error. |
| 418 if architecture == '64bit': |
| 419 success = self._RunProcessAndCheckOutput( |
| 420 [ncval_64_path, nexe_32_path], 'is safe', is_in=False) |
| 421 else: |
| 422 success = self._RunProcessAndCheckOutput( |
| 423 [ncval_32_path, nexe_64_path], 'is safe', is_in=False) |
| 424 self.assertTrue(success, msg='Failed to verify ncval and .nexe mismatch.') |
188 | 425 |
189 def _RemoveDownloadedTestFile(self): | 426 def _RemoveDownloadedTestFile(self): |
190 """Delete downloaded files and dirs from downloads directory.""" | 427 """Delete downloaded files and dirs from downloads directory.""" |
191 if self._extracted_sdk_path and os.path.exists(self._extracted_sdk_path): | 428 if self._extracted_sdk_path and os.path.exists(self._extracted_sdk_path): |
192 self._CloseHTTPServer() | 429 self._CloseHTTPServer() |
193 | 430 |
194 def _RemoveFile(): | 431 def _RemoveFile(): |
195 shutil.rmtree(self._extracted_sdk_path, ignore_errors=True) | 432 shutil.rmtree(self._extracted_sdk_path, ignore_errors=True) |
196 return os.path.exists(self._extracted_sdk_path) | 433 return os.path.exists(self._extracted_sdk_path) |
197 | 434 |
198 success = self.WaitUntil(_RemoveFile, retry_sleep=2, | 435 success = self.WaitUntil(_RemoveFile, retry_sleep=2, expect_retval=False) |
199 expect_retval=False) | |
200 self.assertTrue(success, | 436 self.assertTrue(success, |
201 msg='Cannot remove %s' % self._extracted_sdk_path) | 437 msg='Cannot remove %s' % self._extracted_sdk_path) |
202 | 438 |
203 if self._temp_dir: | 439 if self._temp_dir: |
204 pyauto_utils.RemovePath(self._temp_dir) | 440 pyauto_utils.RemovePath(self._temp_dir) |
205 | 441 |
| 442 def _RunProcessAndCheckOutput(self, args, look_for, is_in=True): |
| 443 """Run process and look for string in output. |
| 444 |
| 445 Args: |
| 446 args: Argument strings to pass to subprocess. |
| 447 look_for: The string to search in output. |
| 448 is_in: True if checking if param look_for is in output. |
| 449 False if checking if param look_for is not in output. |
| 450 |
| 451 Returns: |
| 452 True, if output contains parameter |look_for| and |is_in| is True, or |
| 453 False otherwise. |
| 454 """ |
| 455 proc = subprocess.Popen(args, stdout=subprocess.PIPE, |
| 456 stderr=subprocess.PIPE) |
| 457 (stdout, stderr) = proc.communicate() |
| 458 lines = (stdout + stderr).splitlines() |
| 459 for line in lines: |
| 460 if look_for in line: |
| 461 return is_in |
| 462 return not is_in |
| 463 |
206 def _OpenExamplesAndStartTest(self, examples): | 464 def _OpenExamplesAndStartTest(self, examples): |
207 """Open each example and verify that it's working. | 465 """Open each example and verify that it's working. |
208 | 466 |
209 Args: | 467 Args: |
210 examples: A dict of name to url of examples. | 468 examples: A dict of name to url of examples. |
211 """ | 469 """ |
| 470 self._EnableNaClPlugin() |
| 471 |
212 # Open all examples. | 472 # Open all examples. |
213 for name, url in examples.items(): | 473 for name, url in examples.items(): |
214 self.AppendTab(pyauto.GURL(url)) | 474 self.AppendTab(pyauto.GURL(url)) |
215 self._CheckForCrashes() | 475 self._CheckForCrashes() |
216 | 476 |
217 # Verify all examples are working. | 477 # Verify all examples are working. |
218 for name, url in examples.items(): | 478 for name, url in examples.items(): |
219 self._VerifyAnExample(name, url) | 479 self._VerifyAnExample(name, url) |
220 self._CheckForCrashes() | 480 self._CheckForCrashes() |
221 | 481 |
| 482 # Reload all examples. |
| 483 for _ in range(2): |
| 484 for tab_index in range(self.GetTabCount()): |
| 485 self.GetBrowserWindow(0).GetTab(tab_index).Reload() |
| 486 self._CheckForCrashes() |
| 487 |
| 488 # Verify all examples are working. |
| 489 for name, url in examples.items(): |
| 490 self._VerifyAnExample(name, url) |
| 491 self._CheckForCrashes() |
| 492 |
222 # Close each tab, check for crashes and verify all open | 493 # Close each tab, check for crashes and verify all open |
223 # examples operate correctly. | 494 # examples operate correctly. |
224 tab_count = self.GetTabCount() | 495 tab_count = self.GetTabCount() |
225 for index in xrange(tab_count - 1, 0, -1): | 496 for index in xrange(tab_count - 1, 0, -1): |
226 self.GetBrowserWindow(0).GetTab(index).Close(True) | 497 self.GetBrowserWindow(0).GetTab(index).Close(True) |
227 self._CheckForCrashes() | 498 self._CheckForCrashes() |
228 | 499 |
229 tabs = self.GetBrowserInfo()['windows'][0]['tabs'] | 500 tabs = self.GetBrowserInfo()['windows'][0]['tabs'] |
230 for tab in tabs: | 501 for tab in tabs: |
231 if tab['index'] > 0: | 502 if tab['index'] > 0: |
232 for name, url in examples.items(): | 503 for name, url in examples.items(): |
233 if url == tab['url']: | 504 if url == tab['url']: |
234 self._VerifyAnExample(name, url) | 505 self._VerifyAnExample(name, url) |
235 break | 506 break |
236 | 507 |
237 def _VerifyAnExample(self, name, url): | 508 def _VerifyAnExample(self, name, url): |
238 """Verify NaCl example is working. | 509 """Verify NaCl example is working. |
239 | 510 |
240 Args: | 511 Args: |
241 name: A string name of the example. | 512 name: A string name of the example. |
242 url: A string url of the example. | 513 url: A string url of the example. |
243 """ | 514 """ |
244 available_example_tests = { | 515 available_example_tests = { |
245 'dynamic_library_open': self._VerifyDynamicLibraryOpen, | 516 'hello_world_c': self._VerifyHelloWorldExample, |
246 'geturl': self._VerifyGetURLExample, | 517 'hello_world': self._VerifyHelloWorldExample, |
247 'input_events': self._VerifyInputEventsExample, | 518 'pi_generator': self._VerifyPiGeneratorExample, |
248 'load_progress': self._VerifyLoadProgressExample, | 519 'sine_synth': self._VerifySineSynthExample, |
249 'multithreaded_input_events': | 520 'geturl': self._VerifyGetURLExample, |
250 self._VerifyMultithreadedInputEventsExample, | 521 'life': self._VerifyConwaysLifeExample |
251 'pi_generator': self._VerifyPiGeneratorExample, | |
252 'sine_synth': self._VerifySineSynthExample, | |
253 'web_socket':self._VerifyWebSocketExample, | |
254 } | 522 } |
255 | 523 |
256 if not name in available_example_tests: | 524 if not name in available_example_tests: |
257 self.fail(msg='No test available for %s.' % name) | 525 self.fail(msg='No test available for %s.' % name) |
258 | 526 |
259 info = self.GetBrowserInfo() | 527 info = self.GetBrowserInfo() |
260 tabs = info['windows'][0]['tabs'] | 528 tabs = info['windows'][0]['tabs'] |
261 tab_index = None | 529 tab_index = None |
262 for tab in tabs: | 530 for tab in tabs: |
263 if url == tab['url']: | 531 if url == tab['url']: |
264 self.ActivateTab(tab['index']) | 532 self.ActivateTab(tab['index']) |
265 tab_index = tab['index'] | 533 tab_index = tab['index'] |
266 break | 534 break |
267 | 535 |
268 if tab_index: | 536 if tab_index: |
269 available_example_tests[name](tab_index, name, url) | 537 available_example_tests[name](tab_index, name, url) |
270 | 538 |
271 def _VerifyElementPresent(self, element_id, expected_value, tab_index, msg, | 539 def _VerifyHelloWorldExample(self, tab_index, name, url): |
272 attribute='innerHTML', timeout=150): | 540 """Verify Hello World Example. |
273 """Determine if dom element has the expected value. | 541 |
274 | 542 Args: |
275 Args: | 543 tab_index: Tab index integer that the example is on. |
276 element_id: Dom element's id. | 544 name: A string name of the example. |
277 expected_value: String to be matched against the Dom element. | 545 url: A string url of the example. |
278 tab_index: Tab index to work on. | 546 """ |
279 attribute: Attribute to match |expected_value| against, if | 547 success = self.WaitUntil( |
280 given. Defaults to 'innerHTML'. | 548 lambda: self.GetDOMValue( |
281 timeout: The max timeout (in secs) for which to wait. | 549 'document.getElementById("statusField").innerHTML', |
282 """ | 550 tab_index), |
| 551 timeout=60, expect_retval='SUCCESS') |
| 552 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) |
| 553 |
283 js_code = """ | 554 js_code = """ |
284 var output = document.getElementById('%s').%s; | 555 window.alert = function(e) { |
285 var result; | 556 window.domAutomationController.send(String(e)); |
286 if (output.indexOf('%s') != -1) | 557 } |
287 result = 'pass'; | 558 window.domAutomationController.send("done"); |
288 else | 559 """ |
289 result = 'fail'; | |
290 window.domAutomationController.send(result); | |
291 """ % (element_id, attribute, expected_value) | |
292 success = self.WaitUntil( | |
293 lambda: self.ExecuteJavascript(js_code, tab_index), | |
294 timeout=timeout, expect_retval='pass') | |
295 self.assertTrue(success, msg=msg) | |
296 | |
297 def _CreateJSToSimulateMouseclick(self): | |
298 """Create javascript to simulate mouse click event.""" | |
299 js_code = """ | |
300 var rightClick = document.createEvent('MouseEvents'); | |
301 rightClick.initMouseEvent( | |
302 'mousedown', true, true, document, | |
303 1, 32, 121, 10, 100, | |
304 false, false, false, false, | |
305 2, document.getElementById('event_module') | |
306 ); | |
307 document.getElementById('event_module').dispatchEvent(rightClick); | |
308 window.domAutomationController.send('done'); | |
309 """ | |
310 return js_code | |
311 | |
312 def _VerifyInputEventsExample(self, tab_index, name, url): | |
313 """Verify Input Events Example. | |
314 | |
315 Args: | |
316 tab_index: Tab index integer that the example is on. | |
317 name: A string name of the example. | |
318 url: A string url of the example. | |
319 """ | |
320 success = self._VerifyElementPresent('eventString', 'DidChangeView', | |
321 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | |
322 | |
323 # Simulate mouse click on event module. | |
324 js_code = self._CreateJSToSimulateMouseclick() | |
325 self.ExecuteJavascript(js_code, tab_index) | 560 self.ExecuteJavascript(js_code, tab_index) |
326 | 561 |
327 # Check if 'eventString' has handled above mouse click. | 562 result = self.ExecuteJavascript('document.helloForm.elements[1].click();', |
328 success = self.WaitUntil( | 563 tab_index) |
329 lambda: re.search('DidHandleInputEvent', self.GetDOMValue( | 564 self.assertEqual(result, '42', |
330 'document.getElementById("eventString").innerHTML', | 565 msg='Example %s failed. URL: %s' % (name, url)) |
331 tab_index)).group(), expect_retval='DidHandleInputEvent') | 566 |
332 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | 567 result = self.ExecuteJavascript('document.helloForm.elements[2].click();', |
333 | 568 tab_index) |
334 def _VerifyMultithreadedInputEventsExample(self, tab_index, name, url): | 569 self.assertEqual(result, 'dlrow olleH', |
335 """Verify Input Events Example. | 570 msg='Example %s failed. URL: %s' % (name, url)) |
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.WaitUntil( | |
343 lambda: bool(self.GetDOMValue( | |
344 'document.getElementById("eventString").innerHTML', | |
345 tab_index).find('DidChangeView') + 1)) | |
346 | |
347 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
348 | |
349 # Simulate mouse click on event module. | |
350 js_code = self._CreateJSToSimulateMouseclick() | |
351 self.ExecuteJavascript(js_code, tab_index) | |
352 | |
353 # Check if above mouse click is handled. | |
354 success = self._VerifyElementPresent('eventString', 'Mouse event', | |
355 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | |
356 | |
357 # Kill worker thread and queue | |
358 js_code = """ | |
359 document.getElementsByTagName('button')[0].click(); | |
360 window.domAutomationController.send('done'); | |
361 """ | |
362 self.ExecuteJavascript(js_code, tab_index) | |
363 | |
364 # Check if main thread has cancelled queue. | |
365 success = self._VerifyElementPresent('eventString', 'Received cancel', | |
366 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | |
367 | |
368 # Simulate mouse click on event module. | |
369 js_code = self._CreateJSToSimulateMouseclick() | |
370 self.ExecuteJavascript(js_code, tab_index) | |
371 | |
372 # Check if above mouse click is not handled after killing worker thread. | |
373 def _CheckMouseClickEventStatus(): | |
374 return self.GetDOMValue( | |
375 'document.getElementById("eventString").innerHTML', | |
376 tab_index).find('Mouse event', self.GetDOMValue( | |
377 'document.getElementById("eventString").innerHTML', tab_index).find( | |
378 'Received cancel')) | |
379 | |
380 success = self.WaitUntil(_CheckMouseClickEventStatus, expect_retval=-1) | |
381 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
382 | |
383 def _VerifyWebSocketExample(self, tab_index, name, url): | |
384 """Verify Web Socket Open Example. | |
385 | |
386 Args: | |
387 tab_index: Tab index integer that the example is on. | |
388 name: A string name of the example. | |
389 url: A string url of the example. | |
390 """ | |
391 # Check if example is loaded. | |
392 success = self.WaitUntil( | |
393 lambda: self.GetDOMValue( | |
394 'document.getElementById("statusField").innerHTML', tab_index), | |
395 expect_retval='SUCCESS') | |
396 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
397 | |
398 # Simulate clicking on Connect button to establish a connection. | |
399 js_code = """ | |
400 document.getElementsByTagName('input')[1].click(); | |
401 window.domAutomationController.send('done'); | |
402 """ | |
403 self.ExecuteJavascript(js_code, tab_index) | |
404 | |
405 # Check if connected | |
406 success = self._VerifyElementPresent('log', 'connected', tab_index, | |
407 msg='Example %s failed. URL: %s' %(name, url), attribute='value') | |
408 | |
409 # Simulate clicking on Send button to send text message in log. | |
410 js_code = """ | |
411 document.getElementsByTagName('input')[3].click(); | |
412 window.domAutomationController.send('done'); | |
413 """ | |
414 self.ExecuteJavascript(js_code, tab_index) | |
415 success = self.WaitUntil( | |
416 lambda: bool(re.search('send:', self.GetDOMValue( | |
417 'document.getElementById("log").value', tab_index)))) | |
418 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
419 | |
420 def _VerifyDynamicLibraryOpen(self, tab_index, name, url): | |
421 """Verify Dynamic Library Open Example. | |
422 | |
423 Args: | |
424 tab_index: Tab index integer that the example is on. | |
425 name: A string name of the example. | |
426 url: A string url of the example. | |
427 """ | |
428 # Check if example is loaded. | |
429 success = self._VerifyElementPresent('consolec', 'Eightball loaded', | |
430 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | |
431 | |
432 # Simulate clicking on ASK button and check answer log for desired answer. | |
433 js_code = """ | |
434 document.getElementsByTagName('input')[1].click(); | |
435 window.domAutomationController.send('done'); | |
436 """ | |
437 self.ExecuteJavascript(js_code, tab_index) | |
438 def _CheckAnswerLog(): | |
439 return bool(re.search(r'NO|YES|42|MAYBE NOT|DEFINITELY|' | |
440 'ASK ME TOMORROW|MAYBE|PARTLY CLOUDY', | |
441 self.GetDOMValue('document.getElementById("answerlog").innerHTML', | |
442 tab_index))) | |
443 | |
444 success = self.WaitUntil(_CheckAnswerLog) | |
445 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
446 | |
447 def _VerifyLoadProgressExample(self, tab_index, name, url): | |
448 """Verify Dynamic Library Open Example. | |
449 | |
450 Args: | |
451 tab_index: Tab index integer that the example is on. | |
452 name: A string name of the example. | |
453 url: A string url of the example. | |
454 """ | |
455 # Check if example loads and displays loading progress. | |
456 success = self.WaitUntil( | |
457 lambda: self.GetDOMValue( | |
458 'document.getElementById("status_field").innerHTML', tab_index), | |
459 timeout=150, expect_retval='SUCCESS') | |
460 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
461 | |
462 def _CheckLoadProgressStatus(): | |
463 return re.search( | |
464 r'(loadstart).+(progress:).+(load).+(loadend).+(lastError:)', | |
465 self.GetDOMValue( | |
466 'document.getElementById("event_log_field").innerHTML', tab_index)) | |
467 success = self.WaitUntil(_CheckLoadProgressStatus) | |
468 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | |
469 | 571 |
470 def _VerifyPiGeneratorExample(self, tab_index, name, url): | 572 def _VerifyPiGeneratorExample(self, tab_index, name, url): |
471 """Verify Pi Generator Example. | 573 """Verify Pi Generator Example. |
472 | 574 |
473 Args: | 575 Args: |
474 tab_index: Tab index integer that the example is on. | 576 tab_index: Tab index integer that the example is on. |
475 name: A string name of the example. | 577 name: A string name of the example. |
476 url: A string url of the example. | 578 url: A string url of the example. |
477 """ | 579 """ |
478 success = self.WaitUntil( | 580 success = self.WaitUntil( |
479 lambda: self.GetDOMValue('document.form.pi.value', tab_index)[0:3], | 581 lambda: self.GetDOMValue('document.form.pi.value', 0, tab_index)[0:3], |
480 expect_retval='3.1') | 582 timeout=120, expect_retval='3.1') |
481 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | 583 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) |
| 584 |
| 585 # Get top corner of Pi image. |
| 586 js_code = """ |
| 587 var obj = document.getElementById('piGenerator'); |
| 588 var curleft = curtop = 0; |
| 589 do { |
| 590 curleft += obj.offsetLeft; |
| 591 curtop += obj.offsetTop; |
| 592 } while (obj = obj.offsetParent); |
| 593 window.domAutomationController.send(curleft + ", " + curtop); |
| 594 """ |
| 595 result = self.ExecuteJavascript(js_code, tab_index) |
| 596 result_split = result.split(', ') |
| 597 x = int(result_split[0]) |
| 598 y = int(result_split[1]) |
| 599 window = self.GetBrowserInfo()['windows'][0] |
| 600 window_to_content_x = 2 |
| 601 window_to_content_y = 80 |
| 602 pi_image_x = x + window['x'] + window_to_content_x |
| 603 pi_image_y = y + window['y'] + window_to_content_y |
| 604 |
| 605 if self._IsGetPixelSupported(): |
| 606 is_animating = self._IsColorChanging(pi_image_x, pi_image_y, 50, 50) |
| 607 self.assertTrue(is_animating, |
| 608 msg='Example %s failed. URL: %s' % (name, url)) |
482 | 609 |
483 def _VerifySineSynthExample(self, tab_index, name, url): | 610 def _VerifySineSynthExample(self, tab_index, name, url): |
484 """Verify Sine Wave Synthesizer Example. | 611 """Verify Sine Wave Synthesizer Example. |
485 | 612 |
486 Args: | 613 Args: |
487 tab_index: Tab index integer that the example is on. | 614 tab_index: Tab index integer that the example is on. |
488 name: A string name of the example. | 615 name: A string name of the example. |
489 url: A string url of the example. | 616 url: A string url of the example. |
490 """ | 617 """ |
491 success = self.WaitUntil( | 618 success = self.WaitUntil( |
492 lambda: self.GetDOMValue( | 619 lambda: self.GetDOMValue( |
493 'document.getElementById("frequency_field").value', | 620 'document.getElementById("frequency_field").value', |
494 tab_index),timeout=150, expect_retval='440') | 621 tab_index), |
495 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | 622 timeout=30, expect_retval='440') |
| 623 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) |
| 624 |
496 self.ExecuteJavascript( | 625 self.ExecuteJavascript( |
497 'document.body.getElementsByTagName("button")[0].click();' | 626 'document.body.getElementsByTagName("button")[0].click();' |
498 'window.domAutomationController.send("done")', | 627 'window.domAutomationController.send("done")', |
499 tab_index) | 628 tab_index) |
500 | 629 |
| 630 # TODO(chrisphan): Verify sound. |
| 631 |
501 def _VerifyGetURLExample(self, tab_index, name, url): | 632 def _VerifyGetURLExample(self, tab_index, name, url): |
502 """Verify GetURL Example. | 633 """Verify GetURL Example. |
503 | 634 |
504 Args: | 635 Args: |
505 tab_index: Tab index integer that the example is on. | 636 tab_index: Tab index integer that the example is on. |
506 name: A string name of the example. | 637 name: A string name of the example. |
507 url: A string url of the example. | 638 url: A string url of the example. |
508 """ | 639 """ |
509 success = self.WaitUntil( | 640 success = self.WaitUntil( |
510 lambda: self.GetDOMValue( | 641 lambda: self.GetDOMValue( |
511 'document.getElementById("status_field").innerHTML', | 642 'document.getElementById("status_field").innerHTML', |
512 tab_index), timeout=150, expect_retval='SUCCESS') | 643 tab_index), |
513 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) | 644 timeout=60, expect_retval='SUCCESS') |
| 645 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) |
| 646 |
514 self.ExecuteJavascript( | 647 self.ExecuteJavascript( |
515 'document.geturl_form.elements[0].click();' | 648 'document.geturl_form.elements[0].click();' |
516 'window.domAutomationController.send("done")', | 649 'window.domAutomationController.send("done")', |
517 tab_index) | 650 tab_index) |
518 success = self._VerifyElementPresent('general_output', 'test passed', | 651 |
519 tab_index, msg='Example %s failed. URL: %s' % (name, url)) | 652 js_code = """ |
520 | 653 var output = document.getElementById("general_output").innerHTML; |
521 def _CheckForCrashes(self): | 654 var result; |
522 """Check for any browser/tab crashes and hangs.""" | 655 if (output.indexOf("test passed") != -1) |
| 656 result = "pass"; |
| 657 else |
| 658 result = "fail"; |
| 659 window.domAutomationController.send(result); |
| 660 """ |
| 661 success = self.WaitUntil( |
| 662 lambda: self.ExecuteJavascript(js_code, tab_index), |
| 663 timeout=30, expect_retval='pass') |
| 664 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) |
| 665 |
| 666 def _VerifyConwaysLifeExample(self, tab_index, name, url): |
| 667 """Verify Conway's Life Example. |
| 668 |
| 669 Args: |
| 670 tab_index: Tab index integer that the example is on. |
| 671 name: A string name of the example. |
| 672 url: A string url of the example. |
| 673 """ |
| 674 window = self.GetBrowserInfo()['windows'][0] |
| 675 window_to_content_x = 2 |
| 676 window_to_content_y = 80 |
| 677 x = window['x'] + window_to_content_x |
| 678 y = window['y'] + window_to_content_y |
| 679 offset_pixel = 100 |
| 680 if self._IsGetPixelSupported(): |
| 681 success = self.WaitUntil( |
| 682 lambda: self._GetPixel(x + offset_pixel, y + offset_pixel), |
| 683 timeout=30, expect_retval=16777215) |
| 684 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url)) |
| 685 |
| 686 def _GetXMLNodeData(self, nodelist): |
| 687 rc = [] |
| 688 for node in nodelist: |
| 689 if node.nodeType == node.TEXT_NODE: |
| 690 rc.append(node.data) |
| 691 return ''.join(rc) |
| 692 |
| 693 def _IsColorChanging(self, x, y, width, height): |
| 694 """Check screen for anything that is moving. |
| 695 |
| 696 Args: |
| 697 x: X coordinate on the screen. |
| 698 y: Y coordinate on the screen. |
| 699 width: Width of the area to scan. |
| 700 height: Height of the area to scan. |
| 701 |
| 702 Returns: |
| 703 True, if pixel color in area is changing, or |
| 704 False otherwise. |
| 705 """ |
| 706 color_a = self._GetAreaPixelColor(x, y, width, height) |
| 707 def _HasColorChanged(): |
| 708 color_b = self._GetAreaPixelColor(x, y, width, height) |
| 709 return color_a != color_b |
| 710 |
| 711 return self.WaitUntil(_HasColorChanged, timeout=6, |
| 712 retry_sleep=2, expect_retval=True) |
| 713 |
| 714 def _IsGetPixelSupported(self): |
| 715 """Check if get pixel is supported. |
| 716 |
| 717 Returns: |
| 718 True, if get pixel is supported, or |
| 719 False otherwise. |
| 720 """ |
| 721 return pyauto.PyUITest.IsWin() |
| 722 |
| 723 def _GetAreaPixelColor(self, x, y, width, height): |
| 724 """Get an area of pixel color and return a list of color code values. |
| 725 |
| 726 Args: |
| 727 x: X coordinate on the screen. |
| 728 y: Y coordinate on the screen. |
| 729 width: Width of the area to scan. |
| 730 height: Height of the area to scan. |
| 731 |
| 732 Returns: |
| 733 A list containing color codes. |
| 734 """ |
| 735 if pyauto.PyUITest.IsMac(): |
| 736 pass # TODO(chrisphan): Do Mac. |
| 737 elif pyauto.PyUITest.IsWin(): |
| 738 return self._GetAreaPixelColorWin(x, y, width, height) |
| 739 elif pyauto.PyUITest.IsLinux(): |
| 740 pass # TODO(chrisphan): Do Linux. |
| 741 return None |
| 742 |
| 743 def _GetAreaPixelColorWin(self, x, y, width, height): |
| 744 """Get an area of pixel color for Windows and return a list. |
| 745 |
| 746 Args: |
| 747 x: X coordinate on the screen. |
| 748 y: Y coordinate on the screen. |
| 749 width: Width of the area to scan. |
| 750 height: Height of the area to scan. |
| 751 |
| 752 Returns: |
| 753 A list containing color codes. |
| 754 """ |
| 755 colors = [] |
| 756 hdc = ctypes.windll.user32.GetDC(0) |
| 757 for x_pos in xrange(x, x + width, 1): |
| 758 for y_pos in xrange(y, y + height, 1): |
| 759 color = ctypes.windll.gdi32.GetPixel(hdc, x_pos, y_pos) |
| 760 colors.append(color) |
| 761 return colors |
| 762 |
| 763 def _GetPixel(self, x, y): |
| 764 """Get pixel color at coordinate x and y. |
| 765 |
| 766 Args: |
| 767 x: X coordinate on the screen. |
| 768 y: Y coordinate on the screen. |
| 769 |
| 770 Returns: |
| 771 An integer color code. |
| 772 """ |
| 773 if pyauto.PyUITest.IsMac(): |
| 774 pass # TODO(chrisphan): Do Mac. |
| 775 elif pyauto.PyUITest.IsWin(): |
| 776 return self._GetPixelWin(x, y) |
| 777 elif pyauto.PyUITest.IsLinux(): |
| 778 pass # TODO(chrisphan): Do Linux. |
| 779 return None |
| 780 |
| 781 def _GetPixelWin(self, x, y): |
| 782 """Get pixel color at coordinate x and y for Windows |
| 783 |
| 784 Args: |
| 785 x: X coordinate on the screen. |
| 786 y: Y coordinate on the screen. |
| 787 |
| 788 Returns: |
| 789 An integer color code. |
| 790 """ |
| 791 hdc = ctypes.windll.user32.GetDC(0) |
| 792 color = ctypes.windll.gdi32.GetPixel(hdc, x, y) |
| 793 return color |
| 794 |
| 795 def _CheckForCrashes(self, last_action=None, last_action_param=None): |
| 796 """Check for any browser/tab crashes and hangs. |
| 797 |
| 798 Args: |
| 799 last_action: Specify action taken before checking for crashes. |
| 800 last_action_param: Parameter for last action. |
| 801 """ |
523 self.assertTrue(self.GetBrowserWindowCount(), | 802 self.assertTrue(self.GetBrowserWindowCount(), |
524 msg='Browser crashed, no window is open.') | 803 msg='Browser crashed, no window is open.') |
525 | 804 |
526 info = self.GetBrowserInfo() | 805 info = self.GetBrowserInfo() |
527 breakpad_folder = info['properties']['DIR_CRASH_DUMPS'] | 806 breakpad_folder = info['properties']['DIR_CRASH_DUMPS'] |
528 old_dmp_files = glob.glob(os.path.join(breakpad_folder, '*.dmp')) | 807 old_dmp_files = glob.glob(os.path.join(breakpad_folder, '*.dmp')) |
529 | 808 |
530 # Verify there're no crash dump files. | 809 # Verify there're no crash dump files. |
531 for dmp_file in glob.glob(os.path.join(breakpad_folder, '*.dmp')): | 810 for dmp_file in glob.glob(os.path.join(breakpad_folder, '*.dmp')): |
532 self.assertTrue(dmp_file in old_dmp_files, | 811 self.assertTrue(dmp_file in old_dmp_files, |
533 msg='Crash dump %s found' % dmp_file) | 812 msg='Crash dump %s found' % dmp_file) |
534 | 813 |
535 # Check for any crashed tabs. | 814 # Check for any crashed tabs. |
536 tabs = info['windows'][0]['tabs'] | 815 tabs = info['windows'][0]['tabs'] |
537 for tab in tabs: | 816 for tab in tabs: |
538 if tab['url'] != 'about:blank': | 817 if tab['url'] != 'about:blank': |
539 if not self.GetDOMValue('document.body.innerHTML', tab['index']): | 818 if not self.GetDOMValue('document.body.innerHTML', tab['index']): |
540 self.fail(msg='Tab crashed on %s' % tab['url']) | 819 self.fail(msg='Tab crashed on %s' % tab['url']) |
541 | 820 |
| 821 # TODO(chrisphan): Check for tab hangs and browser hangs. |
| 822 # TODO(chrisphan): Handle specific action: close browser, close tab. |
| 823 if last_action == 'close tab': |
| 824 pass |
| 825 elif last_action == 'close browser': |
| 826 pass |
| 827 else: |
| 828 pass |
| 829 |
542 def _GetPlatformArchitecture(self): | 830 def _GetPlatformArchitecture(self): |
543 """Get platform architecture. | 831 """Get platform architecture. |
544 | 832 |
| 833 Args: |
| 834 last_action: Last action taken before checking for crashes. |
| 835 last_action_param: Parameter for last action. |
| 836 |
545 Returns: | 837 Returns: |
546 A string representing the platform architecture. | 838 A string representing the platform architecture. |
547 """ | 839 """ |
548 if pyauto.PyUITest.IsWin(): | 840 if pyauto.PyUITest.IsWin(): |
549 if os.environ['PROGRAMFILES'] == 'C:\\Program Files (x86)': | 841 if os.environ['PROGRAMFILES'] == 'C:\\Program Files (x86)': |
550 return '64bit' | 842 return '64bit' |
551 else: | 843 else: |
552 return '32bit' | 844 return '32bit' |
553 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux(): | 845 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux(): |
554 if platform.machine() == 'x86_64': | 846 if platform.machine() == 'x86_64': |
555 return '64bit' | 847 return '64bit' |
556 else: | 848 else: |
557 return '32bit' | 849 return '32bit' |
558 return '32bit' | 850 return '32bit' |
559 | 851 |
| 852 def _HasFile(self, pattern, root=os.curdir): |
| 853 """Check if a file matching the specified pattern exists in a directory. |
| 854 |
| 855 Args: |
| 856 pattern: Pattern of file name. |
| 857 root: Directory to start looking. |
| 858 |
| 859 Returns: |
| 860 True, if root contains the file name pattern, or |
| 861 False otherwise. |
| 862 """ |
| 863 return len(glob.glob(os.path.join(root, pattern))) |
| 864 |
560 def _HasPathInTree(self, pattern, is_file, root=os.curdir): | 865 def _HasPathInTree(self, pattern, is_file, root=os.curdir): |
561 """Recursively checks if a file/directory matching a pattern exists. | 866 """Recursively checks if a file/directory matching a pattern exists. |
562 | 867 |
563 Args: | 868 Args: |
564 pattern: Pattern of file or directory name. | 869 pattern: Pattern of file or directory name. |
565 is_file: True if looking for file, or False if looking for directory. | 870 is_file: True if looking for file, or False if looking for directory. |
566 root: Directory to start looking. | 871 root: Directory to start looking. |
567 | 872 |
568 Returns: | 873 Returns: |
569 True, if root contains the directory name pattern, or | 874 True, if root contains the directory name pattern, or |
570 False otherwise. | 875 False otherwise. |
571 """ | 876 """ |
572 for path, dirs, files in os.walk(os.path.abspath(root)): | 877 for path, dirs, files in os.walk(os.path.abspath(root)): |
573 if is_file: | 878 if is_file: |
574 if len(fnmatch.filter(files, pattern)): | 879 if len(fnmatch.filter(files, pattern)): |
575 return True | 880 return True |
576 else: | 881 else: |
577 if len(fnmatch.filter(dirs, pattern)): | 882 if len(fnmatch.filter(dirs, pattern)): |
578 return True | 883 return True |
579 return False | 884 return False |
580 | 885 |
| 886 def _GetDirectoryPath(self, pattern, root=os.curdir): |
| 887 """Get the path of a directory in another directory. |
| 888 |
| 889 Args: |
| 890 pattern: Pattern of directory name. |
| 891 root: Directory to start looking. |
| 892 |
| 893 Returns: |
| 894 A string of the path. |
| 895 """ |
| 896 for path, dirs, files in os.walk(os.path.abspath(root)): |
| 897 result = fnmatch.filter(dirs, pattern) |
| 898 if result: |
| 899 return os.path.join(path, result[0]) |
| 900 return None |
| 901 |
581 def _HasAllSystemRequirements(self): | 902 def _HasAllSystemRequirements(self): |
582 """Verify NaCl SDK installation system requirements. | 903 """Verify NaCl SDK installation system requirements. |
583 | 904 |
584 Returns: | 905 Returns: |
585 True, if system passed requirements, or | 906 True, if system passed requirements, or |
586 False otherwise. | 907 False otherwise. |
587 """ | 908 """ |
588 # Check python version. | 909 # Check python version. |
589 if sys.version_info[0:2] < (2, 6): | 910 if sys.version_info[0:2] < (2, 6): |
590 return False | 911 return False |
(...skipping 16 matching lines...) Expand all Loading... |
607 # NaCl supports Chrome 10 and higher builds. | 928 # NaCl supports Chrome 10 and higher builds. |
608 min_required_chrome_build = self._settings['min_required_chrome_build'] | 929 min_required_chrome_build = self._settings['min_required_chrome_build'] |
609 browser_info = self.GetBrowserInfo() | 930 browser_info = self.GetBrowserInfo() |
610 chrome_version = browser_info['properties']['ChromeVersion'] | 931 chrome_version = browser_info['properties']['ChromeVersion'] |
611 chrome_build = int(chrome_version.split('.')[0]) | 932 chrome_build = int(chrome_version.split('.')[0]) |
612 return chrome_build >= min_required_chrome_build | 933 return chrome_build >= min_required_chrome_build |
613 | 934 |
614 def _DownloadNaClSDK(self): | 935 def _DownloadNaClSDK(self): |
615 """Download NaCl SDK.""" | 936 """Download NaCl SDK.""" |
616 self._temp_dir = tempfile.mkdtemp() | 937 self._temp_dir = tempfile.mkdtemp() |
617 dl_file = urllib2.urlopen(self._settings['post_sdk_zip']) | 938 if pyauto.PyUITest.IsWin(): |
618 file_path = os.path.join(self._temp_dir, 'nacl_sdk.zip') | 939 dl_file = urllib2.urlopen(self._settings['release_win_sdk_url']) |
| 940 file_path = os.path.join(self._temp_dir, 'naclsdk_win.exe') |
| 941 elif pyauto.PyUITest.IsMac(): |
| 942 dl_file = urllib2.urlopen(self._settings['release_mac_sdk_url']) |
| 943 file_path = os.path.join(self._temp_dir, 'naclsdk_mac.tgz') |
| 944 elif pyauto.PyUITest.IsLinux(): |
| 945 dl_file = urllib2.urlopen(self._settings['release_lin_sdk_url']) |
| 946 file_path = os.path.join(self._temp_dir, 'naclsdk_linux.tgz') |
| 947 else: |
| 948 self.fail(msg='NaCl SDK does not support this OS.') |
619 | 949 |
620 try: | 950 try: |
621 f = open(file_path, 'wb') | 951 f = open(file_path, 'wb') |
622 f.write(dl_file.read()) | 952 f.write(dl_file.read()) |
623 except IOError: | 953 except IOError: |
624 self.fail(msg='Cannot open %s.' % file_path) | 954 self.fail(msg='Cannot open %s.' % file_path) |
625 finally: | 955 finally: |
626 f.close() | 956 f.close() |
627 | 957 |
628 def _ExtractNaClSDK(self): | 958 def _ExtractNaClSDK(self): |
629 """Extract NaCl SDK.""" | 959 """Extract NaCl SDK.""" |
630 source_file = os.path.join(self._temp_dir, 'nacl_sdk.zip') | 960 if pyauto.PyUITest.IsWin(): |
631 if zipfile.is_zipfile(source_file): | 961 source_file = os.path.join(self._temp_dir, 'naclsdk_win.exe') |
632 zip = zipfile.ZipFile(source_file, 'r') | 962 proc = subprocess.Popen([source_file, '/S', '/D=' + |
633 zip.extractall(self._extracted_sdk_path) | 963 self._extracted_sdk_path], |
| 964 stdout=subprocess.PIPE) |
| 965 proc.communicate() |
| 966 if not os.listdir(self._extracted_sdk_path): |
| 967 self.fail(msg='Failed to extract NaCl SDK.') |
| 968 elif pyauto.PyUITest.IsMac(): |
| 969 source_file = os.path.join(self._temp_dir, 'naclsdk_mac.tgz') |
| 970 tar = tarfile.open(source_file, 'r') |
| 971 tar.extractall(self._extracted_sdk_path) |
| 972 elif pyauto.PyUITest.IsLinux(): |
| 973 source_file = os.path.join(self._temp_dir, 'naclsdk_linux.tgz') |
| 974 tar = tarfile.open(source_file, 'r') |
| 975 tar.extractall(self._extracted_sdk_path) |
634 else: | 976 else: |
635 self.fail(msg='%s is not a valid zip file' % source_file) | 977 self.fail(msg='NaCl SDK does not support this OS.') |
636 | 978 |
637 def _IsURLAlive(self, url): | 979 def _IsURLAlive(self, url): |
638 """Test if URL is alive.""" | 980 """Test if URL is alive.""" |
639 try: | 981 try: |
640 urllib2.urlopen(url) | 982 urllib2.urlopen(url) |
641 except: | 983 except: |
642 return False | 984 return False |
643 return True | 985 return True |
644 | 986 |
645 def _CloseHTTPServer(self, proc=None): | 987 def _CloseHTTPServer(self, proc=None): |
646 """Close HTTP server. | 988 """Close HTTP server. |
647 | 989 |
648 Args: | 990 Args: |
649 proc: Process that opened the HTTP server. | 991 proc: Process that opened the HTTP server. |
650 proc is None when there is no pointer to HTTP server process. | 992 proc is None when there is no pointer to HTTP server process. |
651 """ | 993 """ |
652 if not self._IsURLAlive('http://localhost:5103'): | 994 if not self._IsURLAlive('http://localhost:5103'): |
653 return | 995 return |
654 response = urllib2.urlopen('http://localhost:5103') | 996 response = urllib2.urlopen('http://localhost:5103') |
655 html = response.read() | 997 html = response.read() |
656 if not 'Native Client' in html: | 998 if not 'Native Client' in html: |
657 self.fail(msg='Port 5103 is in use.') | 999 self.fail(msg='Port 5103 is in use.') |
658 | 1000 |
659 urllib2.urlopen('http://localhost:5103?quit=1') | 1001 urllib2.urlopen('http://localhost:5103?quit=1') |
660 success = self.WaitUntil( | 1002 success = self.WaitUntil( |
661 lambda: self._IsURLAlive('http://localhost:5103'), | 1003 lambda: self._IsURLAlive('http://localhost:5103'), |
662 retry_sleep=1, expect_retval=False) | 1004 timeout=30, retry_sleep=1, expect_retval=False) |
663 if not success: | 1005 if not success: |
664 if not proc: | 1006 if not proc: |
665 self.fail(msg='Failed to close HTTP server.') | 1007 self.fail(msg='Failed to close HTTP server.') |
666 else: | 1008 else: |
667 if proc.poll() == None: | 1009 if proc.poll() == None: |
668 try: | 1010 try: |
669 proc.kill() | 1011 proc.kill() |
670 except: | 1012 except: |
671 self.fail(msg='Failed to close HTTP server.') | 1013 self.fail(msg='Failed to close HTTP server') |
672 | 1014 |
673 def _SearchNaClSDKFile(self, search_list): | 1015 def _SearchNaClSDKTarFile(self, search_list, source_file): |
| 1016 """Search NaCl SDK tar file for example files and directories. |
| 1017 |
| 1018 Args: |
| 1019 search_list: A list of strings, representing file and |
| 1020 directory names for which to search. |
| 1021 source_file: The string name of an NaCl SDK tar file. |
| 1022 """ |
| 1023 tar = tarfile.open(source_file, 'r') |
| 1024 |
| 1025 # Look for files and directories in examples. |
| 1026 files = copy.deepcopy(search_list) |
| 1027 for tar_info in tar: |
| 1028 file_name = tar_info.name |
| 1029 if tar_info.isdir() and not file_name.endswith('/'): |
| 1030 file_name = file_name + '/' |
| 1031 |
| 1032 for name in files: |
| 1033 if file_name.find('examples/' + name): |
| 1034 files.remove(name) |
| 1035 if not files: |
| 1036 break |
| 1037 |
| 1038 tar.close() |
| 1039 |
| 1040 self.assertEqual(len(files), 0, |
| 1041 msg='Missing files or directories: %s' % |
| 1042 ', '.join(map(str, files))) |
| 1043 |
| 1044 def _SearchNaClSDKFileWindows(self, search_list): |
674 """Search NaCl SDK file for example files and directories in Windows. | 1045 """Search NaCl SDK file for example files and directories in Windows. |
675 | 1046 |
676 Args: | 1047 Args: |
677 search_list: A list of strings, representing file and | 1048 search_list: A list of strings, representing file and |
678 directory names for which to search. | 1049 directory names for which to search. |
679 """ | 1050 """ |
680 missing_items = [] | 1051 missing_items = [] |
681 for name in search_list: | 1052 for name in search_list: |
682 is_file = name.find('/') < 0 | 1053 is_file = name.find('/') < 0 |
683 if not is_file: | 1054 if not is_file: |
684 name = name.replace('/', '') | 1055 name = name.replace('/', '') |
685 if not self._HasPathInTree(name, is_file, self._extracted_sdk_path): | 1056 if not self._HasPathInTree(name, is_file, self._extracted_sdk_path): |
686 missing_items.append(name) | 1057 missing_items.append(name) |
687 self.assertEqual(len(missing_items), 0, | 1058 self.assertEqual(len(missing_items), 0, |
688 msg='Missing files or directories: %s' % | 1059 msg='Missing files or directories: %s' % |
689 ', '.join(map(str, missing_items))) | 1060 ', '.join(map(str, missing_items))) |
690 | 1061 |
691 def ExtraChromeFlags(self): | 1062 def _EnableNaClPlugin(self): |
692 """Ensures Nacl is enabled. | 1063 """Enable NaCl plugin.""" |
| 1064 nacl_plugin = (self.GetPluginsInfo().PluginForName('Chrome NaCl') or |
| 1065 self.GetPluginsInfo().PluginForName('Native Client')) |
| 1066 if not nacl_plugin: |
| 1067 self.fail(msg='No NaCl plugin found.') |
| 1068 self.EnablePlugin(nacl_plugin[0]['path']) |
693 | 1069 |
694 Returns: | 1070 self.NavigateToURL('about:flags') |
695 A list of extra flags to pass to Chrome when it is launched. | 1071 |
| 1072 js_code = """ |
| 1073 chrome.send('enableFlagsExperiment', ['enable-nacl', 'true']); |
| 1074 requestFlagsExperimentsData(); |
| 1075 window.domAutomationController.send('done'); |
696 """ | 1076 """ |
697 extra_chrome_flags = [ | 1077 self.ExecuteJavascript(js_code) |
698 '--enable-nacl', | 1078 self.RestartBrowser(False) |
699 '--enable-nacl-exception-handling', | 1079 |
700 '--nacl-gdb', | 1080 self.NavigateToURL('about://version') |
701 ] | 1081 self.assertEqual(self.FindInPage('--enable-nacl')['match_count'], 1, |
702 return pyauto.PyUITest.ExtraChromeFlags(self) + extra_chrome_flags | 1082 msg='Missing expected Chrome flag --enable-nacl.') |
| 1083 |
703 | 1084 |
704 if __name__ == '__main__': | 1085 if __name__ == '__main__': |
705 pyauto_functional.Main() | 1086 pyauto_functional.Main() |
OLD | NEW |