Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / test / chromedriver / test / run_py_tests.py
1 #!/usr/bin/env python
2 # Copyright 2013 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 """End to end tests for ChromeDriver."""
7
8 import base64
9 import json
10 import math
11 import optparse
12 import os
13 import socket
14 import subprocess
15 import sys
16 import tempfile
17 import threading
18 import time
19 import unittest
20 import urllib2
21
22 _THIS_DIR = os.path.abspath(os.path.dirname(__file__))
23 sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir))
24 sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'client'))
25 sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'server'))
26
27 import chrome_paths
28 import chromedriver
29 import unittest_util
30 import util
31 import server
32 from webelement import WebElement
33 import webserver
34
35 _TEST_DATA_DIR = os.path.join(chrome_paths.GetTestData(), 'chromedriver')
36
37 if util.IsLinux():
38   sys.path.insert(0, os.path.join(chrome_paths.GetSrc(), 'build', 'android'))
39   from pylib import android_commands
40   from pylib import constants
41   from pylib import forwarder
42   from pylib import valgrind_tools
43   from pylib.device import device_utils
44
45
46 _NEGATIVE_FILTER = [
47     # https://code.google.com/p/chromedriver/issues/detail?id=213
48     'ChromeDriverTest.testClickElementInSubFrame',
49     # This test is flaky since it uses setTimeout.
50     # Re-enable once crbug.com/177511 is fixed and we can remove setTimeout.
51     'ChromeDriverTest.testAlert',
52 ]
53
54 _VERSION_SPECIFIC_FILTER = {}
55 _VERSION_SPECIFIC_FILTER['HEAD'] = [
56     # https://code.google.com/p/chromedriver/issues/detail?id=815
57     'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
58 ]
59
60 _OS_SPECIFIC_FILTER = {}
61 _OS_SPECIFIC_FILTER['win'] = [
62     # https://code.google.com/p/chromedriver/issues/detail?id=214
63     'ChromeDriverTest.testCloseWindow',
64     # https://code.google.com/p/chromedriver/issues/detail?id=299
65     'ChromeLogPathCapabilityTest.testChromeLogPath',
66 ]
67 _OS_SPECIFIC_FILTER['linux'] = [
68     # Xvfb doesn't support maximization.
69     'ChromeDriverTest.testWindowMaximize',
70     # https://code.google.com/p/chromedriver/issues/detail?id=302
71     'ChromeDriverTest.testWindowPosition',
72     'ChromeDriverTest.testWindowSize',
73 ]
74 _OS_SPECIFIC_FILTER['mac'] = [
75     # https://code.google.com/p/chromedriver/issues/detail?id=304
76     'ChromeDriverTest.testGoBackAndGoForward',
77 ]
78
79 _DESKTOP_NEGATIVE_FILTER = [
80     # Desktop doesn't support touch (without --touch-events).
81     'ChromeDriverTest.testSingleTapElement',
82     'ChromeDriverTest.testTouchDownUpElement',
83     'ChromeDriverTest.testTouchFlickElement',
84     'ChromeDriverTest.testTouchMovedElement',
85     'ChromeDriverAndroidTest.*',
86 ]
87
88
89 def _GetDesktopNegativeFilter(version_name):
90   filter = _NEGATIVE_FILTER + _DESKTOP_NEGATIVE_FILTER
91   os = util.GetPlatformName()
92   if os in _OS_SPECIFIC_FILTER:
93     filter += _OS_SPECIFIC_FILTER[os]
94   if version_name in _VERSION_SPECIFIC_FILTER:
95     filter += _VERSION_SPECIFIC_FILTER[version_name]
96   return filter
97
98 _ANDROID_NEGATIVE_FILTER = {}
99 _ANDROID_NEGATIVE_FILTER['chrome'] = (
100     _NEGATIVE_FILTER + [
101         # TODO(chrisgao): fix hang of tab crash test on android.
102         'ChromeDriverTest.testTabCrash',
103         # Android doesn't support switches and extensions.
104         'ChromeSwitchesCapabilityTest.*',
105         'ChromeExtensionsCapabilityTest.*',
106         'MobileEmulationCapabilityTest.*',
107         # https://crbug.com/274650
108         'ChromeDriverTest.testCloseWindow',
109         # https://code.google.com/p/chromedriver/issues/detail?id=270
110         'ChromeDriverTest.testPopups',
111         # https://code.google.com/p/chromedriver/issues/detail?id=298
112         'ChromeDriverTest.testWindowPosition',
113         'ChromeDriverTest.testWindowSize',
114         'ChromeDriverTest.testWindowMaximize',
115         'ChromeLogPathCapabilityTest.testChromeLogPath',
116         'RemoteBrowserTest.*',
117         # Don't enable perf testing on Android yet.
118         'PerfTest.testSessionStartTime',
119         'PerfTest.testSessionStopTime',
120         'PerfTest.testColdExecuteScript',
121         # https://code.google.com/p/chromedriver/issues/detail?id=459
122         'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
123     ]
124 )
125 _ANDROID_NEGATIVE_FILTER['chrome_stable'] = (
126     _ANDROID_NEGATIVE_FILTER['chrome'])
127 _ANDROID_NEGATIVE_FILTER['chrome_beta'] = (
128     _ANDROID_NEGATIVE_FILTER['chrome'])
129 _ANDROID_NEGATIVE_FILTER['chrome_shell'] = (
130     _ANDROID_NEGATIVE_FILTER['chrome'] + [
131         # ChromeShell doesn't support multiple tabs.
132         'ChromeDriverTest.testGetWindowHandles',
133         'ChromeDriverTest.testSwitchToWindow',
134         'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
135     ]
136 )
137 _ANDROID_NEGATIVE_FILTER['chromedriver_webview_shell'] = (
138     _ANDROID_NEGATIVE_FILTER['chrome_shell'])
139
140
141 class ChromeDriverBaseTest(unittest.TestCase):
142   """Base class for testing chromedriver functionalities."""
143
144   def __init__(self, *args, **kwargs):
145     super(ChromeDriverBaseTest, self).__init__(*args, **kwargs)
146     self._drivers = []
147
148   def tearDown(self):
149     for driver in self._drivers:
150       try:
151         driver.Quit()
152       except:
153         pass
154
155   def CreateDriver(self, server_url=None, **kwargs):
156     if server_url is None:
157       server_url = _CHROMEDRIVER_SERVER_URL
158
159     android_package = None
160     android_activity = None
161     android_process = None
162     if _ANDROID_PACKAGE_KEY:
163       android_package = constants.PACKAGE_INFO[_ANDROID_PACKAGE_KEY].package
164       if _ANDROID_PACKAGE_KEY == 'chromedriver_webview_shell':
165         android_activity = constants.PACKAGE_INFO[_ANDROID_PACKAGE_KEY].activity
166         android_process = '%s:main' % android_package
167
168     driver = chromedriver.ChromeDriver(server_url,
169                                        chrome_binary=_CHROME_BINARY,
170                                        android_package=android_package,
171                                        android_activity=android_activity,
172                                        android_process=android_process,
173                                        **kwargs)
174     self._drivers += [driver]
175     return driver
176
177
178 class ChromeDriverTest(ChromeDriverBaseTest):
179   """End to end tests for ChromeDriver."""
180
181   @staticmethod
182   def GlobalSetUp():
183     ChromeDriverTest._http_server = webserver.WebServer(
184         chrome_paths.GetTestData())
185     ChromeDriverTest._sync_server = webserver.SyncWebServer()
186     if _ANDROID_PACKAGE_KEY:
187       ChromeDriverTest._device = device_utils.DeviceUtils(
188           android_commands.GetAttachedDevices()[0])
189       http_host_port = ChromeDriverTest._http_server._server.server_port
190       sync_host_port = ChromeDriverTest._sync_server._server.server_port
191       forwarder.Forwarder.Map(
192           [(http_host_port, http_host_port), (sync_host_port, sync_host_port)],
193           ChromeDriverTest._device)
194
195   @staticmethod
196   def GlobalTearDown():
197     if _ANDROID_PACKAGE_KEY:
198       forwarder.Forwarder.UnmapAllDevicePorts(ChromeDriverTest._device)
199     ChromeDriverTest._http_server.Shutdown()
200
201   @staticmethod
202   def GetHttpUrlForFile(file_path):
203     return ChromeDriverTest._http_server.GetUrl() + file_path
204
205   def setUp(self):
206     self._driver = self.CreateDriver()
207
208   def testStartStop(self):
209     pass
210
211   def testLoadUrl(self):
212     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
213
214   def testGetCurrentWindowHandle(self):
215     self._driver.GetCurrentWindowHandle()
216
217   def _WaitForNewWindow(self, old_handles):
218     """Wait for at least one new window to show up in 20 seconds.
219
220     Args:
221       old_handles: Handles to all old windows before the new window is added.
222
223     Returns:
224       Handle to a new window. None if timeout.
225     """
226     timeout = time.time() + 20
227     while time.time() < timeout:
228       new_handles = self._driver.GetWindowHandles()
229       if len(new_handles) > len(old_handles):
230         for index, old_handle in enumerate(old_handles):
231           self.assertEquals(old_handle, new_handles[index])
232         return new_handles[len(old_handles)]
233       time.sleep(0.01)
234     return None
235
236   def testCloseWindow(self):
237     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
238     old_handles = self._driver.GetWindowHandles()
239     self._driver.FindElement('id', 'link').Click()
240     new_window_handle = self._WaitForNewWindow(old_handles)
241     self.assertNotEqual(None, new_window_handle)
242     self._driver.SwitchToWindow(new_window_handle)
243     self.assertEquals(new_window_handle, self._driver.GetCurrentWindowHandle())
244     self.assertRaises(chromedriver.NoSuchElement,
245                       self._driver.FindElement, 'id', 'link')
246     self._driver.CloseWindow()
247     self.assertRaises(chromedriver.NoSuchWindow,
248                       self._driver.GetCurrentWindowHandle)
249     new_handles = self._driver.GetWindowHandles()
250     for old_handle in old_handles:
251       self.assertTrue(old_handle in new_handles)
252     for handle in new_handles:
253       self._driver.SwitchToWindow(handle)
254       self.assertEquals(handle, self._driver.GetCurrentWindowHandle())
255       self._driver.CloseWindow()
256
257   def testGetWindowHandles(self):
258     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
259     old_handles = self._driver.GetWindowHandles()
260     self._driver.FindElement('id', 'link').Click()
261     self.assertNotEqual(None, self._WaitForNewWindow(old_handles))
262
263   def testSwitchToWindow(self):
264     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
265     self.assertEquals(
266         1, self._driver.ExecuteScript('window.name = "oldWindow"; return 1;'))
267     window1_handle = self._driver.GetCurrentWindowHandle()
268     old_handles = self._driver.GetWindowHandles()
269     self._driver.FindElement('id', 'link').Click()
270     new_window_handle = self._WaitForNewWindow(old_handles)
271     self.assertNotEqual(None, new_window_handle)
272     self._driver.SwitchToWindow(new_window_handle)
273     self.assertEquals(new_window_handle, self._driver.GetCurrentWindowHandle())
274     self.assertRaises(chromedriver.NoSuchElement,
275                       self._driver.FindElement, 'id', 'link')
276     self._driver.SwitchToWindow('oldWindow')
277     self.assertEquals(window1_handle, self._driver.GetCurrentWindowHandle())
278
279   def testEvaluateScript(self):
280     self.assertEquals(1, self._driver.ExecuteScript('return 1'))
281     self.assertEquals(None, self._driver.ExecuteScript(''))
282
283   def testEvaluateScriptWithArgs(self):
284     script = ('document.body.innerHTML = "<div>b</div><div>c</div>";'
285               'return {stuff: document.querySelectorAll("div")};')
286     stuff = self._driver.ExecuteScript(script)['stuff']
287     script = 'return arguments[0].innerHTML + arguments[1].innerHTML'
288     self.assertEquals(
289         'bc', self._driver.ExecuteScript(script, stuff[0], stuff[1]))
290
291   def testEvaluateInvalidScript(self):
292     self.assertRaises(chromedriver.ChromeDriverException,
293                       self._driver.ExecuteScript, '{{{')
294
295   def testExecuteAsyncScript(self):
296     self._driver.SetTimeout('script', 3000)
297     self.assertRaises(
298         chromedriver.ScriptTimeout,
299         self._driver.ExecuteAsyncScript,
300         'var callback = arguments[0];'
301         'setTimeout(function(){callback(1);}, 10000);')
302     self.assertEquals(
303         2,
304         self._driver.ExecuteAsyncScript(
305             'var callback = arguments[0];'
306             'setTimeout(function(){callback(2);}, 300);'))
307
308   def testSwitchToFrame(self):
309     self._driver.ExecuteScript(
310         'var frame = document.createElement("iframe");'
311         'frame.id="id";'
312         'frame.name="name";'
313         'document.body.appendChild(frame);')
314     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
315     self._driver.SwitchToFrame('id')
316     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
317     self._driver.SwitchToMainFrame()
318     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
319     self._driver.SwitchToFrame('name')
320     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
321     self._driver.SwitchToMainFrame()
322     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
323     self._driver.SwitchToFrameByIndex(0)
324     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
325     self._driver.SwitchToMainFrame()
326     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
327     self._driver.SwitchToFrame(self._driver.FindElement('tag name', 'iframe'))
328     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
329
330   def testSwitchToParentFrame(self):
331     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/nested.html'))
332     self.assertTrue('One' in self._driver.GetPageSource())
333     self._driver.SwitchToFrameByIndex(0)
334     self.assertTrue('Two' in self._driver.GetPageSource())
335     self._driver.SwitchToFrameByIndex(0)
336     self.assertTrue('Three' in self._driver.GetPageSource())
337     self._driver.SwitchToParentFrame()
338     self.assertTrue('Two' in self._driver.GetPageSource())
339     self._driver.SwitchToParentFrame()
340     self.assertTrue('One' in self._driver.GetPageSource())
341
342   def testExecuteInRemovedFrame(self):
343     self._driver.ExecuteScript(
344         'var frame = document.createElement("iframe");'
345         'frame.id="id";'
346         'frame.name="name";'
347         'document.body.appendChild(frame);'
348         'window.addEventListener("message",'
349         '    function(event) { document.body.removeChild(frame); });')
350     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
351     self._driver.SwitchToFrame('id')
352     self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
353     self._driver.ExecuteScript('parent.postMessage("remove", "*");')
354     self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
355
356   def testGetTitle(self):
357     script = 'document.title = "title"; return 1;'
358     self.assertEquals(1, self._driver.ExecuteScript(script))
359     self.assertEquals('title', self._driver.GetTitle())
360
361   def testGetPageSource(self):
362     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
363     self.assertTrue('Link to empty.html' in self._driver.GetPageSource())
364
365   def testFindElement(self):
366     self._driver.ExecuteScript(
367         'document.body.innerHTML = "<div>a</div><div>b</div>";')
368     self.assertTrue(
369         isinstance(self._driver.FindElement('tag name', 'div'), WebElement))
370
371   def testFindElements(self):
372     self._driver.ExecuteScript(
373         'document.body.innerHTML = "<div>a</div><div>b</div>";')
374     divs = self._driver.FindElements('tag name', 'div')
375     self.assertTrue(isinstance(divs, list))
376     self.assertEquals(2, len(divs))
377     for div in divs:
378       self.assertTrue(isinstance(div, WebElement))
379
380   def testFindChildElement(self):
381     self._driver.ExecuteScript(
382         'document.body.innerHTML = "<div><br><br></div><div><a></a></div>";')
383     element = self._driver.FindElement('tag name', 'div')
384     self.assertTrue(
385         isinstance(element.FindElement('tag name', 'br'), WebElement))
386
387   def testFindChildElements(self):
388     self._driver.ExecuteScript(
389         'document.body.innerHTML = "<div><br><br></div><div><br></div>";')
390     element = self._driver.FindElement('tag name', 'div')
391     brs = element.FindElements('tag name', 'br')
392     self.assertTrue(isinstance(brs, list))
393     self.assertEquals(2, len(brs))
394     for br in brs:
395       self.assertTrue(isinstance(br, WebElement))
396
397   def testHoverOverElement(self):
398     div = self._driver.ExecuteScript(
399         'document.body.innerHTML = "<div>old</div>";'
400         'var div = document.getElementsByTagName("div")[0];'
401         'div.addEventListener("mouseover", function() {'
402         '  document.body.appendChild(document.createElement("br"));'
403         '});'
404         'return div;')
405     div.HoverOver()
406     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
407
408   def testClickElement(self):
409     div = self._driver.ExecuteScript(
410         'document.body.innerHTML = "<div>old</div>";'
411         'var div = document.getElementsByTagName("div")[0];'
412         'div.addEventListener("click", function() {'
413         '  div.innerHTML="new<br>";'
414         '});'
415         'return div;')
416     div.Click()
417     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
418
419   def testSingleTapElement(self):
420     div = self._driver.ExecuteScript(
421         'document.body.innerHTML = "<div>old</div>";'
422         'var div = document.getElementsByTagName("div")[0];'
423         'div.addEventListener("touchend", function() {'
424         '  div.innerHTML="new<br>";'
425         '});'
426         'return div;')
427     div.SingleTap()
428     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
429
430   def testTouchDownUpElement(self):
431     div = self._driver.ExecuteScript(
432         'document.body.innerHTML = "<div>old</div>";'
433         'var div = document.getElementsByTagName("div")[0];'
434         'div.addEventListener("touchend", function() {'
435         '  div.innerHTML="new<br>";'
436         '});'
437         'return div;')
438     loc = div.GetLocation()
439     self._driver.TouchDown(loc['x'], loc['y'])
440     self._driver.TouchUp(loc['x'], loc['y'])
441     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
442
443   def testTouchFlickElement(self):
444     dx = 3
445     dy = 4
446     speed = 5
447     flickTouchEventsPerSecond = 30
448     moveEvents = int(
449         math.sqrt(dx * dx + dy * dy) * flickTouchEventsPerSecond / speed)
450     div = self._driver.ExecuteScript(
451         'document.body.innerHTML = "<div>old</div>";'
452         'var div = document.getElementsByTagName("div")[0];'
453         'div.addEventListener("touchstart", function() {'
454         '  div.innerHTML = "preMove0";'
455         '});'
456         'div.addEventListener("touchmove", function() {'
457         '  res = div.innerHTML.match(/preMove(\d+)/);'
458         '  if (res != null) {'
459         '    div.innerHTML = "preMove" + (parseInt(res[1], 10) + 1);'
460         '  }'
461         '});'
462         'div.addEventListener("touchend", function() {'
463         '  if (div.innerHTML == "preMove' + str(moveEvents) + '") {'
464         '    div.innerHTML = "new<br>";'
465         '  }'
466         '});'
467         'return div;')
468     self._driver.TouchFlick(div, dx, dy, speed)
469     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
470
471   def testTouchMovedElement(self):
472     div = self._driver.ExecuteScript(
473         'document.body.innerHTML = "<div>old</div>";'
474         'var div = document.getElementsByTagName("div")[0];'
475         'div.addEventListener("touchmove", function() {'
476         '  div.innerHTML="new<br>";'
477         '});'
478         'return div;')
479     loc = div.GetLocation()
480     self._driver.TouchDown(loc['x'], loc['y'])
481     self._driver.TouchMove(loc['x'] + 1, loc['y'] + 1)
482     self._driver.TouchUp(loc['x'] + 1, loc['y'] + 1)
483     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
484
485   def testClickElementInSubFrame(self):
486     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/frame_test.html'))
487     frame = self._driver.FindElement('tag name', 'iframe')
488     self._driver.SwitchToFrame(frame)
489     # Test clicking element in the sub frame.
490     self.testClickElement()
491
492   def testClearElement(self):
493     text = self._driver.ExecuteScript(
494         'document.body.innerHTML = \'<input type="text" value="abc">\';'
495         'var input = document.getElementsByTagName("input")[0];'
496         'input.addEventListener("change", function() {'
497         '  document.body.appendChild(document.createElement("br"));'
498         '});'
499         'return input;')
500     text.Clear()
501     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
502
503   def testSendKeysToElement(self):
504     text = self._driver.ExecuteScript(
505         'document.body.innerHTML = \'<input type="text">\';'
506         'var input = document.getElementsByTagName("input")[0];'
507         'input.addEventListener("change", function() {'
508         '  document.body.appendChild(document.createElement("br"));'
509         '});'
510         'return input;')
511     text.SendKeys('0123456789+-*/ Hi')
512     text.SendKeys(', there!')
513     value = self._driver.ExecuteScript('return arguments[0].value;', text)
514     self.assertEquals('0123456789+-*/ Hi, there!', value)
515
516   def testGetCurrentUrl(self):
517     self.assertEquals('data:,', self._driver.GetCurrentUrl())
518
519   def testGoBackAndGoForward(self):
520     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
521     self._driver.GoBack()
522     self._driver.GoForward()
523
524   def testRefresh(self):
525     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
526     self._driver.Refresh()
527
528   def testMouseMoveTo(self):
529     div = self._driver.ExecuteScript(
530         'document.body.innerHTML = "<div>old</div>";'
531         'var div = document.getElementsByTagName("div")[0];'
532         'div.style["width"] = "100px";'
533         'div.style["height"] = "100px";'
534         'div.addEventListener("mouseover", function() {'
535         '  var div = document.getElementsByTagName("div")[0];'
536         '  div.innerHTML="new<br>";'
537         '});'
538         'return div;')
539     self._driver.MouseMoveTo(div, 10, 10)
540     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
541
542   def testMouseClick(self):
543     div = self._driver.ExecuteScript(
544         'document.body.innerHTML = "<div>old</div>";'
545         'var div = document.getElementsByTagName("div")[0];'
546         'div.style["width"] = "100px";'
547         'div.style["height"] = "100px";'
548         'div.addEventListener("click", function() {'
549         '  var div = document.getElementsByTagName("div")[0];'
550         '  div.innerHTML="new<br>";'
551         '});'
552         'return div;')
553     self._driver.MouseMoveTo(div)
554     self._driver.MouseClick()
555     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
556
557   def testMouseButtonDownAndUp(self):
558     self._driver.ExecuteScript(
559         'document.body.innerHTML = "<div>old</div>";'
560         'var div = document.getElementsByTagName("div")[0];'
561         'div.style["width"] = "100px";'
562         'div.style["height"] = "100px";'
563         'div.addEventListener("mousedown", function() {'
564         '  var div = document.getElementsByTagName("div")[0];'
565         '  div.innerHTML="new1<br>";'
566         '});'
567         'div.addEventListener("mouseup", function() {'
568         '  var div = document.getElementsByTagName("div")[0];'
569         '  div.innerHTML="new2<a></a>";'
570         '});')
571     self._driver.MouseMoveTo(None, 50, 50)
572     self._driver.MouseButtonDown()
573     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
574     self._driver.MouseButtonUp()
575     self.assertEquals(1, len(self._driver.FindElements('tag name', 'a')))
576
577   def testMouseDoubleClick(self):
578     div = self._driver.ExecuteScript(
579         'document.body.innerHTML = "<div>old</div>";'
580         'var div = document.getElementsByTagName("div")[0];'
581         'div.style["width"] = "100px";'
582         'div.style["height"] = "100px";'
583         'div.addEventListener("dblclick", function() {'
584         '  var div = document.getElementsByTagName("div")[0];'
585         '  div.innerHTML="new<br>";'
586         '});'
587         'return div;')
588     self._driver.MouseMoveTo(div, 1, 1)
589     self._driver.MouseDoubleClick()
590     self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
591
592   def testAlert(self):
593     self.assertFalse(self._driver.IsAlertOpen())
594     self._driver.ExecuteScript(
595         'window.setTimeout('
596         '    function() { window.confirmed = confirm(\'HI\'); },'
597         '    0);')
598     self.assertTrue(self._driver.IsAlertOpen())
599     self.assertEquals('HI', self._driver.GetAlertMessage())
600     self._driver.HandleAlert(False)
601     self.assertFalse(self._driver.IsAlertOpen())
602     self.assertEquals(False,
603                       self._driver.ExecuteScript('return window.confirmed'))
604
605   def testShouldHandleNewWindowLoadingProperly(self):
606     """Tests that ChromeDriver determines loading correctly for new windows."""
607     self._http_server.SetDataForPath(
608         '/newwindow',
609         """
610         <html>
611         <body>
612         <a href='%s' target='_blank'>new window/tab</a>
613         </body>
614         </html>""" % self._sync_server.GetUrl())
615     self._driver.Load(self._http_server.GetUrl() + '/newwindow')
616     old_windows = self._driver.GetWindowHandles()
617     self._driver.FindElement('tagName', 'a').Click()
618     new_window = self._WaitForNewWindow(old_windows)
619     self.assertNotEqual(None, new_window)
620
621     self.assertFalse(self._driver.IsLoading())
622     self._driver.SwitchToWindow(new_window)
623     self.assertTrue(self._driver.IsLoading())
624     self._sync_server.RespondWithContent('<html>new window</html>')
625     self._driver.ExecuteScript('return 1')  # Shouldn't hang.
626
627   def testPopups(self):
628     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
629     old_handles = self._driver.GetWindowHandles()
630     self._driver.ExecuteScript('window.open("about:blank")')
631     new_window_handle = self._WaitForNewWindow(old_handles)
632     self.assertNotEqual(None, new_window_handle)
633
634   def testNoSuchFrame(self):
635     self.assertRaises(chromedriver.NoSuchFrame,
636                       self._driver.SwitchToFrame, 'nosuchframe')
637     self.assertRaises(chromedriver.NoSuchFrame,
638                       self._driver.SwitchToFrame,
639                       self._driver.FindElement('tagName', 'body'))
640
641   def testWindowPosition(self):
642     position = self._driver.GetWindowPosition()
643     self._driver.SetWindowPosition(position[0], position[1])
644     self.assertEquals(position, self._driver.GetWindowPosition())
645
646     # Resize so the window isn't moved offscreen.
647     # See https://code.google.com/p/chromedriver/issues/detail?id=297.
648     self._driver.SetWindowSize(300, 300)
649
650     self._driver.SetWindowPosition(100, 200)
651     self.assertEquals([100, 200], self._driver.GetWindowPosition())
652
653   def testWindowSize(self):
654     size = self._driver.GetWindowSize()
655     self._driver.SetWindowSize(size[0], size[1])
656     self.assertEquals(size, self._driver.GetWindowSize())
657
658     self._driver.SetWindowSize(600, 400)
659     self.assertEquals([600, 400], self._driver.GetWindowSize())
660
661   def testWindowMaximize(self):
662     self._driver.SetWindowPosition(100, 200)
663     self._driver.SetWindowSize(600, 400)
664     self._driver.MaximizeWindow()
665
666     self.assertNotEqual([100, 200], self._driver.GetWindowPosition())
667     self.assertNotEqual([600, 400], self._driver.GetWindowSize())
668     # Set size first so that the window isn't moved offscreen.
669     # See https://code.google.com/p/chromedriver/issues/detail?id=297.
670     self._driver.SetWindowSize(600, 400)
671     self._driver.SetWindowPosition(100, 200)
672     self.assertEquals([100, 200], self._driver.GetWindowPosition())
673     self.assertEquals([600, 400], self._driver.GetWindowSize())
674
675   def testConsoleLogSources(self):
676     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/console_log.html'))
677     logs = self._driver.GetLog('browser')
678     self.assertEquals(len(logs), 2)
679     self.assertEquals(logs[0]['source'], 'network')
680     self.assertEquals(logs[1]['source'], 'javascript')
681
682   def testAutoReporting(self):
683     self.assertFalse(self._driver.IsAutoReporting())
684     self._driver.SetAutoReporting(True)
685     self.assertTrue(self._driver.IsAutoReporting())
686     url = self.GetHttpUrlForFile('/chromedriver/console_log.html')
687     self.assertRaisesRegexp(chromedriver.UnknownError,
688                             '.*(404|Failed to load resource).*',
689                             self._driver.Load,
690                             url)
691
692   def testContextMenuEventFired(self):
693     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/context_menu.html'))
694     self._driver.MouseMoveTo(self._driver.FindElement('tagName', 'div'))
695     self._driver.MouseClick(2)
696     self.assertTrue(self._driver.ExecuteScript('return success'))
697
698   def testHasFocusOnStartup(self):
699     # Some pages (about:blank) cause Chrome to put the focus in URL bar.
700     # This breaks tests depending on focus.
701     self.assertTrue(self._driver.ExecuteScript('return document.hasFocus()'))
702
703   def testTabCrash(self):
704     # If a tab is crashed, the session will be deleted.
705     # When 31 is released, will reload the tab instead.
706     # https://code.google.com/p/chromedriver/issues/detail?id=547
707     self.assertRaises(chromedriver.UnknownError,
708                       self._driver.Load, 'chrome://crash')
709     self.assertRaises(chromedriver.NoSuchSession,
710                       self._driver.GetCurrentUrl)
711
712   def testDoesntHangOnDebugger(self):
713     self._driver.ExecuteScript('debugger;')
714
715   def testMobileEmulationDisabledByDefault(self):
716     self.assertFalse(self._driver.capabilities['mobileEmulationEnabled'])
717
718   def testChromeDriverSendLargeData(self):
719     script = 's = ""; for (i = 0; i < 10e6; i++) s += "0"; return s;'
720     lots_of_data = self._driver.ExecuteScript(script)
721     self.assertEquals('0'.zfill(int(10e6)), lots_of_data)
722
723   def testChromeDriverRecieveAndSendLargeData(self):
724     lots_of_data = '1'.zfill(int(10e6))
725     result = self._driver.ExecuteScript('return "%s"' % lots_of_data)
726     self.assertEquals(lots_of_data, result)
727
728
729 class ChromeDriverAndroidTest(ChromeDriverBaseTest):
730   """End to end tests for Android-specific tests."""
731
732   def testLatestAndroidAppInstalled(self):
733     if ('stable' not in _ANDROID_PACKAGE_KEY and
734         'beta' not in _ANDROID_PACKAGE_KEY):
735       return
736
737     self._driver = self.CreateDriver()
738
739     try:
740       omaha_list = json.loads(
741           urllib2.urlopen('http://omahaproxy.appspot.com/all.json').read())
742       for l in omaha_list:
743         if l['os'] != 'android':
744           continue
745         for v in l['versions']:
746           if (('stable' in v['channel'] and 'stable' in _ANDROID_PACKAGE_KEY) or
747               ('beta' in v['channel'] and 'beta' in _ANDROID_PACKAGE_KEY)):
748             omaha = map(int, v['version'].split('.'))
749             device = map(int, self._driver.capabilities['version'].split('.'))
750             self.assertTrue(omaha <= device)
751             return
752       raise RuntimeError('Malformed omaha JSON')
753     except urllib2.URLError as e:
754       print 'Unable to fetch current version info from omahaproxy (%s)' % e
755
756   def testDeviceManagement(self):
757     self._drivers = [self.CreateDriver() for x in
758                      android_commands.GetAttachedDevices()]
759     self.assertRaises(chromedriver.UnknownError, self.CreateDriver)
760     self._drivers[0].Quit()
761     self._drivers[0] = self.CreateDriver()
762
763
764 class ChromeSwitchesCapabilityTest(ChromeDriverBaseTest):
765   """Tests that chromedriver properly processes chromeOptions.args capabilities.
766
767   Makes sure the switches are passed to Chrome.
768   """
769
770   def testSwitchWithoutArgument(self):
771     """Tests that switch --dom-automation can be passed to Chrome.
772
773     Unless --dom-automation is specified, window.domAutomationController
774     is undefined.
775     """
776     driver = self.CreateDriver(chrome_switches=['dom-automation'])
777     self.assertNotEqual(
778         None,
779         driver.ExecuteScript('return window.domAutomationController'))
780
781
782 class ChromeExtensionsCapabilityTest(ChromeDriverBaseTest):
783   """Tests that chromedriver properly processes chromeOptions.extensions."""
784
785   def _PackExtension(self, ext_path):
786     return base64.b64encode(open(ext_path, 'rb').read())
787
788   def testExtensionsInstall(self):
789     """Checks that chromedriver can take the extensions in crx format."""
790     crx_1 = os.path.join(_TEST_DATA_DIR, 'ext_test_1.crx')
791     crx_2 = os.path.join(_TEST_DATA_DIR, 'ext_test_2.crx')
792     self.CreateDriver(chrome_extensions=[self._PackExtension(crx_1),
793                                          self._PackExtension(crx_2)])
794
795   def testExtensionsInstallZip(self):
796     """Checks that chromedriver can take the extensions in zip format."""
797     zip_1 = os.path.join(_TEST_DATA_DIR, 'ext_test_1.zip')
798     self.CreateDriver(chrome_extensions=[self._PackExtension(zip_1)])
799
800   def testWaitsForExtensionToLoad(self):
801     did_load_event = threading.Event()
802     server = webserver.SyncWebServer()
803     def RunServer():
804       time.sleep(5)
805       server.RespondWithContent('<html>iframe</html>')
806       did_load_event.set()
807
808     thread = threading.Thread(target=RunServer)
809     thread.daemon = True
810     thread.start()
811     crx = os.path.join(_TEST_DATA_DIR, 'ext_slow_loader.crx')
812     driver = self.CreateDriver(
813         chrome_switches=['user-agent=' + server.GetUrl()],
814         chrome_extensions=[self._PackExtension(crx)])
815     self.assertTrue(did_load_event.is_set())
816
817
818 class ChromeLogPathCapabilityTest(ChromeDriverBaseTest):
819   """Tests that chromedriver properly processes chromeOptions.logPath."""
820
821   LOG_MESSAGE = 'Welcome to ChromeLogPathCapabilityTest!'
822
823   def testChromeLogPath(self):
824     """Checks that user can specify the path of the chrome log.
825
826     Verifies that a log message is written into the specified log file.
827     """
828     tmp_log_path = tempfile.NamedTemporaryFile()
829     driver = self.CreateDriver(chrome_log_path=tmp_log_path.name)
830     driver.ExecuteScript('console.info("%s")' % self.LOG_MESSAGE)
831     driver.Quit()
832     self.assertTrue(self.LOG_MESSAGE in open(tmp_log_path.name).read())
833
834
835 class MobileEmulationCapabilityTest(ChromeDriverBaseTest):
836   """Tests that ChromeDriver processes chromeOptions.mobileEmulation.
837
838   Makes sure the device metrics are overridden in DevTools and user agent is
839   overridden in Chrome.
840   """
841
842   @staticmethod
843   def GlobalSetUp():
844     def respondWithUserAgentString(request):
845       return request.GetHeader('User-Agent')
846
847     MobileEmulationCapabilityTest._http_server = webserver.WebServer(
848         chrome_paths.GetTestData())
849     MobileEmulationCapabilityTest._http_server.SetCallbackForPath(
850         '/userAgent', respondWithUserAgentString)
851
852   @staticmethod
853   def GlobalTearDown():
854     MobileEmulationCapabilityTest._http_server.Shutdown()
855
856   def testDeviceMetrics(self):
857     driver = self.CreateDriver(
858         mobile_emulation = {
859             'deviceMetrics': {'width': 360, 'height': 640, 'pixelRatio': 3}})
860     self.assertTrue(driver.capabilities['mobileEmulationEnabled'])
861     self.assertEqual(360, driver.ExecuteScript('return window.innerWidth'))
862     self.assertEqual(640, driver.ExecuteScript('return window.innerHeight'))
863
864   def testUserAgent(self):
865     driver = self.CreateDriver(
866         mobile_emulation = {'userAgent': 'Agent Smith'})
867     driver.Load(self._http_server.GetUrl() + '/userAgent')
868     body_tag = driver.FindElement('tag name', 'body')
869     self.assertEqual("Agent Smith", body_tag.GetText())
870
871   def testDeviceName(self):
872     driver = self.CreateDriver(
873         mobile_emulation = {'deviceName': 'Google Nexus 5'})
874     driver.Load(self._http_server.GetUrl() + '/userAgent')
875     self.assertEqual(360, driver.ExecuteScript('return window.innerWidth'))
876     self.assertEqual(640, driver.ExecuteScript('return window.innerHeight'))
877     body_tag = driver.FindElement('tag name', 'body')
878     self.assertEqual(
879         'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleW'
880         'ebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/53'
881         '5.19',
882         body_tag.GetText())
883
884   def testSendKeysToElement(self):
885     driver = self.CreateDriver(
886         mobile_emulation = {'deviceName': 'Google Nexus 5'})
887     text = driver.ExecuteScript(
888         'document.body.innerHTML = \'<input type="text">\';'
889         'var input = document.getElementsByTagName("input")[0];'
890         'input.addEventListener("change", function() {'
891         '  document.body.appendChild(document.createElement("br"));'
892         '});'
893         'return input;')
894     text.SendKeys('0123456789+-*/ Hi')
895     text.SendKeys(', there!')
896     value = driver.ExecuteScript('return arguments[0].value;', text)
897     self.assertEquals('0123456789+-*/ Hi, there!', value)
898
899   def testHoverOverElement(self):
900     driver = self.CreateDriver(
901         mobile_emulation = {'deviceName': 'Google Nexus 5'})
902     div = driver.ExecuteScript(
903         'document.body.innerHTML = "<div>old</div>";'
904         'var div = document.getElementsByTagName("div")[0];'
905         'div.addEventListener("mouseover", function() {'
906         '  document.body.appendChild(document.createElement("br"));'
907         '});'
908         'return div;')
909     div.HoverOver()
910     self.assertEquals(1, len(driver.FindElements('tag name', 'br')))
911
912   def testClickElement(self):
913     driver = self.CreateDriver(
914         mobile_emulation = {'deviceName': 'Google Nexus 5'})
915     div = driver.ExecuteScript(
916         'document.body.innerHTML = "<div>old</div>";'
917         'var div = document.getElementsByTagName("div")[0];'
918         'div.addEventListener("click", function() {'
919         '  div.innerHTML="new<br>";'
920         '});'
921         'return div;')
922     div.Click()
923     self.assertEquals(1, len(driver.FindElements('tag name', 'br')))
924
925   def testSingleTapElement(self):
926     driver = self.CreateDriver(
927         mobile_emulation = {'deviceName': 'Google Nexus 5'})
928     div = driver.ExecuteScript(
929         'document.body.innerHTML = "<div>old</div>";'
930         'var div = document.getElementsByTagName("div")[0];'
931         'div.addEventListener("touchend", function() {'
932         '  div.innerHTML="new<br>";'
933         '});'
934         'return div;')
935     div.SingleTap()
936     self.assertEquals(1, len(driver.FindElements('tag name', 'br')))
937
938   def testTouchDownUpElement(self):
939     driver = self.CreateDriver(
940         mobile_emulation = {'deviceName': 'Google Nexus 5'})
941     div = driver.ExecuteScript(
942         'document.body.innerHTML = "<div>old</div>";'
943         'var div = document.getElementsByTagName("div")[0];'
944         'div.addEventListener("touchend", function() {'
945         '  div.innerHTML="new<br>";'
946         '});'
947         'return div;')
948     loc = div.GetLocation()
949     driver.TouchDown(loc['x'], loc['y'])
950     driver.TouchUp(loc['x'], loc['y'])
951     self.assertEquals(1, len(driver.FindElements('tag name', 'br')))
952
953
954 class ChromeDriverLogTest(unittest.TestCase):
955   """Tests that chromedriver produces the expected log file."""
956
957   UNEXPECTED_CHROMEOPTION_CAP = 'unexpected_chromeoption_capability'
958   LOG_MESSAGE = 'unrecognized chrome option: %s' % UNEXPECTED_CHROMEOPTION_CAP
959
960   def testChromeDriverLog(self):
961     _, tmp_log_path = tempfile.mkstemp(prefix='chromedriver_log_')
962     chromedriver_server = server.Server(
963         _CHROMEDRIVER_BINARY, log_path=tmp_log_path)
964     try:
965       driver = chromedriver.ChromeDriver(
966           chromedriver_server.GetUrl(), chrome_binary=_CHROME_BINARY,
967           experimental_options={ self.UNEXPECTED_CHROMEOPTION_CAP : 1 })
968       driver.Quit()
969     except chromedriver.ChromeDriverException, e:
970       self.assertTrue(self.LOG_MESSAGE in e.message)
971     finally:
972       chromedriver_server.Kill()
973     with open(tmp_log_path, 'r') as f:
974       self.assertTrue(self.LOG_MESSAGE in f.read())
975
976
977 class PerformanceLoggerTest(ChromeDriverBaseTest):
978   """Tests chromedriver tracing support and Inspector event collection."""
979
980   def testPerformanceLogger(self):
981     driver = self.CreateDriver(
982         experimental_options={'perfLoggingPrefs': {
983             'enableTimeline': True,
984             'traceCategories': 'webkit.console,blink.console'
985           }}, performance_log_level='ALL')
986     driver.Load(
987         ChromeDriverTest._http_server.GetUrl() + '/chromedriver/empty.html')
988     # Mark the timeline; later we will verify the marks appear in the trace.
989     driver.ExecuteScript('console.time("foobar")')
990     driver.ExecuteScript('console.timeEnd("foobar")')
991     logs = driver.GetLog('performance')
992     driver.Quit()
993
994     marked_timeline_events = []
995     seen_log_domains = {}
996     for entry in logs:
997       devtools_message = json.loads(entry['message'])['message']
998       method = devtools_message['method']
999       domain = method[:method.find('.')]
1000       seen_log_domains[domain] = True
1001       if method != 'Tracing.dataCollected':
1002         continue
1003       self.assertTrue('params' in devtools_message)
1004       self.assertTrue(isinstance(devtools_message['params'], dict))
1005       cat = devtools_message['params'].get('cat', '')
1006       # Depending on Chrome version, the events may occur for the webkit.console
1007       # or blink.console category. They will only occur for one of them.
1008       if (cat == 'blink.console' or cat == 'webkit.console'):
1009         self.assertTrue(devtools_message['params']['name'] == 'foobar')
1010         marked_timeline_events.append(devtools_message)
1011     self.assertEquals(2, len(marked_timeline_events))
1012     self.assertEquals({'Network', 'Page', 'Timeline', 'Tracing'},
1013                       set(seen_log_domains.keys()))
1014
1015
1016 class SessionHandlingTest(ChromeDriverBaseTest):
1017   """Tests for session operations."""
1018   def testQuitASessionMoreThanOnce(self):
1019     driver = self.CreateDriver()
1020     driver.Quit()
1021     driver.Quit()
1022
1023
1024 class RemoteBrowserTest(ChromeDriverBaseTest):
1025   """Tests for ChromeDriver remote browser capability."""
1026   def setUp(self):
1027     self.assertTrue(_CHROME_BINARY is not None,
1028                     'must supply a chrome binary arg')
1029
1030   def testConnectToRemoteBrowser(self):
1031     port = self.FindFreePort()
1032     temp_dir = util.MakeTempDir()
1033     process = subprocess.Popen([_CHROME_BINARY,
1034                                 '--remote-debugging-port=%d' % port,
1035                                 '--user-data-dir=%s' % temp_dir])
1036     if process is None:
1037       raise RuntimeError('Chrome could not be started with debugging port')
1038     try:
1039       driver = self.CreateDriver(debugger_address='127.0.0.1:%d' % port)
1040       driver.ExecuteScript('console.info("%s")' % 'connecting at %d!' % port)
1041       driver.Quit()
1042     finally:
1043       process.terminate()
1044
1045   def FindFreePort(self):
1046     for port in range(10000, 10100):
1047       try:
1048         socket.create_connection(('127.0.0.1', port), 0.2).close()
1049       except socket.error:
1050         return port
1051     raise RuntimeError('Cannot find open port')
1052
1053 class PerfTest(ChromeDriverBaseTest):
1054   """Tests for ChromeDriver perf."""
1055   def setUp(self):
1056     self.assertTrue(_REFERENCE_CHROMEDRIVER is not None,
1057                     'must supply a reference-chromedriver arg')
1058
1059   def _RunDriverPerfTest(self, name, test_func):
1060     """Runs a perf test comparing a reference and new ChromeDriver server.
1061
1062     Args:
1063       name: The name of the perf test.
1064       test_func: Called with the server url to perform the test action. Must
1065                  return the time elapsed.
1066     """
1067     class Results(object):
1068       ref = []
1069       new = []
1070
1071     ref_server = server.Server(_REFERENCE_CHROMEDRIVER)
1072     results = Results()
1073     result_url_pairs = zip([results.new, results.ref],
1074                            [_CHROMEDRIVER_SERVER_URL, ref_server.GetUrl()])
1075     for iteration in range(30):
1076       for result, url in result_url_pairs:
1077         result += [test_func(url)]
1078       # Reverse the order for the next run.
1079       result_url_pairs = result_url_pairs[::-1]
1080
1081     def PrintResult(build, result):
1082       mean = sum(result) / len(result)
1083       avg_dev = sum([abs(sample - mean) for sample in result]) / len(result)
1084       print 'perf result', build, name, mean, avg_dev, result
1085       util.AddBuildStepText('%s %s: %.3f+-%.3f' % (
1086           build, name, mean, avg_dev))
1087
1088     # Discard first result, which may be off due to cold start.
1089     PrintResult('new', results.new[1:])
1090     PrintResult('ref', results.ref[1:])
1091
1092   def testSessionStartTime(self):
1093     def Run(url):
1094       start = time.time()
1095       driver = self.CreateDriver(url)
1096       end = time.time()
1097       driver.Quit()
1098       return end - start
1099     self._RunDriverPerfTest('session start', Run)
1100
1101   def testSessionStopTime(self):
1102     def Run(url):
1103       driver = self.CreateDriver(url)
1104       start = time.time()
1105       driver.Quit()
1106       end = time.time()
1107       return end - start
1108     self._RunDriverPerfTest('session stop', Run)
1109
1110   def testColdExecuteScript(self):
1111     def Run(url):
1112       driver = self.CreateDriver(url)
1113       start = time.time()
1114       driver.ExecuteScript('return 1')
1115       end = time.time()
1116       driver.Quit()
1117       return end - start
1118     self._RunDriverPerfTest('cold exe js', Run)
1119
1120 if __name__ == '__main__':
1121   parser = optparse.OptionParser()
1122   parser.add_option(
1123       '', '--chromedriver',
1124       help='Path to chromedriver server (REQUIRED!)')
1125   parser.add_option(
1126       '', '--log-path',
1127       help='Output verbose server logs to this file')
1128   parser.add_option(
1129       '', '--reference-chromedriver',
1130       help='Path to the reference chromedriver server')
1131   parser.add_option(
1132       '', '--chrome', help='Path to a build of the chrome binary')
1133   parser.add_option(
1134       '', '--chrome-version', default='HEAD',
1135       help='Version of chrome. Default is \'HEAD\'.')
1136   parser.add_option(
1137       '', '--filter', type='string', default='*',
1138       help=('Filter for specifying what tests to run, "*" will run all. E.g., '
1139             '*testStartStop'))
1140   parser.add_option(
1141       '', '--android-package',
1142       help=('Android package key. Possible values: ' +
1143             str(_ANDROID_NEGATIVE_FILTER.keys())))
1144   options, args = parser.parse_args()
1145
1146   options.chromedriver = util.GetAbsolutePathOfUserPath(options.chromedriver)
1147   if not options.chromedriver or not os.path.exists(options.chromedriver):
1148     parser.error('chromedriver is required or the given path is invalid.' +
1149                  'Please run "%s --help" for help' % __file__)
1150
1151   global _CHROMEDRIVER_BINARY
1152   _CHROMEDRIVER_BINARY = options.chromedriver
1153
1154   if (options.android_package and
1155       options.android_package not in _ANDROID_NEGATIVE_FILTER):
1156     parser.error('Invalid --android-package')
1157
1158   chromedriver_server = server.Server(_CHROMEDRIVER_BINARY, options.log_path)
1159   global _CHROMEDRIVER_SERVER_URL
1160   _CHROMEDRIVER_SERVER_URL = chromedriver_server.GetUrl()
1161
1162   global _REFERENCE_CHROMEDRIVER
1163   _REFERENCE_CHROMEDRIVER = util.GetAbsolutePathOfUserPath(
1164       options.reference_chromedriver)
1165
1166   global _CHROME_BINARY
1167   if options.chrome:
1168     _CHROME_BINARY = util.GetAbsolutePathOfUserPath(options.chrome)
1169   else:
1170     _CHROME_BINARY = None
1171
1172   global _ANDROID_PACKAGE_KEY
1173   _ANDROID_PACKAGE_KEY = options.android_package
1174
1175   if options.filter == '*':
1176     if _ANDROID_PACKAGE_KEY:
1177       negative_filter = _ANDROID_NEGATIVE_FILTER[_ANDROID_PACKAGE_KEY]
1178     else:
1179       negative_filter = _GetDesktopNegativeFilter(options.chrome_version)
1180     options.filter = '*-' + ':__main__.'.join([''] + negative_filter)
1181
1182   all_tests_suite = unittest.defaultTestLoader.loadTestsFromModule(
1183       sys.modules[__name__])
1184   tests = unittest_util.FilterTestSuite(all_tests_suite, options.filter)
1185   ChromeDriverTest.GlobalSetUp()
1186   MobileEmulationCapabilityTest.GlobalSetUp()
1187   result = unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(tests)
1188   ChromeDriverTest.GlobalTearDown()
1189   MobileEmulationCapabilityTest.GlobalTearDown()
1190   sys.exit(len(result.failures) + len(result.errors))