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

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