Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: functional/nacl_sdk.py

Issue 7633026: Adding pyauto tests for the NaCl SDK. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/chrome/test/
Patch Set: '' Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « functional/PYAUTO_TESTS ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
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
4 # found in the LICENSE file.
5
6 import copy
7 import ctypes
8 from distutils import version
9 import fnmatch
10 import glob
11 import hashlib
12 import logging
13 import os
14 import platform
15 import shutil
16 import subprocess
17 import sys
18 import tarfile
19 import tempfile
20 import urllib2
21 import xml.dom.minidom
22
23 import pyauto_functional # Must be imported before pyauto.
24 import pyauto
25 import pyauto_utils
26
27
28 class NaClSDKTest(pyauto.PyUITest):
29 """Tests for the NaCl SDK."""
30 _extracted_sdk_path = None
31 _temp_dir = None
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',
45 'post_sdk_download_url': 'http://code.google.com/chrome/nativeclient/'
46 'docs/download.html',
47 'post_win_sdk_url': 'http://commondatastorage.googleapis.com/'
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',
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 }
75 }
76
77 def tearDown(self):
78 pyauto.PyUITest.tearDown(self)
79 self._RemoveDownloadedTestFile()
80
81 def testNaClSDK(self):
82 """Verify that NaCl SDK is working properly."""
83 if not self._HasAllSystemRequirements():
84 logging.info('System does not meet the requirements.')
85 return
86 self._extracted_sdk_path = tempfile.mkdtemp()
87
88 self._VerifyDownloadLinks()
89 self._VerifyNaClSDKInstaller()
90 self._VerifyBuildStubProject()
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'])
151
152 def _VerifyDownloadLinks(self):
153 """Verify the download links."""
154 html = None
155 for i in xrange(3):
156 try:
157 html = urllib2.urlopen(self._settings['post_sdk_download_url']).read()
158 break
159 except:
160 pass
161 self.assertTrue(html,
162 msg='Cannot open URL: %s' %
163 self._settings['post_sdk_download_url'])
164
165 # Make sure the correct URL is under the correct label.
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.')
192
193 def _VerifyNaClSDKInstaller(self):
194 """Verify NaCl SDK installer."""
195 search_list = [
196 'build.scons',
197 'favicon.ico',
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
209 mac_lin_additional_search_items = [
210 'sel_ldr_x86_32',
211 'sel_ldr_x86_64',
212 'ncval_x86_32',
213 'ncval_x86_64'
214 ]
215
216 win_additional_search_items = [
217 'httpd.cmd',
218 'sel_ldr_x86_32.exe',
219 'sel_ldr_x86_64.exe',
220 'ncval_x86_32.exe',
221 'ncval_x86_64.exe'
222 ]
223
224 self._DownloadNaClSDK()
225
226 if pyauto.PyUITest.IsWin():
227 self._ExtractNaClSDK()
228 self._SearchNaClSDKFileWindows(
229 search_list + win_additional_search_items)
230 elif pyauto.PyUITest.IsMac():
231 source_file = os.path.join(self._temp_dir, 'naclsdk_mac.tgz')
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()
240 else:
241 self.fail(msg='NaCl SDK does not support this OS.')
242
243 def _VerifyBuildStubProject(self):
244 """Build stub project."""
245 stub_project_files = [
246 'build.scons',
247 'scons'
248 ]
249 project_template_path = self._GetDirectoryPath('project_templates',
250 self._extracted_sdk_path)
251 examples_path = self._GetDirectoryPath('examples',
252 self._extracted_sdk_path)
253 init_project_path = os.path.join(project_template_path, 'init_project.py')
254
255 # Build a C project.
256 subprocess.call(
257 ['python', init_project_path, '-n', 'hello_c', '-c', '-d',
258 examples_path], stdout=subprocess.PIPE)
259
260 hello_c_path = os.path.join(examples_path, 'hello_c')
261 for file in stub_project_files:
262 self.assertTrue(self._HasFile(file, hello_c_path),
263 msg='Cannot build C stub project.')
264
265 # Build a C++ project.
266 subprocess.call(
267 ['python', init_project_path, '-n', 'hello_cc', '-d',
268 examples_path], stdout=subprocess.PIPE)
269
270 hello_cc_path = os.path.join(examples_path, 'hello_cc')
271 for file in stub_project_files:
272 self.assertTrue(self._HasFile(file, hello_cc_path),
273 msg='Cannot build C++ stub project.')
274
275 def _LaunchServerAndVerifyExamples(self):
276 """Start local HTTP server and verify examples."""
277 # Make sure server is not open.
278 if self._IsURLAlive('http://localhost:5103'):
279 self._CloseHTTPServer()
280
281 # Start HTTP server.
282 examples_path = self._GetDirectoryPath('examples',
283 self._extracted_sdk_path)
284 if pyauto.PyUITest.IsWin():
285 http_path = os.path.join(examples_path, 'httpd.cmd')
286 proc = subprocess.Popen([http_path], cwd=examples_path)
287 else:
288 http_path = os.path.join(examples_path, 'httpd.py')
289 proc = subprocess.Popen(['python', http_path], cwd=examples_path)
290
291 success = self.WaitUntil(
292 lambda: self._IsURLAlive('http://localhost:5103'),
293 timeout=30, retry_sleep=1, expect_retval=True)
294 self.assertTrue(success,
295 msg='Cannot open HTTP server. %s' %
296 self.GetActiveTabTitle())
297
298 examples = {
299 'hello_world_c': 'http://localhost:5103/hello_world_c/'
300 'hello_world.html',
301 'hello_world': 'http://localhost:5103/hello_world/hello_world.html',
302 'geturl': 'http://localhost:5103/geturl/geturl.html',
303 'pi_generator': 'http://localhost:5103/pi_generator/pi_generator.html',
304 'sine_synth': 'http://localhost:5103/sine_synth/sine_synth.html',
305 }
306 try:
307 self._OpenExamplesAndStartTest(examples)
308 finally:
309 self._CloseHTTPServer(proc)
310
311 def _VerifyRebuildExamples(self):
312 """Re-build the examples and verify they are as expected."""
313 example_dirs = [
314 'geturl',
315 'hello_world',
316 'hello_world_c',
317 'pi_generator',
318 'sine_synth'
319 ]
320 examples_path = self._GetDirectoryPath('examples',
321 self._extracted_sdk_path)
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.')
425
426 def _RemoveDownloadedTestFile(self):
427 """Delete downloaded files and dirs from downloads directory."""
428 if self._extracted_sdk_path and os.path.exists(self._extracted_sdk_path):
429 self._CloseHTTPServer()
430
431 def _RemoveFile():
432 shutil.rmtree(self._extracted_sdk_path, ignore_errors=True)
433 return os.path.exists(self._extracted_sdk_path)
434
435 success = self.WaitUntil(_RemoveFile, retry_sleep=2, expect_retval=False)
436 self.assertTrue(success,
437 msg='Cannot remove %s' % self._extracted_sdk_path)
438
439 if self._temp_dir:
440 pyauto_utils.RemovePath(self._temp_dir)
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
464 def _OpenExamplesAndStartTest(self, examples):
465 """Open each example and verify that it's working.
466
467 Args:
468 examples: A dict of name to url of examples.
469 """
470 self._EnableNaClPlugin()
471
472 # Open all examples.
473 for name, url in examples.items():
474 self.AppendTab(pyauto.GURL(url))
475 self._CheckForCrashes()
476
477 # Verify all examples are working.
478 for name, url in examples.items():
479 self._VerifyAnExample(name, url)
480 self._CheckForCrashes()
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
493 # Close each tab, check for crashes and verify all open
494 # examples operate correctly.
495 tab_count = self.GetTabCount()
496 for index in xrange(tab_count - 1, 0, -1):
497 self.GetBrowserWindow(0).GetTab(index).Close(True)
498 self._CheckForCrashes()
499
500 tabs = self.GetBrowserInfo()['windows'][0]['tabs']
501 for tab in tabs:
502 if tab['index'] > 0:
503 for name, url in examples.items():
504 if url == tab['url']:
505 self._VerifyAnExample(name, url)
506 break
507
508 def _VerifyAnExample(self, name, url):
509 """Verify NaCl example is working.
510
511 Args:
512 name: A string name of the example.
513 url: A string url of the example.
514 """
515 available_example_tests = {
516 'hello_world_c': self._VerifyHelloWorldExample,
517 'hello_world': self._VerifyHelloWorldExample,
518 'pi_generator': self._VerifyPiGeneratorExample,
519 'sine_synth': self._VerifySineSynthExample,
520 'geturl': self._VerifyGetURLExample,
521 'life': self._VerifyConwaysLifeExample
522 }
523
524 if not name in available_example_tests:
525 self.fail(msg='No test available for %s.' % name)
526
527 info = self.GetBrowserInfo()
528 tabs = info['windows'][0]['tabs']
529 tab_index = None
530 for tab in tabs:
531 if url == tab['url']:
532 self.ActivateTab(tab['index'])
533 tab_index = tab['index']
534 break
535
536 if tab_index:
537 available_example_tests[name](tab_index, name, url)
538
539 def _VerifyHelloWorldExample(self, tab_index, name, url):
540 """Verify Hello World Example.
541
542 Args:
543 tab_index: Tab index integer that the example is on.
544 name: A string name of the example.
545 url: A string url of the example.
546 """
547 success = self.WaitUntil(
548 lambda: self.GetDOMValue(
549 'document.getElementById("statusField").innerHTML',
550 0, tab_index),
551 timeout=60, expect_retval='SUCCESS')
552 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
553
554 js_code = """
555 window.alert = function(e) {
556 window.domAutomationController.send(String(e));
557 }
558 window.domAutomationController.send("done");
559 """
560 self.ExecuteJavascript(js_code, 0, tab_index)
561
562 result = self.ExecuteJavascript('document.helloForm.elements[1].click();',
563 0, tab_index)
564 self.assertEqual(result, '42',
565 msg='Example %s failed. URL: %s' % (name, url))
566
567 result = self.ExecuteJavascript('document.helloForm.elements[2].click();',
568 0, tab_index)
569 self.assertEqual(result, 'dlrow olleH',
570 msg='Example %s failed. URL: %s' % (name, url))
571
572 def _VerifyPiGeneratorExample(self, tab_index, name, url):
573 """Verify Pi Generator Example.
574
575 Args:
576 tab_index: Tab index integer that the example is on.
577 name: A string name of the example.
578 url: A string url of the example.
579 """
580 success = self.WaitUntil(
581 lambda: self.GetDOMValue('document.form.pi.value', 0, tab_index)[0:3],
582 timeout=120, expect_retval='3.1')
583 self.assertTrue(
584 success,
585 msg='Example %s failed: Pi estimation. URL: %s' % (name, url))
586
587 # Get top corner of Pi image.
588 js_code = """
589 var obj = document.getElementById('piGenerator');
590 var curleft = curtop = 0;
591 do {
592 curleft += obj.offsetLeft;
593 curtop += obj.offsetTop;
594 } while (obj = obj.offsetParent);
595 window.domAutomationController.send(curleft + ", " + curtop);
596 """
597 result = self.ExecuteJavascript(js_code, 0, tab_index)
598 result_split = result.split(', ')
599 x = int(result_split[0])
600 y = int(result_split[1])
601 window = self.GetBrowserInfo()['windows'][0]
602 window_to_content_x = 2
603 window_to_content_y = 80
604 pi_image_x = x + window['x'] + window_to_content_x
605 pi_image_y = y + window['y'] + window_to_content_y
606
607 if self._IsGetPixelSupported():
608 is_animating = self._IsColorChanging(pi_image_x, pi_image_y, 50, 50)
609 self.assertTrue(is_animating,
610 msg='Example %s failed: No animation. URL: %s' % (name, ur l))
611
612 def _VerifySineSynthExample(self, tab_index, name, url):
613 """Verify Sine Wave Synthesizer Example.
614
615 Args:
616 tab_index: Tab index integer that the example is on.
617 name: A string name of the example.
618 url: A string url of the example.
619 """
620 success = self.WaitUntil(
621 lambda: self.GetDOMValue(
622 'document.getElementById("frequency_field").value',
623 0, tab_index),
624 timeout=30, expect_retval='440')
625 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
626
627 self.ExecuteJavascript(
628 'document.body.getElementsByTagName("button")[0].click();'
629 'window.domAutomationController.send("done")',
630 0, tab_index)
631
632 # TODO(chrisphan): Verify sound.
633
634 def _VerifyGetURLExample(self, tab_index, name, url):
635 """Verify GetURL Example.
636
637 Args:
638 tab_index: Tab index integer that the example is on.
639 name: A string name of the example.
640 url: A string url of the example.
641 """
642 success = self.WaitUntil(
643 lambda: self.GetDOMValue(
644 'document.getElementById("status_field").innerHTML',
645 0, tab_index),
646 timeout=60, expect_retval='SUCCESS')
647 self.assertTrue(success,
648 msg='Example %s failed. No status. URL: %s' % (name, url))
649
650 self.ExecuteJavascript(
651 'document.geturl_form.elements[0].click();'
652 'window.domAutomationController.send("done")',
653 0, tab_index)
654
655 js_code = """
656 var output = document.getElementById("general_output").innerHTML;
657 var result;
658 if (output.indexOf("test passed") != -1)
659 result = "pass";
660 else
661 result = "fail";
662 window.domAutomationController.send(result);
663 """
664 success = self.WaitUntil(
665 lambda: self.ExecuteJavascript(js_code, 0, tab_index),
666 timeout=30, expect_retval='pass')
667 self.assertTrue(
668 success,
669 msg='Example %s failed. No HTML respond. URL: %s' % (name, url))
670
671 def _VerifyConwaysLifeExample(self, tab_index, name, url):
672 """Verify Conway's Life Example.
673
674 Args:
675 tab_index: Tab index integer that the example is on.
676 name: A string name of the example.
677 url: A string url of the example.
678 """
679 window = self.GetBrowserInfo()['windows'][0]
680 window_to_content_x = 2
681 window_to_content_y = 80
682 x = window['x'] + window_to_content_x
683 y = window['y'] + window_to_content_y
684 offset_pixel = 100
685 if self._IsGetPixelSupported():
686 success = self.WaitUntil(
687 lambda: self._GetPixel(x + offset_pixel, y + offset_pixel),
688 timeout=30, expect_retval=16777215)
689 self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
690
691 def _GetXMLNodeData(self, nodelist):
692 rc = []
693 for node in nodelist:
694 if node.nodeType == node.TEXT_NODE:
695 rc.append(node.data)
696 return ''.join(rc)
697
698 def _IsColorChanging(self, x, y, width, height):
699 """Check screen for anything that is moving.
700
701 Args:
702 x: X coordinate on the screen.
703 y: Y coordinate on the screen.
704 width: Width of the area to scan.
705 height: Height of the area to scan.
706
707 Returns:
708 True, if pixel color in area is changing, or
709 False otherwise.
710 """
711 color_a = self._GetAreaPixelColor(x, y, width, height)
712 def _HasColorChanged():
713 color_b = self._GetAreaPixelColor(x, y, width, height)
714 return color_a != color_b
715
716 return self.WaitUntil(_HasColorChanged, retry_sleep=2, expect_retval=True)
717
718 def _IsGetPixelSupported(self):
719 """Check if get pixel is supported.
720
721 Returns:
722 True, if get pixel is supported, or
723 False otherwise.
724 """
725 return pyauto.PyUITest.IsWin()
726
727 def _GetAreaPixelColor(self, x, y, width, height):
728 """Get an area of pixel color and return a list of color code values.
729
730 Args:
731 x: X coordinate on the screen.
732 y: Y coordinate on the screen.
733 width: Width of the area to scan.
734 height: Height of the area to scan.
735
736 Returns:
737 A list containing color codes.
738 """
739 if pyauto.PyUITest.IsMac():
740 pass # TODO(chrisphan): Do Mac.
741 elif pyauto.PyUITest.IsWin():
742 return self._GetAreaPixelColorWin(x, y, width, height)
743 elif pyauto.PyUITest.IsLinux():
744 pass # TODO(chrisphan): Do Linux.
745 return None
746
747 def _GetAreaPixelColorWin(self, x, y, width, height):
748 """Get an area of pixel color for Windows and return a list.
749
750 Args:
751 x: X coordinate on the screen.
752 y: Y coordinate on the screen.
753 width: Width of the area to scan.
754 height: Height of the area to scan.
755
756 Returns:
757 A list containing color codes.
758 """
759 colors = []
760 hdc = ctypes.windll.user32.GetDC(0)
761 for x_pos in xrange(x, x + width, 1):
762 for y_pos in xrange(y, y + height, 1):
763 color = ctypes.windll.gdi32.GetPixel(hdc, x_pos, y_pos)
764 colors.append(color)
765 return colors
766
767 def _GetPixel(self, x, y):
768 """Get pixel color at coordinate x and y.
769
770 Args:
771 x: X coordinate on the screen.
772 y: Y coordinate on the screen.
773
774 Returns:
775 An integer color code.
776 """
777 if pyauto.PyUITest.IsMac():
778 pass # TODO(chrisphan): Do Mac.
779 elif pyauto.PyUITest.IsWin():
780 return self._GetPixelWin(x, y)
781 elif pyauto.PyUITest.IsLinux():
782 pass # TODO(chrisphan): Do Linux.
783 return None
784
785 def _GetPixelWin(self, x, y):
786 """Get pixel color at coordinate x and y for Windows
787
788 Args:
789 x: X coordinate on the screen.
790 y: Y coordinate on the screen.
791
792 Returns:
793 An integer color code.
794 """
795 hdc = ctypes.windll.user32.GetDC(0)
796 color = ctypes.windll.gdi32.GetPixel(hdc, x, y)
797 return color
798
799 def _CheckForCrashes(self, last_action=None, last_action_param=None):
800 """Check for any browser/tab crashes and hangs.
801
802 Args:
803 last_action: Specify action taken before checking for crashes.
804 last_action_param: Parameter for last action.
805 """
806 self.assertTrue(self.GetBrowserWindowCount(),
807 msg='Browser crashed, no window is open.')
808
809 info = self.GetBrowserInfo()
810 breakpad_folder = info['properties']['DIR_CRASH_DUMPS']
811 old_dmp_files = glob.glob(os.path.join(breakpad_folder, '*.dmp'))
812
813 # Verify there're no crash dump files.
814 for dmp_file in glob.glob(os.path.join(breakpad_folder, '*.dmp')):
815 self.assertTrue(dmp_file in old_dmp_files,
816 msg='Crash dump %s found' % dmp_file)
817
818 # Check for any crashed tabs.
819 tabs = info['windows'][0]['tabs']
820 for tab in tabs:
821 if tab['url'] != 'about:blank':
822 if not self.GetDOMValue('document.body.innerHTML', 0, tab['index']):
823 self.fail(msg='Tab crashed on %s' % tab['url'])
824
825 # TODO(chrisphan): Check for tab hangs and browser hangs.
826 # TODO(chrisphan): Handle specific action: close browser, close tab.
827 if last_action == 'close tab':
828 pass
829 elif last_action == 'close browser':
830 pass
831 else:
832 pass
833
834 def _GetPlatformArchitecture(self):
835 """Get platform architecture.
836
837 Args:
838 last_action: Last action taken before checking for crashes.
839 last_action_param: Parameter for last action.
840
841 Returns:
842 A string representing the platform architecture.
843 """
844 if pyauto.PyUITest.IsWin():
845 if os.environ['PROGRAMFILES'] == 'C:\\Program Files (x86)':
846 return '64bit'
847 else:
848 return '32bit'
849 elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux():
850 if platform.machine() == 'x86_64':
851 return '64bit'
852 else:
853 return '32bit'
854 return '32bit'
855
856 def _HasFile(self, pattern, root=os.curdir):
857 """Check if a file matching the specified pattern exists in a directory.
858
859 Args:
860 pattern: Pattern of file name.
861 root: Directory to start looking.
862
863 Returns:
864 True, if root contains the file name pattern, or
865 False otherwise.
866 """
867 return len(glob.glob(os.path.join(root, pattern)))
868
869 def _HasPathInTree(self, pattern, is_file, root=os.curdir):
870 """Recursively checks if a file/directory matching a pattern exists.
871
872 Args:
873 pattern: Pattern of file or directory name.
874 is_file: True if looking for file, or False if looking for directory.
875 root: Directory to start looking.
876
877 Returns:
878 True, if root contains the directory name pattern, or
879 False otherwise.
880 """
881 for path, dirs, files in os.walk(os.path.abspath(root)):
882 if is_file:
883 if len(fnmatch.filter(files, pattern)):
884 return True
885 else:
886 if len(fnmatch.filter(dirs, pattern)):
887 return True
888 return False
889
890 def _GetDirectoryPath(self, pattern, root=os.curdir):
891 """Get the path of a directory in another directory.
892
893 Args:
894 pattern: Pattern of directory name.
895 root: Directory to start looking.
896
897 Returns:
898 A string of the path.
899 """
900 for path, dirs, files in os.walk(os.path.abspath(root)):
901 result = fnmatch.filter(dirs, pattern)
902 if result:
903 return os.path.join(path, result[0])
904 return None
905
906 def _HasAllSystemRequirements(self):
907 """Verify NaCl SDK installation system requirements.
908
909 Returns:
910 True, if system passed requirements, or
911 False otherwise.
912 """
913 # Check python version.
914 if sys.version_info[0:2] < (2, 6):
915 return False
916
917 # Check OS requirements.
918 if pyauto.PyUITest.IsMac():
919 mac_min_version = version.StrictVersion('10.6')
920 mac_version = version.StrictVersion(platform.mac_ver()[0])
921 if mac_version < mac_min_version:
922 return False
923 elif pyauto.PyUITest.IsWin():
924 if not (self.IsWin7() or self.IsWinVista() or self.IsWinXP()):
925 return False
926 elif pyauto.PyUITest.IsLinux():
927 pass # TODO(chrisphan): Check Lin requirements.
928 else:
929 return False
930
931 # Check for Chrome version compatibility.
932 # NaCl supports Chrome 10 and higher builds.
933 min_required_chrome_build = self._settings['min_required_chrome_build']
934 browser_info = self.GetBrowserInfo()
935 chrome_version = browser_info['properties']['ChromeVersion']
936 chrome_build = int(chrome_version.split('.')[0])
937 return chrome_build >= min_required_chrome_build
938
939 def _DownloadNaClSDK(self):
940 """Download NaCl SDK."""
941 self._temp_dir = tempfile.mkdtemp()
942 if pyauto.PyUITest.IsWin():
943 dl_file = urllib2.urlopen(self._settings['release_win_sdk_url'])
944 file_path = os.path.join(self._temp_dir, 'naclsdk_win.exe')
945 elif pyauto.PyUITest.IsMac():
946 dl_file = urllib2.urlopen(self._settings['release_mac_sdk_url'])
947 file_path = os.path.join(self._temp_dir, 'naclsdk_mac.tgz')
948 elif pyauto.PyUITest.IsLinux():
949 dl_file = urllib2.urlopen(self._settings['release_lin_sdk_url'])
950 file_path = os.path.join(self._temp_dir, 'naclsdk_linux.tgz')
951 else:
952 self.fail(msg='NaCl SDK does not support this OS.')
953
954 try:
955 f = open(file_path, 'wb')
956 f.write(dl_file.read())
957 except IOError:
958 self.fail(msg='Cannot open %s.' % file_path)
959 finally:
960 f.close()
961
962 def _ExtractNaClSDK(self):
963 """Extract NaCl SDK."""
964 if pyauto.PyUITest.IsWin():
965 source_file = os.path.join(self._temp_dir, 'naclsdk_win.exe')
966 proc = subprocess.Popen([source_file, '/S', '/D=' +
967 self._extracted_sdk_path],
968 stdout=subprocess.PIPE)
969 proc.communicate()
970 if not os.listdir(self._extracted_sdk_path):
971 self.fail(msg='Failed to extract NaCl SDK.')
972 elif pyauto.PyUITest.IsMac():
973 source_file = os.path.join(self._temp_dir, 'naclsdk_mac.tgz')
974 tar = tarfile.open(source_file, 'r')
975 tar.extractall(self._extracted_sdk_path)
976 elif pyauto.PyUITest.IsLinux():
977 source_file = os.path.join(self._temp_dir, 'naclsdk_linux.tgz')
978 tar = tarfile.open(source_file, 'r')
979 tar.extractall(self._extracted_sdk_path)
980 else:
981 self.fail(msg='NaCl SDK does not support this OS.')
982
983 def _IsURLAlive(self, url):
984 """Test if URL is alive."""
985 try:
986 urllib2.urlopen(url)
987 except:
988 return False
989 return True
990
991 def _CloseHTTPServer(self, proc=None):
992 """Close HTTP server.
993
994 Args:
995 proc: Process that opened the HTTP server.
996 proc is None when there is no pointer to HTTP server process.
997 """
998 if not self._IsURLAlive('http://localhost:5103'):
999 return
1000 response = urllib2.urlopen('http://localhost:5103')
1001 html = response.read()
1002 if not 'Native Client' in html:
1003 self.fail(msg='Port 5103 is in use.')
1004
1005 urllib2.urlopen('http://localhost:5103?quit=1')
1006 success = self.WaitUntil(
1007 lambda: self._IsURLAlive('http://localhost:5103'),
1008 timeout=30, retry_sleep=1, expect_retval=False)
1009 if not success:
1010 if not proc:
1011 self.fail(msg='Failed to close HTTP server.')
1012 else:
1013 if proc.poll() == None:
1014 try:
1015 proc.kill()
1016 except:
1017 self.fail(msg='Failed to close HTTP server')
1018
1019 def _SearchNaClSDKTarFile(self, search_list, source_file):
1020 """Search NaCl SDK tar file for example files and directories.
1021
1022 Args:
1023 search_list: A list of strings, representing file and
1024 directory names for which to search.
1025 source_file: The string name of an NaCl SDK tar file.
1026 """
1027 tar = tarfile.open(source_file, 'r')
1028
1029 # Look for files and directories in examples.
1030 files = copy.deepcopy(search_list)
1031 for tar_info in tar:
1032 file_name = tar_info.name
1033 if tar_info.isdir() and not file_name.endswith('/'):
1034 file_name = file_name + '/'
1035
1036 for name in files:
1037 if file_name.find('examples/' + name):
1038 files.remove(name)
1039 if not files:
1040 break
1041
1042 tar.close()
1043
1044 self.assertEqual(len(files), 0,
1045 msg='Missing files or directories: %s' %
1046 ', '.join(map(str, files)))
1047
1048 def _SearchNaClSDKFileWindows(self, search_list):
1049 """Search NaCl SDK file for example files and directories in Windows.
1050
1051 Args:
1052 search_list: A list of strings, representing file and
1053 directory names for which to search.
1054 """
1055 missing_items = []
1056 for name in search_list:
1057 is_file = name.find('/') < 0
1058 if not is_file:
1059 name = name.replace('/', '')
1060 if not self._HasPathInTree(name, is_file, self._extracted_sdk_path):
1061 missing_items.append(name)
1062 self.assertEqual(len(missing_items), 0,
1063 msg='Missing files or directories: %s' %
1064 ', '.join(map(str, missing_items)))
1065
1066 def _EnableNaClPlugin(self):
1067 """Enable NaCl plugin."""
1068 nacl_plugin = (self.GetPluginsInfo().PluginForName('Chrome NaCl') or
1069 self.GetPluginsInfo().PluginForName('Native Client'))
1070 if not nacl_plugin:
1071 self.fail(msg='No NaCl plugin found.')
1072 self.EnablePlugin(nacl_plugin[0]['path'])
1073
1074 self.NavigateToURL('about:flags')
1075
1076 js_code = """
1077 chrome.send('enableFlagsExperiment', ['enable-nacl', 'true']);
1078 requestFlagsExperimentsData();
1079 window.domAutomationController.send('done');
1080 """
1081 self.ExecuteJavascript(js_code)
1082 self.RestartBrowser(False)
1083
1084 self.NavigateToURL('about://version')
1085 self.assertEqual(self.FindInPage('--enable-nacl')['match_count'], 1,
1086 msg='Missing expected Chrome flag --enable-nacl.')
1087
1088
1089 if __name__ == '__main__':
1090 pyauto_functional.Main()
OLDNEW
« no previous file with comments | « functional/PYAUTO_TESTS ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698