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"""Runs all ChromeDriver end to end tests."""
7
8import optparse
9import os
10import platform
11import shutil
12import sys
13import tempfile
14import traceback
15
16_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
17sys.path.insert(0, os.path.join(_THIS_DIR, os.pardir))
18
19import archive
20import chrome_paths
21import util
22
23sys.path.insert(0, os.path.join(chrome_paths.GetSrc(), 'build', 'android'))
24from pylib import constants
25
26
27def _GenerateTestCommand(script,
28                         chromedriver,
29                         ref_chromedriver=None,
30                         chrome=None,
31                         chrome_version=None,
32                         android_package=None,
33                         verbose=False):
34  _, log_path = tempfile.mkstemp(prefix='chromedriver_')
35  print 'chromedriver server log: %s' % log_path
36  cmd = [
37      sys.executable,
38      os.path.join(_THIS_DIR, script),
39      '--chromedriver=%s' % chromedriver,
40      '--log-path=%s' % log_path,
41  ]
42  if ref_chromedriver:
43    cmd.append('--reference-chromedriver=' + ref_chromedriver)
44
45  if chrome:
46    cmd.append('--chrome=' + chrome)
47
48  if chrome_version:
49    cmd.append('--chrome-version=' + chrome_version)
50
51  if verbose:
52    cmd.append('--verbose')
53
54  if android_package:
55    cmd = ['xvfb-run', '-a'] + cmd
56    cmd.append('--android-package=' + android_package)
57  return cmd
58
59
60def RunPythonTests(chromedriver, ref_chromedriver,
61                   chrome=None, chrome_version=None,
62                   chrome_version_name=None, android_package=None):
63  version_info = ''
64  if chrome_version_name:
65    version_info = '(%s)' % chrome_version_name
66  util.MarkBuildStepStart('python_tests%s' % version_info)
67  code = util.RunCommand(
68      _GenerateTestCommand('run_py_tests.py',
69                           chromedriver,
70                           ref_chromedriver=ref_chromedriver,
71                           chrome=chrome,
72                           chrome_version=chrome_version,
73                           android_package=android_package))
74  if code:
75    util.MarkBuildStepError()
76  return code
77
78
79def RunJavaTests(chromedriver, chrome=None, chrome_version=None,
80                 chrome_version_name=None, android_package=None,
81                 verbose=False):
82  version_info = ''
83  if chrome_version_name:
84    version_info = '(%s)' % chrome_version_name
85  util.MarkBuildStepStart('java_tests%s' % version_info)
86  code = util.RunCommand(
87      _GenerateTestCommand('run_java_tests.py',
88                           chromedriver,
89                           ref_chromedriver=None,
90                           chrome=chrome,
91                           chrome_version=chrome_version,
92                           android_package=android_package,
93                           verbose=verbose))
94  if code:
95    util.MarkBuildStepError()
96  return code
97
98
99def RunCppTests(cpp_tests):
100  util.MarkBuildStepStart('chromedriver_tests')
101  code = util.RunCommand([cpp_tests])
102  if code:
103    util.MarkBuildStepError()
104  return code
105
106
107def DownloadChrome(version_name, revision, download_site):
108  util.MarkBuildStepStart('download %s' % version_name)
109  try:
110    temp_dir = util.MakeTempDir()
111    return (temp_dir, archive.DownloadChrome(revision, temp_dir, download_site))
112  except Exception:
113    traceback.print_exc()
114    util.AddBuildStepText('Skip Java and Python tests')
115    util.MarkBuildStepError()
116    return (None, None)
117
118
119def _KillChromes():
120  chrome_map = {
121      'win': 'chrome.exe',
122      'mac': 'Chromium',
123      'linux': 'chrome',
124  }
125  if util.IsWindows():
126    cmd = ['taskkill', '/F', '/IM']
127  else:
128    cmd = ['killall', '-9']
129  cmd.append(chrome_map[util.GetPlatformName()])
130  util.RunCommand(cmd)
131
132
133def main():
134  parser = optparse.OptionParser()
135  parser.add_option(
136      '', '--android-packages',
137      help='Comma separated list of application package names, '
138           'if running tests on Android.')
139  # Option 'chrome-version' is for desktop only.
140  parser.add_option(
141      '', '--chrome-version',
142      help='Version of chrome, e.g., \'HEAD\', \'27\', or \'26\'.'
143           'Default is to run tests against all of these versions.'
144           'Notice: this option only applies to desktop.')
145  options, _ = parser.parse_args()
146
147  exe_postfix = ''
148  if util.IsWindows():
149    exe_postfix = '.exe'
150  cpp_tests_name = 'chromedriver_tests' + exe_postfix
151  server_name = 'chromedriver' + exe_postfix
152
153  required_build_outputs = [server_name]
154  if not options.android_packages:
155    required_build_outputs += [cpp_tests_name]
156  try:
157    build_dir = chrome_paths.GetBuildDir(required_build_outputs)
158  except RuntimeError:
159    util.MarkBuildStepStart('check required binaries')
160    traceback.print_exc()
161    util.MarkBuildStepError()
162  constants.SetBuildType(os.path.basename(build_dir))
163  print 'Using build outputs from', build_dir
164
165  chromedriver = os.path.join(build_dir, server_name)
166  platform_name = util.GetPlatformName()
167  if util.IsLinux() and platform.architecture()[0] == '64bit':
168    platform_name += '64'
169  ref_chromedriver = os.path.join(
170      chrome_paths.GetSrc(),
171      'chrome', 'test', 'chromedriver', 'third_party', 'java_tests',
172      'reference_builds',
173      'chromedriver_%s%s' % (platform_name, exe_postfix))
174
175  if options.android_packages:
176    os.environ['PATH'] += os.pathsep + os.path.join(
177        _THIS_DIR, os.pardir, 'chrome')
178    code = 0
179    for package in options.android_packages.split(','):
180      code1 = RunPythonTests(chromedriver,
181                             ref_chromedriver,
182                             chrome_version_name=package,
183                             android_package=package)
184      code2 = RunJavaTests(chromedriver,
185                           chrome_version_name=package,
186                           android_package=package,
187                           verbose=True)
188      code = code or code1 or code2
189    return code
190  else:
191    latest_snapshot_revision = archive.GetLatestSnapshotVersion()
192    versions = [
193        ['HEAD', latest_snapshot_revision],
194        ['37', archive.CHROME_37_REVISION],
195        ['36', archive.CHROME_36_REVISION],
196        ['35', archive.CHROME_35_REVISION]
197    ]
198    code = 0
199    for version in versions:
200      if options.chrome_version and version[0] != options.chrome_version:
201        continue
202      download_site = archive.Site.CONTINUOUS
203      version_name = version[0]
204      if version_name == 'HEAD':
205        version_name = version[1]
206        download_site = archive.GetSnapshotDownloadSite()
207      temp_dir, chrome_path = DownloadChrome(version_name, version[1],
208                                             download_site)
209      if not chrome_path:
210        code = 1
211        continue
212      code1 = RunPythonTests(chromedriver,
213                             ref_chromedriver,
214                             chrome=chrome_path,
215                             chrome_version=version[0],
216                             chrome_version_name='v%s' % version_name)
217      code2 = RunJavaTests(chromedriver, chrome=chrome_path,
218                           chrome_version=version[0],
219                           chrome_version_name='v%s' % version_name)
220      code = code or code1 or code2
221      _KillChromes()
222      shutil.rmtree(temp_dir)
223    cpp_tests = os.path.join(build_dir, cpp_tests_name)
224    return RunCppTests(cpp_tests) or code
225
226
227if __name__ == '__main__':
228  sys.exit(main())
229