Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / test / functional / nacl_sdk.py
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
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 re
16 import shutil
17 import subprocess
18 import sys
19 import tempfile
20 import urllib2
21 import xml.dom.minidom
22 import zipfile
23
24 import pyauto_functional  # Must be imported before pyauto.
25 import pyauto
26 import pyauto_utils
27 import test_utils
28
29
30 class NaClSDKTest(pyauto.PyUITest):
31   """Tests for the NaCl SDK."""
32   _isExamplesTest = False
33   _extracted_sdk_path = None
34   _temp_dir = None
35   _updated_pepper_versions = []
36   _latest_updated_pepper_versions = []
37   _settings = {
38       'post_sdk_download_url': 'http://code.google.com/chrome/nativeclient/'
39           'docs/download.html',
40       'post_sdk_zip': 'http://storage.googleapis.com/'
41           'nativeclient-mirror/nacl/nacl_sdk/nacl_sdk.zip',
42       'min_required_chrome_build': 14,
43   }
44
45   def tearDown(self):
46     pyauto.PyUITest.tearDown(self)
47     if not self._isExamplesTest:
48       self._RemoveDownloadedTestFile()
49
50   def testNaClSDK(self):
51     """Verify that NaCl SDK is working properly."""
52     if not self._HasAllSystemRequirements():
53       logging.info('System does not meet the requirements.')
54       return
55     self._extracted_sdk_path = tempfile.mkdtemp()
56     self._VerifyDownloadLinks()
57     self._VerifyNaClSDKInstaller()
58     self._VerifyInstall()
59     self._VerifyUpdate()
60     self._LaunchServerAndVerifyExamplesAllPepperVersions()
61
62   def NaClSDKExamples(self):
63     """Verify if NaCl SDK examples are working."""
64     self._isExamplesTest = True
65     nacl_sdk_root = os.environ.get('NACL_SDK_ROOT', None)
66     pepper_version = os.environ.get('PEPPER_VER', None)
67     if nacl_sdk_root and pepper_version:
68       self._LaunchServerAndVerifyExamples('pepper_' + pepper_version,
69           nacl_sdk_root)
70     else:
71       self.fail(msg='Missing pepper version to be checked or SDK path.')
72
73   def _VerifyDownloadLinks(self):
74     """Verify the download links.
75
76     Simply verify that NaCl download links exist in html page.
77     """
78     html = None
79     for i in xrange(3):
80       try:
81         html = urllib2.urlopen(self._settings['post_sdk_download_url']).read()
82         break
83       except:
84         pass
85     self.assertTrue(html,
86                     msg='Cannot open URL: %s' %
87                     self._settings['post_sdk_download_url'])
88     sdk_url = self._settings['post_sdk_zip']
89     self.assertTrue(sdk_url in html,
90                     msg='Missing SDK download URL: %s' % sdk_url)
91
92   def _VerifyNaClSDKInstaller(self):
93     """Verify NaCl SDK installer."""
94     search_list = [
95         'sdk_cache/',
96         'sdk_tools/',
97     ]
98     mac_lin_additional_search_items = [
99         'naclsdk',
100     ]
101     win_additional_search_items = [
102         'naclsdk.bat'
103     ]
104     self._DownloadNaClSDK()
105     self._ExtractNaClSDK()
106     if pyauto.PyUITest.IsWin():
107       self._SearchNaClSDKFile(
108           search_list + win_additional_search_items)
109     elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux():
110       self._SearchNaClSDKFile(
111           search_list + mac_lin_additional_search_items)
112     else:
113       self.fail(msg='NaCl SDK does not support this OS.')
114
115   def _VerifyInstall(self):
116     """Install NACL sdk."""
117     # Executing naclsdk(.bat) list
118     if pyauto.PyUITest.IsWin():
119       source_file = os.path.join(
120           self._extracted_sdk_path, 'nacl_sdk', 'naclsdk.bat')
121     elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux():
122       source_file = os.path.join(
123           self._extracted_sdk_path, 'nacl_sdk', 'naclsdk')
124       subprocess.call(['chmod', '-R', '755', self._extracted_sdk_path])
125     else:
126       self.fail(msg='NaCl SDK does not support this OS.')
127     subprocess.Popen([source_file, 'list'],
128                      stdout=subprocess.PIPE,
129                      stderr=subprocess.PIPE).communicate()
130
131   def _VerifyUpdate(self):
132     """Update NACL sdk"""
133     # Executing naclsdk(.bat) update
134     if pyauto.PyUITest.IsWin():
135       source_file = os.path.join(self._extracted_sdk_path, 'nacl_sdk',
136                                  'naclsdk.bat')
137     elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux():
138       source_file = os.path.join(self._extracted_sdk_path, 'nacl_sdk',
139                                  'naclsdk')
140     else:
141       self.fail(msg='NaCl SDK does not support this OS.')
142     # Executing nacl_sdk(.bat) update to get the latest version.
143     updated_output = subprocess.Popen([source_file, 'update'],
144         stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
145     self._updated_pepper_versions.extend(
146         re.findall('Updating bundle (pepper_[0-9]{2})', updated_output))
147     self._updated_pepper_versions = list(set(self._updated_pepper_versions))
148     self._updated_pepper_versions.sort(key=str.lower)
149     updated_pepper_versions_len = len(self._updated_pepper_versions)
150     self._latest_updated_pepper_versions = filter(
151         lambda x: x >= 'pepper_18', self._updated_pepper_versions)
152
153   def _GetURLForExampleName(self, name, toolchain):
154     return 'http://localhost:5103/%s/index_%s.html' % (name, toolchain)
155
156   def _GetExampleNamesAndURLs(self, examples_path):
157     """Get a list of all examples as (name, url) tuples.
158
159     Args:
160       examples_path: The path to the examples directory in the NaCl SDK.
161     """
162     toolchains = ['newlib', 'glibc', 'pnacl']
163
164     examples = []
165     for toolchain in toolchains:
166       for example in os.listdir(examples_path):
167         html_path = os.path.join(examples_path, example,
168             'index_%s.html' % (toolchain,))
169         if os.path.exists(html_path):
170           example_url = self._GetURLForExampleName(example, toolchain)
171           examples.append((example, example_url))
172     return examples
173
174   def _LaunchServerAndVerifyExamplesAllPepperVersions(self):
175     for pepper_version in self._latest_updated_pepper_versions:
176       pepper_path = os.path.join(self._extracted_sdk_path,
177           'nacl_sdk', 'pepper_' + str(pepper_version))
178       self._LaunchServerAndVerifyExamples(pepper_version, pepper_path)
179
180   def _LaunchServerAndVerifyExamples(self, pepper_version, pepper_path):
181     """Start local HTTP server and verify examples."""
182     if self._ChromeAndPepperVersionMatch(pepper_version):
183       # Close server if it's already open.
184       if self._IsURLAlive('http://localhost:5103'):
185         self._CloseHTTPServer()
186
187       examples_path = os.path.join(pepper_path, 'examples')
188
189       # Launch local http server.
190       proc = subprocess.Popen(['make RUN'], shell=True, cwd=examples_path)
191       self.WaitUntil(
192           lambda: self._IsURLAlive('http://localhost:5103'),
193           timeout=150, retry_sleep=1)
194
195       examples = self._GetExampleNamesAndURLs(examples_path)
196       try:
197         self._OpenExamplesAndStartTest(examples)
198       finally:
199         self._CloseHTTPServer(proc)
200
201     else:
202       self.pprint('Pepper Version %s does not match the Chrome version %s.'
203           % (pepper_version,
204           self.GetBrowserInfo()['properties']['ChromeVersion']))
205
206   def _ChromeAndPepperVersionMatch(self, pepper_version='pepper_18'):
207     """Determine if chrome and pepper version match"""
208     version_number = re.findall('pepper_([0-9]{2})', pepper_version)
209     browser_info = self.GetBrowserInfo()
210     chrome_version = browser_info['properties']['ChromeVersion']
211     chrome_build = int(chrome_version.split('.')[0])
212     return int(chrome_build) == int(version_number[0])
213
214   def _RemoveDownloadedTestFile(self):
215     """Delete downloaded files and dirs from downloads directory."""
216     if self._extracted_sdk_path and os.path.exists(self._extracted_sdk_path):
217       self._CloseHTTPServer()
218
219       def _RemoveFile():
220         shutil.rmtree(self._extracted_sdk_path, ignore_errors=True)
221         return os.path.exists(self._extracted_sdk_path)
222
223       success = self.WaitUntil(_RemoveFile, retry_sleep=2,
224                                expect_retval=False)
225       self.assertTrue(success,
226                       msg='Cannot remove %s' % self._extracted_sdk_path)
227
228     if self._temp_dir:
229       pyauto_utils.RemovePath(self._temp_dir)
230
231   def _OpenExamplesAndStartTest(self, examples):
232     """Open each example and verify that it's working.
233
234     Args:
235       examples: A list of example (name, url) tuples.
236     """
237     example_verify_funcs = {
238         'dlopen': self._VerifyDynamicLibraryOpen,
239         'file_io': self._VerifyFileIoExample,
240         'geturl': self._VerifyGetURLExample,
241         'input_events': self._VerifyInputEventsExample,
242         'load_progress': self._VerifyLoadProgressExample,
243         'mt_input_events': self._VerifyMultithreadedInputEventsExample,
244         'pi_generator': self._VerifyPiGeneratorExample,
245         'sine_synth': self._VerifySineSynthExample,
246         'websocket': self._VerifyWebSocketExample,
247     }
248
249     # Remove examples that we don't yet verify
250     examples = [(name, url) for name, url in examples
251         if name in example_verify_funcs]
252
253     # Open all examples.
254     for name, url in examples:
255       self.AppendTab(pyauto.GURL(url))
256       self._CheckForCrashes()
257
258     # Verify all examples are working.
259     for name, url in examples:
260       self._VerifyAnExample(name, url, example_verify_funcs[name])
261     self._CheckForCrashes()
262
263     # Close each tab and check for crashes.
264     tab_count = self.GetTabCount()
265     for index in xrange(tab_count - 1, 0, -1):
266       self.CloseTab(tab_index=index)
267       self._CheckForCrashes()
268
269   def _VerifyAnExample(self, name, url, verify_func):
270     """Verify NaCl example is working.
271
272     Args:
273       name: A string name of the example.
274       url: A string url of the example.
275       verify_func: The function to verify the example.
276           Takes (tab_index, name, url) as parameters.
277     """
278     if not verify_func:
279       self.fail(msg='No test available for %s.' % name)
280
281     info = self.GetBrowserInfo()
282     tabs = info['windows'][0]['tabs']
283     tab_index = None
284     for tab in tabs:
285       if url == tab['url']:
286         self.ActivateTab(tab['index'])
287         tab_index = tab['index']
288         break
289
290     if tab_index:
291       verify_func(tab_index, name, url)
292
293   def _VerifyElementPresent(self, element_id, expected_value, tab_index, msg,
294                             attribute='innerHTML', timeout=150):
295     """Determine if dom element has the expected value.
296
297     Args:
298       element_id: Dom element's id.
299       expected_value: String to be matched against the Dom element.
300       tab_index: Tab index to work on.
301       attribute: Attribute to match |expected_value| against, if
302                  given. Defaults to 'innerHTML'.
303       timeout: The max timeout (in secs) for which to wait.
304     """
305     js_code = """
306         var output = document.getElementById('%s').%s;
307         var result;
308         if (output.indexOf('%s') != -1)
309           result = 'pass';
310         else
311           result = 'fail';
312         window.domAutomationController.send(result);
313     """ % (element_id, attribute, expected_value)
314     success = self.WaitUntil(
315         lambda: self.ExecuteJavascript(js_code, tab_index),
316         timeout=timeout, expect_retval='pass')
317     self.assertTrue(success, msg=msg)
318
319   def _CreateJSToSimulateMouseclick(self):
320     """Create javascript to simulate mouse click event."""
321     js_code = """
322         var rightClick = document.createEvent('MouseEvents');
323         rightClick.initMouseEvent(
324           'mousedown', true, true, document,
325           1, 32, 121, 10, 100,
326           false, false, false, false,
327           2, common.naclModule
328         );
329         common.naclModule.dispatchEvent(rightClick);
330         window.domAutomationController.send('done');
331     """
332     return js_code
333
334   def _VerifyInputEventsExample(self, tab_index, name, url):
335     """Verify Input Events Example.
336
337     Args:
338       tab_index: Tab index integer that the example is on.
339       name: A string name of the example.
340       url: A string url of the example.
341     """
342     success = self._VerifyElementPresent('eventString', 'DidChangeView',
343         tab_index, msg='Example %s failed. URL: %s' % (name, url))
344
345     # Simulate mouse click on event module.
346     js_code = self._CreateJSToSimulateMouseclick()
347     self.ExecuteJavascript(js_code, tab_index)
348
349     # Check if 'eventString' has handled above mouse click.
350     success = self.WaitUntil(
351         lambda: re.search('DidHandleInputEvent', self.GetDOMValue(
352           'document.getElementById("eventString").innerHTML',
353           tab_index)).group(), expect_retval='DidHandleInputEvent')
354     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
355
356   def _VerifyMultithreadedInputEventsExample(self, tab_index, name, url):
357     """Verify Input Events Example.
358
359     Args:
360       tab_index: Tab index integer that the example is on.
361       name: A string name of the example.
362       url: A string url of the example.
363     """
364     success = self.WaitUntil(
365         lambda: bool(self.GetDOMValue(
366           'document.getElementById("eventString").innerHTML',
367           tab_index).find('DidChangeView') + 1))
368
369     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
370
371     # Simulate mouse click on event module.
372     js_code = self._CreateJSToSimulateMouseclick()
373     self.ExecuteJavascript(js_code, tab_index)
374
375     # Check if above mouse click is handled.
376     success = self._VerifyElementPresent('eventString', 'Mouse event',
377         tab_index, msg='Example %s failed. URL: %s' % (name, url))
378
379     # Kill worker thread and queue
380     js_code = """
381       document.getElementsByTagName('button')[0].click();
382       window.domAutomationController.send('done');
383     """
384     self.ExecuteJavascript(js_code, tab_index)
385
386     # Check if main thread has cancelled queue.
387     success = self._VerifyElementPresent('eventString', 'Received cancel',
388         tab_index, msg='Example %s failed. URL: %s' % (name, url))
389
390     # Simulate mouse click on event module.
391     js_code = self._CreateJSToSimulateMouseclick()
392     self.ExecuteJavascript(js_code, tab_index)
393
394     # Check if above mouse click is not handled after killing worker thread.
395     def _CheckMouseClickEventStatus():
396       return self.GetDOMValue(
397         'document.getElementById("eventString").innerHTML',
398         tab_index).find('Mouse event', self.GetDOMValue(
399         'document.getElementById("eventString").innerHTML', tab_index).find(
400         'Received cancel'))
401
402     success = self.WaitUntil(_CheckMouseClickEventStatus, expect_retval=-1)
403     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
404
405   def _VerifyFileIoExample(self, tab_index, name, url):
406     """Verify File IO Example.
407
408     Args:
409       tab_index: Tab index integer that the example is on.
410       name: A string name of the example.
411       url: A string url of the example.
412     """
413     def _CheckStatus(substring_expected, fail_msg):
414       self.assertTrue(
415           self.WaitUntil(
416             lambda: self.GetDOMValue(
417               'document.getElementById("statusField").innerHTML', tab_index)\
418                   .find(substring_expected) != -1, expect_retval=True),
419           msg='Example %s failed. URL: %s. Reason: %s' % (name, url, fail_msg))
420
421     # Give permission to use file system by clicking infobar OK
422     infobar_index = test_utils.WaitForInfobarTypeAndGetIndex(self,
423         'confirm_infobar', 0, tab_index)
424     self.PerformActionOnInfobar('accept', infobar_index, 0, tab_index)
425     _CheckStatus('Ready!', 'NaCl module load')
426
427     # Check that deleting non-existing files gives file not found
428     js_code = """
429       document.getElementById('file_name').value = '/abc';
430       document.getElementById('file_editor').value = 'test';
431       document.getElementById('delete_but').click();
432       window.domAutomationController.send('done');
433     """
434     self.ExecuteJavascript(js_code, tab_index)
435     _CheckStatus('File not found', 'Delete non-existing')
436
437     # Check that saving works
438     js_code = """
439       document.getElementById('save_but').click();
440       window.domAutomationController.send('done');
441     """
442     self.ExecuteJavascript(js_code, tab_index)
443     _CheckStatus('Save successful', 'Save test')
444
445     # Check that we load what we saved
446     js_code = """
447       document.getElementById('file_editor').value = 'different';
448       document.getElementById('load_but').click();
449       window.domAutomationController.send('done');
450     """
451     self.ExecuteJavascript(js_code, tab_index)
452     _CheckStatus('Load complete', 'Load test')
453     self.assertTrue(
454         self.GetDOMValue('document.getElementById("file_editor").value',
455           tab_index).find('test') != -1, msg='Loaded wrong text or failed')
456
457     # Check that we delete files successfully
458     js_code = """
459       document.getElementById('delete_but').click();
460       window.domAutomationController.send('done');
461     """
462     self.ExecuteJavascript(js_code, tab_index)
463     _CheckStatus('File deleted', 'Delete test')
464
465     # Check that file is deleted and load produces not found
466     js_code = """
467       document.getElementById('load_but').click();
468       window.domAutomationController.send('done');
469     """
470     self.ExecuteJavascript(js_code, tab_index)
471     _CheckStatus('File not found', 'Load deleted test')
472
473   def _VerifyWebSocketExample(self, tab_index, name, url):
474     """Verify Web Socket Open Example.
475
476     Args:
477       tab_index: Tab index integer that the example is on.
478       name: A string name of the example.
479       url: A string url of the example.
480     """
481     # Check if example is loaded.
482     success = self.WaitUntil(
483         lambda: self.GetDOMValue(
484             'document.getElementById("statusField").innerHTML', tab_index),
485             expect_retval='SUCCESS')
486     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
487
488     # Simulate clicking on Connect button to establish a connection.
489     js_code = """
490       document.getElementsByTagName('input')[1].click();
491       window.domAutomationController.send('done');
492     """
493     self.ExecuteJavascript(js_code, tab_index)
494
495     # Check if connected
496     success = self._VerifyElementPresent('log', 'connected', tab_index,
497         msg='Example %s failed. URL: %s' % (name, url))
498
499     # Simulate clicking on Send button to send text message in log.
500     js_code = """
501       document.getElementsByTagName('input')[3].click();
502       window.domAutomationController.send('done');
503     """
504     self.ExecuteJavascript(js_code, tab_index)
505     success = self.WaitUntil(
506         lambda: bool(re.search('send:', self.GetDOMValue(
507             'document.getElementById("log").textContent', tab_index))))
508     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
509
510   def _VerifyDynamicLibraryOpen(self, tab_index, name, url):
511     """Verify Dynamic Library Open Example.
512
513     Args:
514       tab_index: Tab index integer that the example is on.
515       name: A string name of the example.
516       url: A string url of the example.
517     """
518     # Check if example is loaded.
519     success = self._VerifyElementPresent('log', 'Eightball loaded!',
520         tab_index, msg='Example %s failed. URL: %s' % (name, url))
521
522     # Simulate clicking on ASK button and check answer log for desired answer.
523     js_code = """
524       document.getElementsByTagName('input')[1].click();
525       window.domAutomationController.send('done');
526     """
527     self.ExecuteJavascript(js_code, tab_index)
528     def _CheckAnswerLog():
529       return bool(re.search(r'NO|YES|42|MAYBE NOT|DEFINITELY|'
530         'ASK ME TOMORROW|MAYBE|PARTLY CLOUDY',
531         self.GetDOMValue('document.getElementById("log").innerHTML',
532         tab_index)))
533
534     success = self.WaitUntil(_CheckAnswerLog)
535     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
536
537   def _VerifyLoadProgressExample(self, tab_index, name, url):
538     """Verify Dynamic Library Open Example.
539
540     Args:
541       tab_index: Tab index integer that the example is on.
542       name: A string name of the example.
543       url: A string url of the example.
544     """
545     # Check if example loads and displays loading progress.
546     success = self.WaitUntil(
547         lambda: self.GetDOMValue(
548         'document.getElementById("statusField").innerHTML', tab_index),
549         timeout=150, expect_retval='SUCCESS')
550     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
551
552     def _CheckLoadProgressStatus():
553       return re.search(
554           r'(loadstart).+(progress:).+(load).+(loadend).+(lastError:)',
555           self.GetDOMValue(
556           'document.getElementById("log").innerHTML', tab_index))
557     success = self.WaitUntil(_CheckLoadProgressStatus)
558     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
559
560   def _VerifyPiGeneratorExample(self, tab_index, name, url):
561     """Verify Pi Generator Example.
562
563     Args:
564       tab_index: Tab index integer that the example is on.
565       name: A string name of the example.
566       url: A string url of the example.
567     """
568     success = self.WaitUntil(
569         lambda: self.GetDOMValue('document.getElementById("pi").value',
570             tab_index)[0:3],
571         expect_retval='3.1')
572     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
573
574   def _VerifySineSynthExample(self, tab_index, name, url):
575     """Verify Sine Wave Synthesizer Example.
576
577     Args:
578       tab_index: Tab index integer that the example is on.
579       name: A string name of the example.
580       url: A string url of the example.
581     """
582     success = self.WaitUntil(
583         lambda: self.GetDOMValue(
584                     'document.getElementById("frequency_field").value',
585                     tab_index), timeout=150, expect_retval='440')
586     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
587     self.ExecuteJavascript(
588         'document.body.getElementsByTagName("button")[0].click();'
589         'window.domAutomationController.send("done")',
590         tab_index)
591
592   def _VerifyGetURLExample(self, tab_index, name, url):
593     """Verify GetURL Example.
594
595     Args:
596       tab_index: Tab index integer that the example is on.
597       name: A string name of the example.
598       url: A string url of the example.
599     """
600     success = self.WaitUntil(
601         lambda: self.GetDOMValue(
602                     'document.getElementById("statusField").innerHTML',
603                     tab_index), timeout=150, expect_retval='SUCCESS')
604     self.assertTrue(success, msg='Example %s failed. URL: %s' % (name, url))
605     self.ExecuteJavascript(
606         'document.getElementById("button").click();'
607         'window.domAutomationController.send("done")',
608         tab_index)
609     success = self._VerifyElementPresent('general_output', 'test passed',
610         tab_index, msg='Example %s failed. URL: %s' % (name, url))
611
612   def _CheckForCrashes(self):
613     """Check for any browser/tab crashes and hangs."""
614     self.assertTrue(self.GetBrowserWindowCount(),
615                     msg='Browser crashed, no window is open.')
616
617     info = self.GetBrowserInfo()
618     breakpad_folder = info['properties']['DIR_CRASH_DUMPS']
619     old_dmp_files = glob.glob(os.path.join(breakpad_folder, '*.dmp'))
620
621     # Verify there're no crash dump files.
622     for dmp_file in glob.glob(os.path.join(breakpad_folder, '*.dmp')):
623       self.assertTrue(dmp_file in old_dmp_files,
624                       msg='Crash dump %s found' % dmp_file)
625
626     # Check for any crashed tabs.
627     tabs = info['windows'][0]['tabs']
628     for tab in tabs:
629       if tab['url'] != 'about:blank':
630         if not self.GetDOMValue('document.body.innerHTML', tab['index']):
631           self.fail(msg='Tab crashed on %s' % tab['url'])
632
633   def _GetPlatformArchitecture(self):
634     """Get platform architecture.
635
636     Returns:
637       A string representing the platform architecture.
638     """
639     if pyauto.PyUITest.IsWin():
640       if os.environ['PROGRAMFILES'] == 'C:\\Program Files (x86)':
641         return '64bit'
642       else:
643         return '32bit'
644     elif pyauto.PyUITest.IsMac() or pyauto.PyUITest.IsLinux():
645       if platform.machine() == 'x86_64':
646         return '64bit'
647       else:
648         return '32bit'
649     return '32bit'
650
651   def _HasPathInTree(self, pattern, is_file, root=os.curdir):
652     """Recursively checks if a file/directory matching a pattern exists.
653
654     Args:
655       pattern: Pattern of file or directory name.
656       is_file: True if looking for file, or False if looking for directory.
657       root: Directory to start looking.
658
659     Returns:
660       True, if root contains the directory name pattern, or
661       False otherwise.
662     """
663     for path, dirs, files in os.walk(os.path.abspath(root)):
664       if is_file:
665         if len(fnmatch.filter(files, pattern)):
666           return True
667       else:
668         if len(fnmatch.filter(dirs, pattern)):
669           return True
670     return False
671
672   def _HasAllSystemRequirements(self):
673     """Verify NaCl SDK installation system requirements.
674
675     Returns:
676         True, if system passed requirements, or
677         False otherwise.
678     """
679     # Check python version.
680     if sys.version_info[0:2] < (2, 6):
681       return False
682
683     # Check OS requirements.
684     if pyauto.PyUITest.IsMac():
685       mac_min_version = version.StrictVersion('10.6')
686       mac_version = version.StrictVersion(platform.mac_ver()[0])
687       if mac_version < mac_min_version:
688         return False
689     elif pyauto.PyUITest.IsWin():
690       if not (self.IsWin7() or self.IsWinVista() or self.IsWinXP()):
691         return False
692     elif pyauto.PyUITest.IsLinux():
693       pass  # TODO(chrisphan): Check Lin requirements.
694     else:
695       return False
696
697     # Check for Chrome version compatibility.
698     # NaCl supports Chrome 10 and higher builds.
699     min_required_chrome_build = self._settings['min_required_chrome_build']
700     browser_info = self.GetBrowserInfo()
701     chrome_version = browser_info['properties']['ChromeVersion']
702     chrome_build = int(chrome_version.split('.')[0])
703     return chrome_build >= min_required_chrome_build
704
705   def _DownloadNaClSDK(self):
706     """Download NaCl SDK."""
707     self._temp_dir = tempfile.mkdtemp()
708     dl_file = urllib2.urlopen(self._settings['post_sdk_zip'])
709     file_path = os.path.join(self._temp_dir, 'nacl_sdk.zip')
710
711     try:
712       f = open(file_path, 'wb')
713       f.write(dl_file.read())
714     except IOError:
715       self.fail(msg='Cannot open %s.' % file_path)
716     finally:
717       f.close()
718
719   def _ExtractNaClSDK(self):
720     """Extract NaCl SDK."""
721     source_file = os.path.join(self._temp_dir, 'nacl_sdk.zip')
722     if zipfile.is_zipfile(source_file):
723       zip = zipfile.ZipFile(source_file, 'r')
724       zip.extractall(self._extracted_sdk_path)
725     else:
726       self.fail(msg='%s is not a valid zip file' % source_file)
727
728   def _IsURLAlive(self, url):
729     """Test if URL is alive."""
730     try:
731       urllib2.urlopen(url)
732     except:
733       return False
734     return True
735
736   def _CloseHTTPServer(self, proc=None):
737     """Close HTTP server.
738
739     Args:
740       proc: Process that opened the HTTP server.
741       proc is None when there is no pointer to HTTP server process.
742     """
743     if not self._IsURLAlive('http://localhost:5103'):
744       return
745     response = urllib2.urlopen('http://localhost:5103')
746     html = response.read()
747     if not 'Native Client' in html:
748       self.fail(msg='Port 5103 is in use.')
749
750     urllib2.urlopen('http://localhost:5103?quit=1')
751     success = self.WaitUntil(
752         lambda: self._IsURLAlive('http://localhost:5103'),
753         retry_sleep=1, expect_retval=False)
754     if not success:
755       if not proc:
756         self.fail(msg='Failed to close HTTP server.')
757       else:
758         if proc.poll() == None:
759           try:
760             proc.kill()
761           except:
762             self.fail(msg='Failed to close HTTP server.')
763
764   def _SearchNaClSDKFile(self, search_list):
765     """Search NaCl SDK file for example files and directories in Windows.
766
767     Args:
768       search_list: A list of strings, representing file and
769                    directory names for which to search.
770     """
771     missing_items = []
772     for name in search_list:
773       is_file = name.find('/') < 0
774       if not is_file:
775         name = name.replace('/', '')
776       if not self._HasPathInTree(name, is_file, self._extracted_sdk_path):
777         missing_items.append(name)
778     self.assertEqual(len(missing_items), 0,
779                      msg='Missing files or directories: %s' %
780                          ', '.join(map(str, missing_items)))
781
782   def ExtraChromeFlags(self):
783     """Ensures Nacl is enabled.
784
785     Returns:
786       A list of extra flags to pass to Chrome when it is launched.
787     """
788     extra_chrome_flags = [
789         '--enable-nacl',
790         '--enable-nacl-exception-handling',
791         '--nacl-gdb',
792       ]
793     return pyauto.PyUITest.ExtraChromeFlags(self) + extra_chrome_flags
794
795 if __name__ == '__main__':
796   pyauto_functional.Main()