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

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

Powered by Google App Engine
This is Rietveld 408576698