1251881Speter#
2251881Speter#
3251881Speter# Licensed to the Apache Software Foundation (ASF) under one
4251881Speter# or more contributor license agreements.  See the NOTICE file
5251881Speter# distributed with this work for additional information
6251881Speter# regarding copyright ownership.  The ASF licenses this file
7251881Speter# to you under the Apache License, Version 2.0 (the
8251881Speter# "License"); you may not use this file except in compliance
9251881Speter# with the License.  You may obtain a copy of the License at
10251881Speter#
11251881Speter#   http://www.apache.org/licenses/LICENSE-2.0
12251881Speter#
13251881Speter# Unless required by applicable law or agreed to in writing,
14251881Speter# software distributed under the License is distributed on an
15251881Speter# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16251881Speter# KIND, either express or implied.  See the License for the
17251881Speter# specific language governing permissions and limitations
18251881Speter# under the License.
19251881Speter#
20251881Speter#
21251881Speter"""
22251881SpeterDriver for running the tests on Windows.
23251881Speter
24251881SpeterFor a list of options, run this script with the --help option.
25251881Speter"""
26251881Speter
27251881Speter# $HeadURL: http://svn.apache.org/repos/asf/subversion/branches/1.8.x/win-tests.py $
28253734Speter# $LastChangedRevision: 1492044 $
29251881Speter
30251881Speterimport os, sys, subprocess
31251881Speterimport filecmp
32251881Speterimport shutil
33251881Speterimport traceback
34251881Spetertry:
35251881Speter  # Python >=3.0
36251881Speter  import configparser
37251881Speterexcept ImportError:
38251881Speter  # Python <3.0
39251881Speter  import ConfigParser as configparser
40251881Speterimport string
41251881Speterimport random
42251881Speter
43251881Speterimport getopt
44251881Spetertry:
45251881Speter    my_getopt = getopt.gnu_getopt
46251881Speterexcept AttributeError:
47251881Speter    my_getopt = getopt.getopt
48251881Speter
49251881Speterdef _usage_exit():
50251881Speter  "print usage, exit the script"
51251881Speter
52251881Speter  print("Driver for running the tests on Windows.")
53251881Speter  print("Usage: python win-tests.py [option] [test-path]")
54251881Speter  print("")
55251881Speter  print("Valid options:")
56251881Speter  print("  -r, --release          : test the Release configuration")
57251881Speter  print("  -d, --debug            : test the Debug configuration (default)")
58251881Speter  print("  --bin=PATH             : use the svn binaries installed in PATH")
59251881Speter  print("  -u URL, --url=URL      : run ra_dav or ra_svn tests against URL;")
60251881Speter  print("                           will start svnserve for ra_svn tests")
61251881Speter  print("  -v, --verbose          : talk more")
62251881Speter  print("  -q, --quiet            : talk less")
63251881Speter  print("  -f, --fs-type=type     : filesystem type to use (fsfs is default)")
64251881Speter  print("  -c, --cleanup          : cleanup after running a test")
65251881Speter  print("  -t, --test=TEST        : Run the TEST test (all is default); use")
66251881Speter  print("                           TEST#n to run a particular test number,")
67251881Speter  print("                           multiples also accepted e.g. '2,4-7'")
68251881Speter  print("  --log-level=LEVEL      : Set log level to LEVEL (E.g. DEBUG)")
69251881Speter  print("  --log-to-stdout        : Write log results to stdout")
70251881Speter
71251881Speter  print("  --svnserve-args=list   : comma-separated list of arguments for")
72251881Speter  print("                           svnserve")
73251881Speter  print("                           default is '-d,-r,<test-path-root>'")
74251881Speter  print("  --asp.net-hack         : use '_svn' instead of '.svn' for the admin")
75251881Speter  print("                           dir name")
76251881Speter  print("  --httpd-dir            : location where Apache HTTPD is installed")
77251881Speter  print("  --httpd-port           : port for Apache HTTPD; random port number")
78251881Speter  print("                           will be used, if not specified")
79251881Speter  print("  --httpd-daemon         : Run Apache httpd as daemon")
80251881Speter  print("  --httpd-service        : Run Apache httpd as Windows service (default)")
81251881Speter  print("  --httpd-no-log         : Disable httpd logging")
82251881Speter  print("  --http-short-circuit   : Use SVNPathAuthz short_circuit on HTTP server")
83251881Speter  print("  --disable-http-v2      : Do not advertise support for HTTPv2 on server")
84251881Speter  print("  --disable-bulk-updates : Disable bulk updates on HTTP server")
85251881Speter  print("  --ssl-cert             : Path to SSL server certificate to trust.")
86251881Speter  print("  --javahl               : Run the javahl tests instead of the normal tests")
87251881Speter  print("  --list                 : print test doc strings only")
88251881Speter  print("  --milestone-filter=RE  : RE is a regular expression pattern that (when")
89251881Speter  print("                           used with --list) limits the tests listed to")
90251881Speter  print("                           those with an associated issue in the tracker")
91251881Speter  print("                           which has a target milestone that matches RE.")
92251881Speter  print("  --mode-filter=TYPE     : limit tests to expected TYPE = XFAIL, SKIP, PASS,")
93251881Speter  print("                           or 'ALL' (default)")
94251881Speter  print("  --enable-sasl          : enable Cyrus SASL authentication for")
95251881Speter  print("                           svnserve")
96251881Speter  print("  -p, --parallel         : run multiple tests in parallel")
97251881Speter  print("  --server-minor-version : the minor version of the server being")
98251881Speter  print("                           tested")
99251881Speter  print("  --config-file          : Configuration file for tests")
100251881Speter  print("  --fsfs-sharding        : Specify shard size (for fsfs)")
101251881Speter  print("  --fsfs-packing         : Run 'svnadmin pack' automatically")
102251881Speter
103251881Speter  sys.exit(0)
104251881Speter
105251881SpeterCMDLINE_TEST_SCRIPT_PATH = 'subversion/tests/cmdline/'
106251881SpeterCMDLINE_TEST_SCRIPT_NATIVE_PATH = CMDLINE_TEST_SCRIPT_PATH.replace('/', os.sep)
107251881Speter
108251881Spetersys.path.insert(0, os.path.join('build', 'generator'))
109251881Spetersys.path.insert(1, 'build')
110251881Speter
111251881Speterimport gen_win
112251881Speterversion_header = os.path.join('subversion', 'include', 'svn_version.h')
113251881Spetercp = configparser.ConfigParser()
114251881Spetercp.read('gen-make.opts')
115251881Spetergen_obj = gen_win.GeneratorBase('build.conf', version_header,
116251881Speter                                cp.items('options'))
117251881Speterall_tests = gen_obj.test_progs + gen_obj.bdb_test_progs \
118251881Speter          + gen_obj.scripts + gen_obj.bdb_scripts
119251881Speterclient_tests = [x for x in all_tests if x.startswith(CMDLINE_TEST_SCRIPT_PATH)]
120251881Speter
121251881Spetersvn_dlls = []
122251881Speterfor section in gen_obj.sections.values():
123251881Speter  if section.options.get("msvc-export"):
124251881Speter    dll_basename = section.name + "-" + str(gen_obj.version) + ".dll"
125251881Speter    svn_dlls.append(os.path.join("subversion", section.name, dll_basename))
126251881Speter
127251881Speteropts, args = my_getopt(sys.argv[1:], 'hrdvqct:pu:f:',
128251881Speter                       ['release', 'debug', 'verbose', 'quiet', 'cleanup',
129251881Speter                        'test=', 'url=', 'svnserve-args=', 'fs-type=', 'asp.net-hack',
130251881Speter                        'httpd-dir=', 'httpd-port=', 'httpd-daemon',
131251881Speter                        'httpd-server', 'http-short-circuit', 'httpd-no-log',
132251881Speter                        'disable-http-v2', 'disable-bulk-updates', 'help',
133251881Speter                        'fsfs-packing', 'fsfs-sharding=', 'javahl',
134251881Speter                        'list', 'enable-sasl', 'bin=', 'parallel',
135251881Speter                        'config-file=', 'server-minor-version=', 'log-level=',
136251881Speter                        'log-to-stdout', 'mode-filter=', 'milestone-filter=',
137251881Speter                        'ssl-cert='])
138251881Speterif len(args) > 1:
139251881Speter  print('Warning: non-option arguments after the first one will be ignored')
140251881Speter
141251881Speter# Interpret the options and set parameters
142251881Speterbase_url, fs_type, verbose, quiet, cleanup = None, None, None, None, None
143251881Speterrepo_loc = 'local repository.'
144251881Speterobjdir = 'Debug'
145251881Speterlog = 'tests.log'
146251881Speterfaillog = 'fails.log'
147251881Speterrun_svnserve = None
148251881Spetersvnserve_args = None
149251881Speterrun_httpd = None
150251881Speterhttpd_port = None
151251881Speterhttpd_service = None
152251881Speterhttpd_no_log = None
153251881Speterhttp_short_circuit = False
154251881Speteradvertise_httpv2 = True
155251881Speterhttp_bulk_updates = True
156251881Speterlist_tests = None
157251881Spetermilestone_filter = None
158251881Spetertest_javahl = None
159251881Speterenable_sasl = None
160251881Spetersvn_bin = None
161251881Speterparallel = None
162251881Speterfsfs_sharding = None
163251881Speterfsfs_packing = None
164251881Speterserver_minor_version = None
165251881Speterconfig_file = None
166251881Speterlog_to_stdout = None
167251881Spetermode_filter=None
168251881Spetertests_to_run = []
169251881Speterlog_level = None
170251881Speterssl_cert = None
171251881Speter
172251881Speterfor opt, val in opts:
173251881Speter  if opt in ('-h', '--help'):
174251881Speter    _usage_exit()
175251881Speter  elif opt in ('-u', '--url'):
176251881Speter    base_url = val
177251881Speter  elif opt in ('-f', '--fs-type'):
178251881Speter    fs_type = val
179251881Speter  elif opt in ('-v', '--verbose'):
180251881Speter    verbose = 1
181251881Speter  elif opt in ('-q', '--quiet'):
182251881Speter    quiet = 1
183251881Speter  elif opt in ('-c', '--cleanup'):
184251881Speter    cleanup = 1
185251881Speter  elif opt in ('-t', '--test'):
186251881Speter    tests_to_run.append(val)
187251881Speter  elif opt in ['-r', '--release']:
188251881Speter    objdir = 'Release'
189251881Speter  elif opt in ['-d', '--debug']:
190251881Speter    objdir = 'Debug'
191251881Speter  elif opt == '--svnserve-args':
192251881Speter    svnserve_args = val.split(',')
193251881Speter    run_svnserve = 1
194251881Speter  elif opt == '--asp.net-hack':
195251881Speter    os.environ['SVN_ASP_DOT_NET_HACK'] = opt
196251881Speter  elif opt == '--httpd-dir':
197251881Speter    abs_httpd_dir = os.path.abspath(val)
198251881Speter    run_httpd = 1
199251881Speter  elif opt == '--httpd-port':
200251881Speter    httpd_port = int(val)
201251881Speter  elif opt == '--httpd-daemon':
202251881Speter    httpd_service = 0
203251881Speter  elif opt == '--httpd-service':
204251881Speter    httpd_service = 1
205251881Speter  elif opt == '--httpd-no-log':
206251881Speter    httpd_no_log = 1
207251881Speter  elif opt == '--http-short-circuit':
208251881Speter    http_short_circuit = True
209251881Speter  elif opt == '--disable-http-v2':
210251881Speter    advertise_httpv2 = False
211251881Speter  elif opt == '--disable-bulk-updates':
212251881Speter    http_bulk_updates = False
213251881Speter  elif opt == '--fsfs-sharding':
214251881Speter    fsfs_sharding = int(val)
215251881Speter  elif opt == '--fsfs-packing':
216251881Speter    fsfs_packing = 1
217251881Speter  elif opt == '--javahl':
218251881Speter    test_javahl = 1
219251881Speter  elif opt == '--list':
220251881Speter    list_tests = 1
221251881Speter  elif opt == '--milestone-filter':
222251881Speter    milestone_filter = val
223251881Speter  elif opt == '--mode-filter':
224251881Speter    mode_filter = val
225251881Speter  elif opt == '--enable-sasl':
226251881Speter    enable_sasl = 1
227251881Speter    base_url = "svn://localhost/"
228251881Speter  elif opt == '--server-minor-version':
229251881Speter    server_minor_version = val
230251881Speter  elif opt == '--bin':
231251881Speter    svn_bin = val
232251881Speter  elif opt in ('-p', '--parallel'):
233251881Speter    parallel = 1
234251881Speter  elif opt in ('--config-file'):
235251881Speter    config_file = val
236251881Speter  elif opt == '--log-to-stdout':
237251881Speter    log_to_stdout = 1
238251881Speter  elif opt == '--log-level':
239251881Speter    log_level = val
240251881Speter  elif opt == '--ssl-cert':
241251881Speter    ssl_cert = val
242251881Speter
243251881Speter# Calculate the source and test directory names
244251881Speterabs_srcdir = os.path.abspath("")
245251881Speterabs_objdir = os.path.join(abs_srcdir, objdir)
246251881Speterif len(args) == 0:
247251881Speter  abs_builddir = abs_objdir
248251881Speter  create_dirs = 0
249251881Speterelse:
250251881Speter  abs_builddir = os.path.abspath(args[0])
251251881Speter  create_dirs = 1
252251881Speter
253251881Speter# Default to fsfs explicitly
254251881Speterif not fs_type:
255251881Speter  fs_type = 'fsfs'
256251881Speter
257251881Speter# Don't run bdb tests if they want to test fsfs
258251881Speterif fs_type == 'fsfs':
259251881Speter  all_tests = gen_obj.test_progs + gen_obj.scripts
260251881Speter
261251881Speterif run_httpd:
262251881Speter  if not httpd_port:
263251881Speter    httpd_port = random.randrange(1024, 30000)
264251881Speter  if not base_url:
265251881Speter    base_url = 'http://localhost:' + str(httpd_port)
266251881Speter
267251881Speterif base_url:
268251881Speter  repo_loc = 'remote repository ' + base_url + '.'
269251881Speter  if base_url[:4] == 'http':
270251881Speter    log = 'dav-tests.log'
271251881Speter    faillog = 'dav-fails.log'
272251881Speter  elif base_url[:3] == 'svn':
273251881Speter    log = 'svn-tests.log'
274251881Speter    faillog = 'svn-fails.log'
275251881Speter    run_svnserve = 1
276251881Speter  else:
277251881Speter    # Don't know this scheme, but who're we to judge whether it's
278251881Speter    # correct or not?
279251881Speter    log = 'url-tests.log'
280251881Speter    faillog = 'url-fails.log'
281251881Speter
282251881Speter# Have to move the executables where the tests expect them to be
283251881Spetercopied_execs = []   # Store copied exec files to avoid the final dir scan
284251881Speter
285251881Speterdef create_target_dir(dirname):
286251881Speter  tgt_dir = os.path.join(abs_builddir, dirname)
287251881Speter  if not os.path.exists(tgt_dir):
288251881Speter    if verbose:
289251881Speter      print("mkdir: %s" % tgt_dir)
290251881Speter    os.makedirs(tgt_dir)
291251881Speter
292251881Speterdef copy_changed_file(src, tgt):
293251881Speter  if not os.path.isfile(src):
294251881Speter    print('Could not find ' + src)
295251881Speter    sys.exit(1)
296251881Speter  if os.path.isdir(tgt):
297251881Speter    tgt = os.path.join(tgt, os.path.basename(src))
298251881Speter  if os.path.exists(tgt):
299251881Speter    assert os.path.isfile(tgt)
300251881Speter    if filecmp.cmp(src, tgt):
301251881Speter      if verbose:
302251881Speter        print("same: %s" % src)
303251881Speter        print(" and: %s" % tgt)
304251881Speter      return 0
305251881Speter  if verbose:
306251881Speter    print("copy: %s" % src)
307251881Speter    print("  to: %s" % tgt)
308251881Speter  shutil.copy(src, tgt)
309251881Speter  return 1
310251881Speter
311251881Speterdef copy_execs(baton, dirname, names):
312251881Speter  copied_execs = baton
313251881Speter  for name in names:
314251881Speter    if not name.endswith('.exe'):
315251881Speter      continue
316251881Speter    src = os.path.join(dirname, name)
317251881Speter    tgt = os.path.join(abs_builddir, dirname, name)
318251881Speter    create_target_dir(dirname)
319251881Speter    if copy_changed_file(src, tgt):
320251881Speter      copied_execs.append(tgt)
321251881Speter
322251881Speterdef locate_libs():
323251881Speter  "Move DLLs to a known location and set env vars"
324251881Speter
325251881Speter  dlls = []
326251881Speter
327251881Speter  # look for APR 1.x dll's and use those if found
328251881Speter  apr_test_path = os.path.join(gen_obj.apr_path, objdir, 'libapr-1.dll')
329251881Speter  if os.path.exists(apr_test_path):
330251881Speter    suffix = "-1"
331251881Speter  else:
332251881Speter    suffix = ""
333251881Speter
334251881Speter  if cp.has_option('options', '--with-static-apr'):
335251881Speter    dlls.append(os.path.join(gen_obj.apr_path, objdir,
336251881Speter                             'libapr%s.dll' % (suffix)))
337251881Speter    dlls.append(os.path.join(gen_obj.apr_util_path, objdir,
338251881Speter                             'libaprutil%s.dll' % (suffix)))
339251881Speter
340251881Speter  if gen_obj.libintl_path is not None:
341251881Speter    dlls.append(os.path.join(gen_obj.libintl_path, 'bin', 'intl3_svn.dll'))
342251881Speter
343251881Speter  if gen_obj.bdb_lib is not None:
344251881Speter    partial_path = os.path.join(gen_obj.bdb_path, 'bin', gen_obj.bdb_lib)
345251881Speter    if objdir == 'Debug':
346251881Speter      dlls.append(partial_path + 'd.dll')
347251881Speter    else:
348251881Speter      dlls.append(partial_path + '.dll')
349251881Speter
350251881Speter  if gen_obj.sasl_path is not None:
351251881Speter    dlls.append(os.path.join(gen_obj.sasl_path, 'lib', 'libsasl.dll'))
352251881Speter
353251881Speter  for dll in dlls:
354251881Speter    copy_changed_file(dll, abs_objdir)
355251881Speter
356251881Speter  # Copy the Subversion library DLLs
357251881Speter  if not cp.has_option('options', '--disable-shared'):
358251881Speter    for svn_dll in svn_dlls:
359251881Speter      copy_changed_file(os.path.join(abs_objdir, svn_dll), abs_objdir)
360251881Speter
361251881Speter  # Copy the Apache modules
362251881Speter  if run_httpd and cp.has_option('options', '--with-httpd'):
363251881Speter    mod_dav_svn_path = os.path.join(abs_objdir, 'subversion',
364251881Speter                                    'mod_dav_svn', 'mod_dav_svn.so')
365251881Speter    mod_authz_svn_path = os.path.join(abs_objdir, 'subversion',
366251881Speter                                      'mod_authz_svn', 'mod_authz_svn.so')
367251881Speter    mod_dontdothat_path = os.path.join(abs_objdir, 'tools', 'server-side',
368251881Speter                                        'mod_dontdothat', 'mod_dontdothat.so')
369251881Speter
370251881Speter    copy_changed_file(mod_dav_svn_path, abs_objdir)
371251881Speter    copy_changed_file(mod_authz_svn_path, abs_objdir)
372251881Speter    copy_changed_file(mod_dontdothat_path, abs_objdir)
373251881Speter
374251881Speter  os.environ['PATH'] = abs_objdir + os.pathsep + os.environ['PATH']
375251881Speter
376251881Speterdef fix_case(path):
377251881Speter    path = os.path.normpath(path)
378251881Speter    parts = path.split(os.path.sep)
379251881Speter    drive = parts[0].upper()
380251881Speter    parts = parts[1:]
381251881Speter    path = drive + os.path.sep
382251881Speter    for part in parts:
383251881Speter        dirs = os.listdir(path)
384251881Speter        for dir in dirs:
385251881Speter            if dir.lower() == part.lower():
386251881Speter                path = os.path.join(path, dir)
387251881Speter                break
388251881Speter    return path
389251881Speter
390251881Speterclass Svnserve:
391251881Speter  "Run svnserve for ra_svn tests"
392251881Speter  def __init__(self, svnserve_args, objdir, abs_objdir, abs_builddir):
393251881Speter    self.args = svnserve_args
394251881Speter    self.name = 'svnserve.exe'
395251881Speter    self.kind = objdir
396251881Speter    self.path = os.path.join(abs_objdir,
397251881Speter                             'subversion', 'svnserve', self.name)
398251881Speter    self.root = os.path.join(abs_builddir, CMDLINE_TEST_SCRIPT_NATIVE_PATH)
399251881Speter    self.proc_handle = None
400251881Speter
401251881Speter  def __del__(self):
402251881Speter    "Stop svnserve when the object is deleted"
403251881Speter    self.stop()
404251881Speter
405251881Speter  def _quote(self, arg):
406251881Speter    if ' ' in arg:
407251881Speter      return '"' + arg + '"'
408251881Speter    else:
409251881Speter      return arg
410251881Speter
411251881Speter  def start(self):
412251881Speter    if not self.args:
413251881Speter      args = [self.name, '-d', '-r', self.root]
414251881Speter    else:
415251881Speter      args = [self.name] + self.args
416251881Speter    print('Starting %s %s' % (self.kind, self.name))
417251881Speter    try:
418251881Speter      import win32process
419251881Speter      import win32con
420251881Speter      args = ' '.join([self._quote(x) for x in args])
421251881Speter      self.proc_handle = (
422251881Speter        win32process.CreateProcess(self._quote(self.path), args,
423251881Speter                                   None, None, 0,
424251881Speter                                   win32con.CREATE_NEW_CONSOLE,
425251881Speter                                   None, None, win32process.STARTUPINFO()))[0]
426251881Speter    except ImportError:
427251881Speter      os.spawnv(os.P_NOWAIT, self.path, args)
428251881Speter
429251881Speter  def stop(self):
430251881Speter    if self.proc_handle is not None:
431251881Speter      try:
432251881Speter        import win32process
433251881Speter        print('Stopping %s' % self.name)
434251881Speter        win32process.TerminateProcess(self.proc_handle, 0)
435251881Speter        return
436251881Speter      except ImportError:
437251881Speter        pass
438251881Speter    print('Svnserve.stop not implemented')
439251881Speter
440251881Speterclass Httpd:
441251881Speter  "Run httpd for DAV tests"
442251881Speter  def __init__(self, abs_httpd_dir, abs_objdir, abs_builddir, httpd_port,
443251881Speter               service, no_log, httpv2, short_circuit, bulk_updates):
444251881Speter    self.name = 'apache.exe'
445251881Speter    self.httpd_port = httpd_port
446251881Speter    self.httpd_dir = abs_httpd_dir
447251881Speter
448251881Speter    if httpv2:
449251881Speter      self.httpv2_option = 'on'
450251881Speter    else:
451251881Speter      self.httpv2_option = 'off'
452251881Speter
453251881Speter    if bulk_updates:
454251881Speter      self.bulkupdates_option = 'on'
455251881Speter    else:
456251881Speter      self.bulkupdates_option = 'off'
457251881Speter
458251881Speter    self.service = service
459251881Speter    self.proc_handle = None
460251881Speter    self.path = os.path.join(self.httpd_dir, 'bin', self.name)
461251881Speter
462251881Speter    if short_circuit:
463251881Speter      self.path_authz_option = 'short_circuit'
464251881Speter    else:
465251881Speter      self.path_authz_option = 'on'
466251881Speter
467251881Speter    if not os.path.exists(self.path):
468251881Speter      self.name = 'httpd.exe'
469251881Speter      self.path = os.path.join(self.httpd_dir, 'bin', self.name)
470251881Speter      if not os.path.exists(self.path):
471251881Speter        raise RuntimeError("Could not find a valid httpd binary!")
472251881Speter
473251881Speter    self.root_dir = os.path.join(CMDLINE_TEST_SCRIPT_NATIVE_PATH, 'httpd')
474251881Speter    self.root = os.path.join(abs_builddir, self.root_dir)
475251881Speter    self.authz_file = os.path.join(abs_builddir,
476251881Speter                                   CMDLINE_TEST_SCRIPT_NATIVE_PATH,
477251881Speter                                   'svn-test-work', 'authz')
478251881Speter    self.dontdothat_file = os.path.join(abs_builddir,
479251881Speter                                         CMDLINE_TEST_SCRIPT_NATIVE_PATH,
480251881Speter                                         'svn-test-work', 'dontdothat')
481251881Speter    self.httpd_config = os.path.join(self.root, 'httpd.conf')
482251881Speter    self.httpd_users = os.path.join(self.root, 'users')
483251881Speter    self.httpd_mime_types = os.path.join(self.root, 'mime.types')
484251881Speter    self.abs_builddir = abs_builddir
485251881Speter    self.abs_objdir = abs_objdir
486251881Speter    self.service_name = 'svn-test-httpd-' + str(httpd_port)
487251881Speter
488251881Speter    if self.service:
489251881Speter      self.httpd_args = [self.name, '-n', self._quote(self.service_name),
490251881Speter                         '-f', self._quote(self.httpd_config)]
491251881Speter    else:
492251881Speter      self.httpd_args = [self.name, '-f', self._quote(self.httpd_config)]
493251881Speter
494251881Speter    create_target_dir(self.root_dir)
495251881Speter
496251881Speter    self._create_users_file()
497251881Speter    self._create_mime_types_file()
498251881Speter    self._create_dontdothat_file()
499251881Speter
500251881Speter    # Determine version.
501251881Speter    if os.path.exists(os.path.join(self.httpd_dir,
502251881Speter                                   'modules', 'mod_access_compat.so')):
503251881Speter      self.httpd_ver = 2.3
504251881Speter    elif os.path.exists(os.path.join(self.httpd_dir,
505251881Speter                                     'modules', 'mod_auth_basic.so')):
506251881Speter      self.httpd_ver = 2.2
507251881Speter    else:
508251881Speter      self.httpd_ver = 2.0
509251881Speter
510251881Speter    # Create httpd config file
511251881Speter    fp = open(self.httpd_config, 'w')
512251881Speter
513251881Speter    # Limit the number of threads (default = 64)
514251881Speter    fp.write('<IfModule mpm_winnt.c>\n')
515251881Speter    fp.write('ThreadsPerChild 16\n')
516251881Speter    fp.write('</IfModule>\n')
517251881Speter
518251881Speter    # Global Environment
519251881Speter    fp.write('ServerRoot   ' + self._quote(self.root) + '\n')
520251881Speter    fp.write('DocumentRoot ' + self._quote(self.root) + '\n')
521251881Speter    fp.write('ServerName   localhost\n')
522251881Speter    fp.write('PidFile      pid\n')
523251881Speter    fp.write('ErrorLog     log\n')
524251881Speter    fp.write('Listen       ' + str(self.httpd_port) + '\n')
525251881Speter
526251881Speter    if not no_log:
527251881Speter      fp.write('LogFormat    "%h %l %u %t \\"%r\\" %>s %b" common\n')
528251881Speter      fp.write('Customlog    log common\n')
529251881Speter      fp.write('LogLevel     Debug\n')
530251881Speter    else:
531251881Speter      fp.write('LogLevel     Crit\n')
532251881Speter
533251881Speter    # Write LoadModule for minimal system module
534251881Speter    fp.write(self._sys_module('dav_module', 'mod_dav.so'))
535251881Speter    if self.httpd_ver >= 2.3:
536251881Speter      fp.write(self._sys_module('access_compat_module', 'mod_access_compat.so'))
537251881Speter      fp.write(self._sys_module('authz_core_module', 'mod_authz_core.so'))
538251881Speter      fp.write(self._sys_module('authz_user_module', 'mod_authz_user.so'))
539251881Speter      fp.write(self._sys_module('authn_core_module', 'mod_authn_core.so'))
540251881Speter    if self.httpd_ver >= 2.2:
541251881Speter      fp.write(self._sys_module('auth_basic_module', 'mod_auth_basic.so'))
542251881Speter      fp.write(self._sys_module('authn_file_module', 'mod_authn_file.so'))
543251881Speter    else:
544251881Speter      fp.write(self._sys_module('auth_module', 'mod_auth.so'))
545251881Speter    fp.write(self._sys_module('alias_module', 'mod_alias.so'))
546251881Speter    fp.write(self._sys_module('mime_module', 'mod_mime.so'))
547251881Speter    fp.write(self._sys_module('log_config_module', 'mod_log_config.so'))
548251881Speter
549251881Speter    # Write LoadModule for Subversion modules
550251881Speter    fp.write(self._svn_module('dav_svn_module', 'mod_dav_svn.so'))
551251881Speter    fp.write(self._svn_module('authz_svn_module', 'mod_authz_svn.so'))
552251881Speter
553251881Speter    # And for mod_dontdothat
554251881Speter    fp.write(self._svn_module('dontdothat_module', 'mod_dontdothat.so'))
555251881Speter
556251881Speter    # Don't handle .htaccess, symlinks, etc.
557251881Speter    fp.write('<Directory />\n')
558251881Speter    fp.write('AllowOverride None\n')
559251881Speter    fp.write('Options None\n')
560251881Speter    fp.write('</Directory>\n\n')
561251881Speter
562251881Speter    # Define two locations for repositories
563251881Speter    fp.write(self._svn_repo('repositories'))
564251881Speter    fp.write(self._svn_repo('local_tmp'))
565251881Speter
566251881Speter    # And two redirects for the redirect tests
567251881Speter    fp.write('RedirectMatch permanent ^/svn-test-work/repositories/'
568251881Speter             'REDIRECT-PERM-(.*)$ /svn-test-work/repositories/$1\n')
569251881Speter    fp.write('RedirectMatch           ^/svn-test-work/repositories/'
570251881Speter             'REDIRECT-TEMP-(.*)$ /svn-test-work/repositories/$1\n')
571251881Speter
572251881Speter    fp.write('TypesConfig     ' + self._quote(self.httpd_mime_types) + '\n')
573251881Speter    fp.write('HostNameLookups Off\n')
574251881Speter
575251881Speter    fp.close()
576251881Speter
577251881Speter  def __del__(self):
578251881Speter    "Stop httpd when the object is deleted"
579251881Speter    self.stop()
580251881Speter
581251881Speter  def _quote(self, arg):
582251881Speter    if ' ' in arg:
583251881Speter      return '"' + arg + '"'
584251881Speter    else:
585251881Speter      return arg
586251881Speter
587251881Speter  def _create_users_file(self):
588251881Speter    "Create users file"
589251881Speter    htpasswd = os.path.join(self.httpd_dir, 'bin', 'htpasswd.exe')
590251881Speter    # Create the cheapest to compare password form for our testsuite
591251881Speter    os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bcp', self.httpd_users,
592251881Speter                                    'jrandom', 'rayjandom'])
593251881Speter    os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp',  self.httpd_users,
594251881Speter                                    'jconstant', 'rayjandom'])
595251881Speter
596251881Speter  def _create_mime_types_file(self):
597251881Speter    "Create empty mime.types file"
598251881Speter    fp = open(self.httpd_mime_types, 'w')
599251881Speter    fp.close()
600251881Speter
601251881Speter  def _create_dontdothat_file(self):
602251881Speter    "Create empty mime.types file"
603253734Speter    # If the tests have not previously been run or were cleaned
604253734Speter    # up, then 'svn-test-work' does not exist yet.
605253734Speter    parent_dir = os.path.dirname(self.dontdothat_file)
606253734Speter    if not os.path.exists(parent_dir):
607253734Speter      os.makedirs(parent_dir)
608253734Speter
609251881Speter    fp = open(self.dontdothat_file, 'w')
610251881Speter    fp.write('[recursive-actions]\n')
611251881Speter    fp.write('/ = deny\n')
612251881Speter    fp.close()
613251881Speter
614251881Speter  def _sys_module(self, name, path):
615251881Speter    full_path = os.path.join(self.httpd_dir, 'modules', path)
616251881Speter    return 'LoadModule ' + name + " " + self._quote(full_path) + '\n'
617251881Speter
618251881Speter  def _svn_module(self, name, path):
619251881Speter    full_path = os.path.join(self.abs_objdir, path)
620251881Speter    return 'LoadModule ' + name + ' ' + self._quote(full_path) + '\n'
621251881Speter
622251881Speter  def _svn_repo(self, name):
623251881Speter    path = os.path.join(self.abs_builddir,
624251881Speter                        CMDLINE_TEST_SCRIPT_NATIVE_PATH,
625251881Speter                        'svn-test-work', name)
626251881Speter    location = '/svn-test-work/' + name
627251881Speter    ddt_location = '/ddt-test-work/' + name
628251881Speter    return \
629251881Speter      '<Location ' + location + '>\n' \
630251881Speter      '  DAV             svn\n' \
631251881Speter      '  SVNParentPath   ' + self._quote(path) + '\n' \
632251881Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
633251881Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
634251881Speter      '  SVNAllowBulkUpdates ' + self.bulkupdates_option + '\n' \
635251881Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
636251881Speter      '  AuthType        Basic\n' \
637251881Speter      '  AuthName        "Subversion Repository"\n' \
638251881Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
639251881Speter      '  Require         valid-user\n' \
640251881Speter      '</Location>\n' \
641251881Speter      '<Location ' + ddt_location + '>\n' \
642251881Speter      '  DAV             svn\n' \
643251881Speter      '  SVNParentPath   ' + self._quote(path) + '\n' \
644251881Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
645251881Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
646251881Speter      '  SVNAllowBulkUpdates ' + self.bulkupdates_option + '\n' \
647251881Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
648251881Speter      '  AuthType        Basic\n' \
649251881Speter      '  AuthName        "Subversion Repository"\n' \
650251881Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
651251881Speter      '  Require         valid-user\n' \
652251881Speter      '  DontDoThatConfigFile ' + self._quote(self.dontdothat_file) + '\n' \
653251881Speter      '</Location>\n'
654251881Speter
655251881Speter  def start(self):
656251881Speter    if self.service:
657251881Speter      self._start_service()
658251881Speter    else:
659251881Speter      self._start_daemon()
660251881Speter
661251881Speter  def stop(self):
662251881Speter    if self.service:
663251881Speter      self._stop_service()
664251881Speter    else:
665251881Speter      self._stop_daemon()
666251881Speter
667251881Speter  def _start_service(self):
668251881Speter    "Install and start HTTPD service"
669251881Speter    print('Installing service %s' % self.service_name)
670251881Speter    os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'install'])
671251881Speter    print('Starting service %s' % self.service_name)
672251881Speter    os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'start'])
673251881Speter
674251881Speter  def _stop_service(self):
675251881Speter    "Stop and uninstall HTTPD service"
676251881Speter    os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'stop'])
677251881Speter    os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'uninstall'])
678251881Speter
679251881Speter  def _start_daemon(self):
680251881Speter    "Start HTTPD as daemon"
681251881Speter    print('Starting httpd as daemon')
682251881Speter    print(self.httpd_args)
683251881Speter    try:
684251881Speter      import win32process
685251881Speter      import win32con
686251881Speter      args = ' '.join([self._quote(x) for x in self.httpd_args])
687251881Speter      self.proc_handle = (
688251881Speter        win32process.CreateProcess(self._quote(self.path), args,
689251881Speter                                   None, None, 0,
690251881Speter                                   win32con.CREATE_NEW_CONSOLE,
691251881Speter                                   None, None, win32process.STARTUPINFO()))[0]
692251881Speter    except ImportError:
693251881Speter      os.spawnv(os.P_NOWAIT, self.path, self.httpd_args)
694251881Speter
695251881Speter  def _stop_daemon(self):
696251881Speter    "Stop the HTTPD daemon"
697251881Speter    if self.proc_handle is not None:
698251881Speter      try:
699251881Speter        import win32process
700251881Speter        print('Stopping %s' % self.name)
701251881Speter        win32process.TerminateProcess(self.proc_handle, 0)
702251881Speter        return
703251881Speter      except ImportError:
704251881Speter        pass
705251881Speter    print('Httpd.stop_daemon not implemented')
706251881Speter
707251881Speter# Move the binaries to the test directory
708251881Speterlocate_libs()
709251881Speterif create_dirs:
710251881Speter  old_cwd = os.getcwd()
711251881Speter  try:
712251881Speter    os.chdir(abs_objdir)
713251881Speter    baton = copied_execs
714251881Speter    for dirpath, dirs, files in os.walk('subversion'):
715251881Speter      copy_execs(baton, dirpath, files)
716251881Speter    for dirpath, dirs, files in os.walk('tools/server-side'):
717251881Speter      copy_execs(baton, dirpath, files)
718251881Speter  except:
719251881Speter    os.chdir(old_cwd)
720251881Speter    raise
721251881Speter  else:
722251881Speter    os.chdir(old_cwd)
723251881Speter
724251881Speter# Create the base directory for Python tests
725251881Spetercreate_target_dir(CMDLINE_TEST_SCRIPT_NATIVE_PATH)
726251881Speter
727251881Speter# Ensure the tests directory is correctly cased
728251881Speterabs_builddir = fix_case(abs_builddir)
729251881Speter
730251881Speterdaemon = None
731251881Speter# Run the tests
732251881Speter
733251881Speter# No need to start any servers if we are only listing the tests.
734251881Speterif not list_tests:
735251881Speter  if run_svnserve:
736251881Speter    daemon = Svnserve(svnserve_args, objdir, abs_objdir, abs_builddir)
737251881Speter
738251881Speter  if run_httpd:
739251881Speter    daemon = Httpd(abs_httpd_dir, abs_objdir, abs_builddir, httpd_port,
740251881Speter                   httpd_service, httpd_no_log,
741251881Speter                   advertise_httpv2, http_short_circuit,
742251881Speter                   http_bulk_updates)
743251881Speter
744251881Speter  # Start service daemon, if any
745251881Speter  if daemon:
746251881Speter    daemon.start()
747251881Speter
748251881Speter# Find the full path and filename of any test that is specified just by
749251881Speter# its base name.
750251881Speterif len(tests_to_run) != 0:
751251881Speter  tests = []
752251881Speter  for t in tests_to_run:
753251881Speter    tns = None
754251881Speter    if '#' in t:
755251881Speter      t, tns = t.split('#')
756251881Speter
757251881Speter    test = [x for x in all_tests if x.split('/')[-1] == t]
758251881Speter    if not test and not (t.endswith('-test.exe') or t.endswith('_tests.py')):
759251881Speter      # The lengths of '-test.exe' and of '_tests.py' are both 9.
760251881Speter      test = [x for x in all_tests if x.split('/')[-1][:-9] == t]
761251881Speter
762251881Speter    if not test:
763251881Speter      print("Skipping test '%s', test not found." % t)
764251881Speter    elif tns:
765251881Speter      tests.append('%s#%s' % (test[0], tns))
766251881Speter    else:
767251881Speter      tests.extend(test)
768251881Speter
769251881Speter  tests_to_run = tests
770251881Speterelse:
771251881Speter  tests_to_run = all_tests
772251881Speter
773251881Speter
774251881Speterif list_tests:
775251881Speter  print('Listing %s configuration on %s' % (objdir, repo_loc))
776251881Speterelse:
777251881Speter  print('Testing %s configuration on %s' % (objdir, repo_loc))
778251881Spetersys.path.insert(0, os.path.join(abs_srcdir, 'build'))
779251881Speter
780251881Speterif not test_javahl:
781251881Speter  import run_tests
782251881Speter  if log_to_stdout:
783251881Speter    log_file = None
784251881Speter    fail_log_file = None
785251881Speter  else:
786251881Speter    log_file = os.path.join(abs_builddir, log)
787251881Speter    fail_log_file = os.path.join(abs_builddir, faillog)
788251881Speter
789251881Speter  th = run_tests.TestHarness(abs_srcdir, abs_builddir,
790251881Speter                             log_file,
791251881Speter                             fail_log_file,
792251881Speter                             base_url, fs_type, 'serf',
793251881Speter                             server_minor_version, not quiet,
794251881Speter                             cleanup, enable_sasl, parallel, config_file,
795251881Speter                             fsfs_sharding, fsfs_packing,
796251881Speter                             list_tests, svn_bin, mode_filter,
797251881Speter                             milestone_filter,
798251881Speter                             set_log_level=log_level, ssl_cert=ssl_cert)
799251881Speter  old_cwd = os.getcwd()
800251881Speter  try:
801251881Speter    os.chdir(abs_builddir)
802251881Speter    failed = th.run(tests_to_run)
803251881Speter  except:
804251881Speter    os.chdir(old_cwd)
805251881Speter    raise
806251881Speter  else:
807251881Speter    os.chdir(old_cwd)
808251881Speterelse:
809251881Speter  failed = False
810251881Speter  args = (
811251881Speter          'java.exe',
812251881Speter          '-Dtest.rootdir=' + os.path.join(abs_builddir, 'javahl'),
813251881Speter          '-Dtest.srcdir=' + os.path.join(abs_srcdir,
814251881Speter                                          'subversion/bindings/javahl'),
815251881Speter          '-Dtest.rooturl=',
816251881Speter          '-Dtest.fstype=' + fs_type ,
817251881Speter          '-Dtest.tests=',
818251881Speter
819251881Speter          '-Djava.library.path='
820251881Speter                    + os.path.join(abs_objdir,
821251881Speter                                   'subversion/bindings/javahl/native'),
822251881Speter          '-classpath',
823251881Speter          os.path.join(abs_srcdir, 'subversion/bindings/javahl/classes') +';' +
824251881Speter            gen_obj.junit_path
825251881Speter         )
826251881Speter
827251881Speter  sys.stderr.flush()
828251881Speter  print('Running org.apache.subversion tests:')
829251881Speter  sys.stdout.flush()
830251881Speter
831251881Speter  r = subprocess.call(args + tuple(['org.apache.subversion.javahl.RunTests']))
832251881Speter  sys.stdout.flush()
833251881Speter  sys.stderr.flush()
834251881Speter  if (r != 0):
835251881Speter    print('[Test runner reported failure]')
836251881Speter    failed = True
837251881Speter
838251881Speter  print('Running org.tigris.subversion tests:')
839251881Speter  sys.stdout.flush()
840251881Speter  r = subprocess.call(args + tuple(['org.tigris.subversion.javahl.RunTests']))
841251881Speter  sys.stdout.flush()
842251881Speter  sys.stderr.flush()
843251881Speter  if (r != 0):
844251881Speter    print('[Test runner reported failure]')
845251881Speter    failed = True
846251881Speter
847251881Speter# Stop service daemon, if any
848251881Speterif daemon:
849251881Speter  del daemon
850251881Speter
851251881Speter# Remove the execs again
852251881Speterfor tgt in copied_execs:
853251881Speter  try:
854251881Speter    if os.path.isfile(tgt):
855251881Speter      if verbose:
856251881Speter        print("kill: %s" % tgt)
857251881Speter      os.unlink(tgt)
858251881Speter  except:
859251881Speter    traceback.print_exc(file=sys.stdout)
860251881Speter    pass
861251881Speter
862251881Speter
863251881Speterif failed:
864251881Speter  sys.exit(1)
865