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
27362181Sdim# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.14.x/win-tests.py $
28369302Sdim# $LastChangedRevision: 1884665 $
29251881Speter
30251881Speterimport os, sys, subprocess
31251881Speterimport filecmp
32251881Speterimport shutil
33251881Speterimport traceback
34289180Speterimport logging
35362181Sdimimport re
36251881Spetertry:
37251881Speter  # Python >=3.0
38251881Speter  import configparser
39251881Speterexcept ImportError:
40251881Speter  # Python <3.0
41251881Speter  import ConfigParser as configparser
42251881Speterimport string
43251881Speterimport random
44251881Speter
45251881Speterimport getopt
46251881Spetertry:
47251881Speter    my_getopt = getopt.gnu_getopt
48251881Speterexcept AttributeError:
49251881Speter    my_getopt = getopt.getopt
50251881Speter
51251881Speterdef _usage_exit():
52251881Speter  "print usage, exit the script"
53251881Speter
54251881Speter  print("Driver for running the tests on Windows.")
55251881Speter  print("Usage: python win-tests.py [option] [test-path]")
56251881Speter  print("")
57251881Speter  print("Valid options:")
58251881Speter  print("  -r, --release          : test the Release configuration")
59251881Speter  print("  -d, --debug            : test the Debug configuration (default)")
60251881Speter  print("  --bin=PATH             : use the svn binaries installed in PATH")
61251881Speter  print("  -u URL, --url=URL      : run ra_dav or ra_svn tests against URL;")
62251881Speter  print("                           will start svnserve for ra_svn tests")
63251881Speter  print("  -v, --verbose          : talk more")
64251881Speter  print("  -f, --fs-type=type     : filesystem type to use (fsfs is default)")
65251881Speter  print("  -c, --cleanup          : cleanup after running a test")
66251881Speter  print("  -t, --test=TEST        : Run the TEST test (all is default); use")
67251881Speter  print("                           TEST#n to run a particular test number,")
68251881Speter  print("                           multiples also accepted e.g. '2,4-7'")
69251881Speter  print("  --log-level=LEVEL      : Set log level to LEVEL (E.g. DEBUG)")
70251881Speter  print("  --log-to-stdout        : Write log results to stdout")
71251881Speter
72251881Speter  print("  --svnserve-args=list   : comma-separated list of arguments for")
73251881Speter  print("                           svnserve")
74251881Speter  print("                           default is '-d,-r,<test-path-root>'")
75251881Speter  print("  --asp.net-hack         : use '_svn' instead of '.svn' for the admin")
76251881Speter  print("                           dir name")
77251881Speter  print("  --httpd-dir            : location where Apache HTTPD is installed")
78251881Speter  print("  --httpd-port           : port for Apache HTTPD; random port number")
79251881Speter  print("                           will be used, if not specified")
80251881Speter  print("  --httpd-daemon         : Run Apache httpd as daemon")
81251881Speter  print("  --httpd-service        : Run Apache httpd as Windows service (default)")
82251881Speter  print("  --httpd-no-log         : Disable httpd logging")
83251881Speter  print("  --http-short-circuit   : Use SVNPathAuthz short_circuit on HTTP server")
84251881Speter  print("  --disable-http-v2      : Do not advertise support for HTTPv2 on server")
85251881Speter  print("  --disable-bulk-updates : Disable bulk updates on HTTP server")
86251881Speter  print("  --ssl-cert             : Path to SSL server certificate to trust.")
87362181Sdim  print("  --https                : Run Apache httpd with an https setup.")
88362181Sdim  print("  --http2                : Enable http2 in Apache Httpd (>= 2.4.17).")
89362181Sdim  print("  --mod-deflate          : Enable mod_deflate in Apache Httpd.")
90362181Sdim  print("  --global-scheduler     : Enable global scheduler.")
91362181Sdim  print("  --exclusive-wc-locks   : Enable exclusive working copy locks")
92362181Sdim  print("  --memcached-dir=DIR    : Run memcached from dir")
93362181Sdim  print("  --memcached-server=    : Enable usage of the specified memcached server")
94362181Sdim  print("              <url:port>")
95362181Sdim  print("  --skip-c-tests         : Skip all C tests")
96362181Sdim  print("  --dump-load-cross-check: Run the dump load cross check after every test")
97362181Sdim
98251881Speter  print("  --javahl               : Run the javahl tests instead of the normal tests")
99289180Speter  print("  --swig=language        : Run the swig perl/python/ruby tests instead of")
100289180Speter  print("                           the normal tests")
101251881Speter  print("  --list                 : print test doc strings only")
102251881Speter  print("  --milestone-filter=RE  : RE is a regular expression pattern that (when")
103251881Speter  print("                           used with --list) limits the tests listed to")
104251881Speter  print("                           those with an associated issue in the tracker")
105251881Speter  print("                           which has a target milestone that matches RE.")
106251881Speter  print("  --mode-filter=TYPE     : limit tests to expected TYPE = XFAIL, SKIP, PASS,")
107251881Speter  print("                           or 'ALL' (default)")
108251881Speter  print("  --enable-sasl          : enable Cyrus SASL authentication for")
109251881Speter  print("                           svnserve")
110251881Speter  print("  -p, --parallel         : run multiple tests in parallel")
111251881Speter  print("  --server-minor-version : the minor version of the server being")
112251881Speter  print("                           tested")
113251881Speter  print("  --config-file          : Configuration file for tests")
114251881Speter  print("  --fsfs-sharding        : Specify shard size (for fsfs)")
115251881Speter  print("  --fsfs-packing         : Run 'svnadmin pack' automatically")
116362181Sdim  print("  --fsfs-compression=VAL : Set compression type to VAL (for fsfs)")
117289180Speter  print("  -q, --quiet            : Deprecated; this is the default.")
118289180Speter  print("                           Use --set-log-level instead.")
119251881Speter
120251881Speter  sys.exit(0)
121251881Speter
122251881SpeterCMDLINE_TEST_SCRIPT_PATH = 'subversion/tests/cmdline/'
123251881SpeterCMDLINE_TEST_SCRIPT_NATIVE_PATH = CMDLINE_TEST_SCRIPT_PATH.replace('/', os.sep)
124251881Speter
125251881Spetersys.path.insert(0, os.path.join('build', 'generator'))
126251881Spetersys.path.insert(1, 'build')
127251881Speter
128289180Speterimport gen_win_dependencies
129289180Speterimport gen_base
130251881Speterversion_header = os.path.join('subversion', 'include', 'svn_version.h')
131251881Spetercp = configparser.ConfigParser()
132251881Spetercp.read('gen-make.opts')
133289180Spetergen_obj = gen_win_dependencies.GenDependenciesBase('build.conf', version_header,
134289180Speter                                                   cp.items('options'))
135251881Speteropts, args = my_getopt(sys.argv[1:], 'hrdvqct:pu:f:',
136251881Speter                       ['release', 'debug', 'verbose', 'quiet', 'cleanup',
137251881Speter                        'test=', 'url=', 'svnserve-args=', 'fs-type=', 'asp.net-hack',
138362181Sdim                        'httpd-dir=', 'httpd-port=', 'httpd-daemon', 'https',
139251881Speter                        'httpd-server', 'http-short-circuit', 'httpd-no-log',
140251881Speter                        'disable-http-v2', 'disable-bulk-updates', 'help',
141289180Speter                        'fsfs-packing', 'fsfs-sharding=', 'javahl', 'swig=',
142362181Sdim                        'list', 'enable-sasl', 'bin=', 'parallel', 'http2',
143362181Sdim                        'mod-deflate', 'global-scheduler',
144251881Speter                        'config-file=', 'server-minor-version=', 'log-level=',
145251881Speter                        'log-to-stdout', 'mode-filter=', 'milestone-filter=',
146362181Sdim                        'ssl-cert=', 'exclusive-wc-locks', 'memcached-server=',
147362181Sdim                        'skip-c-tests', 'dump-load-cross-check', 'memcached-dir=',
148362181Sdim                        'fsfs-compression=',
149362181Sdim                        ])
150251881Speterif len(args) > 1:
151251881Speter  print('Warning: non-option arguments after the first one will be ignored')
152251881Speter
153251881Speter# Interpret the options and set parameters
154289180Speterbase_url, fs_type, verbose, cleanup = None, None, None, None
155362181Sdimglobal_scheduler = None
156251881Speterrepo_loc = 'local repository.'
157251881Speterobjdir = 'Debug'
158251881Speterlog = 'tests.log'
159251881Speterfaillog = 'fails.log'
160251881Speterrun_svnserve = None
161251881Spetersvnserve_args = None
162251881Speterrun_httpd = None
163251881Speterhttpd_port = None
164251881Speterhttpd_service = None
165251881Speterhttpd_no_log = None
166362181Sdimuse_ssl = False
167362181Sdimuse_http2 = False
168362181Sdimuse_mod_deflate = False
169251881Speterhttp_short_circuit = False
170251881Speteradvertise_httpv2 = True
171251881Speterhttp_bulk_updates = True
172251881Speterlist_tests = None
173251881Spetermilestone_filter = None
174251881Spetertest_javahl = None
175289180Spetertest_swig = None
176251881Speterenable_sasl = None
177251881Spetersvn_bin = None
178251881Speterparallel = None
179251881Speterfsfs_sharding = None
180251881Speterfsfs_packing = None
181251881Speterserver_minor_version = None
182251881Speterconfig_file = None
183251881Speterlog_to_stdout = None
184251881Spetermode_filter=None
185251881Spetertests_to_run = []
186251881Speterlog_level = None
187251881Speterssl_cert = None
188362181Sdimexclusive_wc_locks = None
189362181Sdimrun_memcached = None
190362181Sdimmemcached_server = None
191362181Sdimmemcached_dir = None
192362181Sdimskip_c_tests = None
193362181Sdimdump_load_cross_check = None
194362181Sdimfsfs_compression = None
195362181Sdimfsfs_dir_deltification = None
196251881Speter
197251881Speterfor opt, val in opts:
198251881Speter  if opt in ('-h', '--help'):
199251881Speter    _usage_exit()
200251881Speter  elif opt in ('-u', '--url'):
201251881Speter    base_url = val
202251881Speter  elif opt in ('-f', '--fs-type'):
203251881Speter    fs_type = val
204251881Speter  elif opt in ('-v', '--verbose'):
205251881Speter    verbose = 1
206289180Speter    log_level = logging.DEBUG
207251881Speter  elif opt in ('-c', '--cleanup'):
208251881Speter    cleanup = 1
209251881Speter  elif opt in ('-t', '--test'):
210251881Speter    tests_to_run.append(val)
211251881Speter  elif opt in ['-r', '--release']:
212251881Speter    objdir = 'Release'
213251881Speter  elif opt in ['-d', '--debug']:
214251881Speter    objdir = 'Debug'
215251881Speter  elif opt == '--svnserve-args':
216251881Speter    svnserve_args = val.split(',')
217251881Speter    run_svnserve = 1
218251881Speter  elif opt == '--asp.net-hack':
219251881Speter    os.environ['SVN_ASP_DOT_NET_HACK'] = opt
220251881Speter  elif opt == '--httpd-dir':
221251881Speter    abs_httpd_dir = os.path.abspath(val)
222251881Speter    run_httpd = 1
223251881Speter  elif opt == '--httpd-port':
224251881Speter    httpd_port = int(val)
225251881Speter  elif opt == '--httpd-daemon':
226251881Speter    httpd_service = 0
227251881Speter  elif opt == '--httpd-service':
228251881Speter    httpd_service = 1
229251881Speter  elif opt == '--httpd-no-log':
230251881Speter    httpd_no_log = 1
231362181Sdim  elif opt == '--https':
232362181Sdim    use_ssl = 1
233362181Sdim  elif opt == '--http2':
234362181Sdim    use_http2 = 1
235362181Sdim  elif opt == '--mod-deflate':
236362181Sdim    use_mod_deflate = 1
237251881Speter  elif opt == '--http-short-circuit':
238251881Speter    http_short_circuit = True
239251881Speter  elif opt == '--disable-http-v2':
240251881Speter    advertise_httpv2 = False
241251881Speter  elif opt == '--disable-bulk-updates':
242251881Speter    http_bulk_updates = False
243251881Speter  elif opt == '--fsfs-sharding':
244251881Speter    fsfs_sharding = int(val)
245251881Speter  elif opt == '--fsfs-packing':
246251881Speter    fsfs_packing = 1
247251881Speter  elif opt == '--javahl':
248251881Speter    test_javahl = 1
249362181Sdim  elif opt == '--global-scheduler':
250362181Sdim    global_scheduler = 1
251289180Speter  elif opt == '--swig':
252289180Speter    if val not in ['perl', 'python', 'ruby']:
253289180Speter      sys.stderr.write('Running \'%s\' swig tests not supported (yet).\n'
254289180Speter                        % (val,))
255289180Speter    test_swig = val
256251881Speter  elif opt == '--list':
257251881Speter    list_tests = 1
258251881Speter  elif opt == '--milestone-filter':
259251881Speter    milestone_filter = val
260251881Speter  elif opt == '--mode-filter':
261251881Speter    mode_filter = val
262251881Speter  elif opt == '--enable-sasl':
263251881Speter    enable_sasl = 1
264251881Speter    base_url = "svn://localhost/"
265251881Speter  elif opt == '--server-minor-version':
266298845Sdim    server_minor_version = int(val)
267251881Speter  elif opt == '--bin':
268251881Speter    svn_bin = val
269251881Speter  elif opt in ('-p', '--parallel'):
270251881Speter    parallel = 1
271251881Speter  elif opt in ('--config-file'):
272251881Speter    config_file = val
273251881Speter  elif opt == '--log-to-stdout':
274251881Speter    log_to_stdout = 1
275251881Speter  elif opt == '--log-level':
276289180Speter    log_level = getattr(logging, val, None) or int(val)
277251881Speter  elif opt == '--ssl-cert':
278251881Speter    ssl_cert = val
279362181Sdim  elif opt == '--exclusive-wc-locks':
280362181Sdim    exclusive_wc_locks = 1
281362181Sdim  elif opt == '--memcached-server':
282362181Sdim    memcached_server = val
283362181Sdim  elif opt == '--skip-c-tests':
284362181Sdim    skip_c_tests = 1
285362181Sdim  elif opt == '--dump-load-cross-check':
286362181Sdim    dump_load_cross_check = 1
287362181Sdim  elif opt == '--memcached-dir':
288362181Sdim    memcached_dir = val
289362181Sdim    run_memcached = 1
290362181Sdim  elif opt == '--fsfs-compression':
291362181Sdim    fsfs_compression = val
292362181Sdim  elif opt == '--fsfs-dir-deltification':
293362181Sdim    fsfs_dir_deltification = val
294251881Speter
295251881Speter# Calculate the source and test directory names
296251881Speterabs_srcdir = os.path.abspath("")
297251881Speterabs_objdir = os.path.join(abs_srcdir, objdir)
298251881Speterif len(args) == 0:
299251881Speter  abs_builddir = abs_objdir
300251881Speter  create_dirs = 0
301251881Speterelse:
302251881Speter  abs_builddir = os.path.abspath(args[0])
303251881Speter  create_dirs = 1
304251881Speter
305251881Speter# Default to fsfs explicitly
306251881Speterif not fs_type:
307251881Speter  fs_type = 'fsfs'
308251881Speter
309289180Speterif fs_type == 'bdb':
310289180Speter  all_tests = gen_obj.test_progs + gen_obj.bdb_test_progs \
311289180Speter            + gen_obj.scripts + gen_obj.bdb_scripts
312289180Speterelse:
313251881Speter  all_tests = gen_obj.test_progs + gen_obj.scripts
314251881Speter
315289180Speterclient_tests = [x for x in all_tests if x.startswith(CMDLINE_TEST_SCRIPT_PATH)]
316289180Speter
317251881Speterif run_httpd:
318251881Speter  if not httpd_port:
319251881Speter    httpd_port = random.randrange(1024, 30000)
320251881Speter  if not base_url:
321362181Sdim    if use_ssl:
322362181Sdim      scheme = 'https'
323362181Sdim    else:
324362181Sdim      scheme = 'http'
325251881Speter
326362181Sdim    base_url = '%s://localhost:%d' % (scheme, httpd_port)
327362181Sdim
328251881Speterif base_url:
329251881Speter  repo_loc = 'remote repository ' + base_url + '.'
330251881Speter  if base_url[:4] == 'http':
331251881Speter    log = 'dav-tests.log'
332251881Speter    faillog = 'dav-fails.log'
333251881Speter  elif base_url[:3] == 'svn':
334251881Speter    log = 'svn-tests.log'
335251881Speter    faillog = 'svn-fails.log'
336251881Speter    run_svnserve = 1
337251881Speter  else:
338251881Speter    # Don't know this scheme, but who're we to judge whether it's
339251881Speter    # correct or not?
340251881Speter    log = 'url-tests.log'
341251881Speter    faillog = 'url-fails.log'
342251881Speter
343251881Speter# Have to move the executables where the tests expect them to be
344251881Spetercopied_execs = []   # Store copied exec files to avoid the final dir scan
345251881Speter
346251881Speterdef create_target_dir(dirname):
347251881Speter  tgt_dir = os.path.join(abs_builddir, dirname)
348251881Speter  if not os.path.exists(tgt_dir):
349251881Speter    if verbose:
350251881Speter      print("mkdir: %s" % tgt_dir)
351251881Speter    os.makedirs(tgt_dir)
352251881Speter
353289180Speterdef copy_changed_file(src, tgt=None, to_dir=None, cleanup=True):
354251881Speter  if not os.path.isfile(src):
355251881Speter    print('Could not find ' + src)
356251881Speter    sys.exit(1)
357289180Speter
358289180Speter  if to_dir and not tgt:
359289180Speter    tgt = os.path.join(to_dir, os.path.basename(src))
360289180Speter  elif not tgt or (tgt and to_dir):
361289180Speter    raise RuntimeError("Using 'tgt' *or* 'to_dir' is required" % (tgt,))
362289180Speter  elif tgt and os.path.isdir(tgt):
363289180Speter    raise RuntimeError("'%s' is a directory. Use to_dir=" % (tgt,))
364289180Speter
365251881Speter  if os.path.exists(tgt):
366251881Speter    assert os.path.isfile(tgt)
367251881Speter    if filecmp.cmp(src, tgt):
368251881Speter      if verbose:
369251881Speter        print("same: %s" % src)
370251881Speter        print(" and: %s" % tgt)
371251881Speter      return 0
372251881Speter  if verbose:
373251881Speter    print("copy: %s" % src)
374251881Speter    print("  to: %s" % tgt)
375251881Speter  shutil.copy(src, tgt)
376251881Speter
377289180Speter  if cleanup:
378289180Speter    copied_execs.append(tgt)
379251881Speter
380251881Speterdef locate_libs():
381251881Speter  "Move DLLs to a known location and set env vars"
382251881Speter
383289180Speter  debug = (objdir == 'Debug')
384251881Speter
385289180Speter  for lib in gen_obj._libraries.values():
386251881Speter
387289180Speter    if debug:
388289180Speter      name, dir = lib.debug_dll_name, lib.debug_dll_dir
389289180Speter    else:
390289180Speter      name, dir = lib.dll_name, lib.dll_dir
391251881Speter
392289180Speter    if name and dir:
393289180Speter      src = os.path.join(dir, name)
394289180Speter      if os.path.exists(src):
395289180Speter        copy_changed_file(src, to_dir=abs_builddir, cleanup=False)
396251881Speter
397289180Speter    for name in lib.extra_bin:
398289180Speter      src = os.path.join(dir, name)
399289180Speter      copy_changed_file(src, to_dir=abs_builddir)
400251881Speter
401251881Speter
402251881Speter  # Copy the Subversion library DLLs
403289180Speter  for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL):
404289180Speter    if isinstance(i, gen_base.TargetLib) and i.msvc_export:
405289180Speter      src = os.path.join(abs_objdir, i.filename)
406289180Speter      if os.path.isfile(src):
407289180Speter        copy_changed_file(src, to_dir=abs_builddir,
408289180Speter                          cleanup=False)
409251881Speter
410251881Speter  # Copy the Apache modules
411251881Speter  if run_httpd and cp.has_option('options', '--with-httpd'):
412251881Speter    mod_dav_svn_path = os.path.join(abs_objdir, 'subversion',
413251881Speter                                    'mod_dav_svn', 'mod_dav_svn.so')
414251881Speter    mod_authz_svn_path = os.path.join(abs_objdir, 'subversion',
415251881Speter                                      'mod_authz_svn', 'mod_authz_svn.so')
416251881Speter    mod_dontdothat_path = os.path.join(abs_objdir, 'tools', 'server-side',
417251881Speter                                        'mod_dontdothat', 'mod_dontdothat.so')
418251881Speter
419289180Speter    copy_changed_file(mod_dav_svn_path, to_dir=abs_builddir, cleanup=False)
420289180Speter    copy_changed_file(mod_authz_svn_path, to_dir=abs_builddir, cleanup=False)
421289180Speter    copy_changed_file(mod_dontdothat_path, to_dir=abs_builddir, cleanup=False)
422251881Speter
423289180Speter  os.environ['PATH'] = abs_builddir + os.pathsep + os.environ['PATH']
424251881Speter
425251881Speterdef fix_case(path):
426251881Speter    path = os.path.normpath(path)
427251881Speter    parts = path.split(os.path.sep)
428251881Speter    drive = parts[0].upper()
429251881Speter    parts = parts[1:]
430251881Speter    path = drive + os.path.sep
431251881Speter    for part in parts:
432251881Speter        dirs = os.listdir(path)
433251881Speter        for dir in dirs:
434251881Speter            if dir.lower() == part.lower():
435251881Speter                path = os.path.join(path, dir)
436251881Speter                break
437251881Speter    return path
438251881Speter
439251881Speterclass Svnserve:
440251881Speter  "Run svnserve for ra_svn tests"
441251881Speter  def __init__(self, svnserve_args, objdir, abs_objdir, abs_builddir):
442251881Speter    self.args = svnserve_args
443251881Speter    self.name = 'svnserve.exe'
444251881Speter    self.kind = objdir
445251881Speter    self.path = os.path.join(abs_objdir,
446251881Speter                             'subversion', 'svnserve', self.name)
447251881Speter    self.root = os.path.join(abs_builddir, CMDLINE_TEST_SCRIPT_NATIVE_PATH)
448289180Speter    self.proc = None
449251881Speter
450251881Speter  def __del__(self):
451251881Speter    "Stop svnserve when the object is deleted"
452251881Speter    self.stop()
453251881Speter
454251881Speter  def _quote(self, arg):
455251881Speter    if ' ' in arg:
456251881Speter      return '"' + arg + '"'
457251881Speter    else:
458251881Speter      return arg
459251881Speter
460251881Speter  def start(self):
461251881Speter    if not self.args:
462251881Speter      args = [self.name, '-d', '-r', self.root]
463251881Speter    else:
464251881Speter      args = [self.name] + self.args
465251881Speter    print('Starting %s %s' % (self.kind, self.name))
466251881Speter
467362181Sdim    env = os.environ.copy()
468362181Sdim    env['SVN_DBG_STACKTRACES_TO_STDERR'] = 'y'
469362181Sdim    self.proc = subprocess.Popen([self.path] + args[1:], env=env)
470289180Speter
471251881Speter  def stop(self):
472289180Speter    if self.proc is not None:
473251881Speter      try:
474251881Speter        print('Stopping %s' % self.name)
475289180Speter        self.proc.poll();
476289180Speter        if self.proc.returncode is None:
477289180Speter          self.proc.kill();
478251881Speter        return
479289180Speter      except AttributeError:
480251881Speter        pass
481251881Speter    print('Svnserve.stop not implemented')
482251881Speter
483251881Speterclass Httpd:
484251881Speter  "Run httpd for DAV tests"
485362181Sdim  def __init__(self, abs_httpd_dir, abs_objdir, abs_builddir, abs_srcdir,
486362181Sdim               httpd_port, service, use_ssl, use_http2, use_mod_deflate,
487362181Sdim               no_log, httpv2, short_circuit, bulk_updates):
488251881Speter    self.name = 'apache.exe'
489251881Speter    self.httpd_port = httpd_port
490251881Speter    self.httpd_dir = abs_httpd_dir
491251881Speter
492251881Speter    if httpv2:
493251881Speter      self.httpv2_option = 'on'
494251881Speter    else:
495251881Speter      self.httpv2_option = 'off'
496251881Speter
497251881Speter    if bulk_updates:
498251881Speter      self.bulkupdates_option = 'on'
499251881Speter    else:
500251881Speter      self.bulkupdates_option = 'off'
501251881Speter
502251881Speter    self.service = service
503289180Speter    self.proc = None
504251881Speter    self.path = os.path.join(self.httpd_dir, 'bin', self.name)
505251881Speter
506251881Speter    if short_circuit:
507251881Speter      self.path_authz_option = 'short_circuit'
508251881Speter    else:
509251881Speter      self.path_authz_option = 'on'
510251881Speter
511251881Speter    if not os.path.exists(self.path):
512251881Speter      self.name = 'httpd.exe'
513251881Speter      self.path = os.path.join(self.httpd_dir, 'bin', self.name)
514251881Speter      if not os.path.exists(self.path):
515251881Speter        raise RuntimeError("Could not find a valid httpd binary!")
516251881Speter
517251881Speter    self.root_dir = os.path.join(CMDLINE_TEST_SCRIPT_NATIVE_PATH, 'httpd')
518251881Speter    self.root = os.path.join(abs_builddir, self.root_dir)
519251881Speter    self.authz_file = os.path.join(abs_builddir,
520251881Speter                                   CMDLINE_TEST_SCRIPT_NATIVE_PATH,
521251881Speter                                   'svn-test-work', 'authz')
522251881Speter    self.dontdothat_file = os.path.join(abs_builddir,
523251881Speter                                         CMDLINE_TEST_SCRIPT_NATIVE_PATH,
524251881Speter                                         'svn-test-work', 'dontdothat')
525362181Sdim    self.certfile = os.path.join(abs_builddir,
526362181Sdim                                 CMDLINE_TEST_SCRIPT_NATIVE_PATH,
527362181Sdim                                 'svn-test-work', 'cert.pem')
528362181Sdim    self.certkeyfile = os.path.join(abs_builddir,
529362181Sdim                                     CMDLINE_TEST_SCRIPT_NATIVE_PATH,
530362181Sdim                                     'svn-test-work', 'cert-key.pem')
531251881Speter    self.httpd_config = os.path.join(self.root, 'httpd.conf')
532251881Speter    self.httpd_users = os.path.join(self.root, 'users')
533251881Speter    self.httpd_mime_types = os.path.join(self.root, 'mime.types')
534286506Speter    self.httpd_groups = os.path.join(self.root, 'groups')
535251881Speter    self.abs_builddir = abs_builddir
536251881Speter    self.abs_objdir = abs_objdir
537362181Sdim    self.abs_srcdir = abs_srcdir
538251881Speter    self.service_name = 'svn-test-httpd-' + str(httpd_port)
539251881Speter
540251881Speter    if self.service:
541251881Speter      self.httpd_args = [self.name, '-n', self._quote(self.service_name),
542251881Speter                         '-f', self._quote(self.httpd_config)]
543251881Speter    else:
544251881Speter      self.httpd_args = [self.name, '-f', self._quote(self.httpd_config)]
545251881Speter
546251881Speter    create_target_dir(self.root_dir)
547251881Speter
548251881Speter    self._create_users_file()
549286506Speter    self._create_groups_file()
550251881Speter    self._create_mime_types_file()
551251881Speter    self._create_dontdothat_file()
552251881Speter
553362181Sdim    if use_ssl:
554362181Sdim      self._create_cert_files()
555362181Sdim
556289180Speter    # Obtain version.
557289180Speter    version_vals = gen_obj._libraries['httpd'].version.split('.')
558289180Speter    self.httpd_ver = float('%s.%s' % (version_vals[0], version_vals[1]))
559251881Speter
560251881Speter    # Create httpd config file
561251881Speter    fp = open(self.httpd_config, 'w')
562251881Speter
563251881Speter    # Limit the number of threads (default = 64)
564362181Sdim    if not use_http2:
565362181Sdim      fp.write('<IfModule mpm_winnt.c>\n')
566362181Sdim      fp.write('ThreadsPerChild 16\n')
567362181Sdim      fp.write('</IfModule>\n')
568251881Speter
569251881Speter    # Global Environment
570251881Speter    fp.write('ServerRoot   ' + self._quote(self.root) + '\n')
571251881Speter    fp.write('DocumentRoot ' + self._quote(self.root) + '\n')
572251881Speter    fp.write('ServerName   localhost\n')
573251881Speter    fp.write('PidFile      pid\n')
574251881Speter    fp.write('ErrorLog     log\n')
575251881Speter    fp.write('Listen       ' + str(self.httpd_port) + '\n')
576251881Speter
577251881Speter    if not no_log:
578251881Speter      fp.write('LogFormat    "%h %l %u %t \\"%r\\" %>s %b" common\n')
579251881Speter      fp.write('Customlog    log common\n')
580251881Speter      fp.write('LogLevel     Debug\n')
581251881Speter    else:
582251881Speter      fp.write('LogLevel     Crit\n')
583251881Speter
584251881Speter    # Write LoadModule for minimal system module
585362181Sdim    if use_ssl:
586362181Sdim      fp.write(self._sys_module('ssl_module', 'mod_ssl.so'))
587362181Sdim    if use_http2:
588362181Sdim      fp.write(self._sys_module('http2_module', 'mod_http2.so'))
589362181Sdim    if use_mod_deflate:
590362181Sdim      fp.write(self._sys_module('deflate_module', 'mod_deflate.so'))
591251881Speter    fp.write(self._sys_module('dav_module', 'mod_dav.so'))
592251881Speter    if self.httpd_ver >= 2.3:
593251881Speter      fp.write(self._sys_module('access_compat_module', 'mod_access_compat.so'))
594251881Speter      fp.write(self._sys_module('authz_core_module', 'mod_authz_core.so'))
595251881Speter      fp.write(self._sys_module('authz_user_module', 'mod_authz_user.so'))
596251881Speter      fp.write(self._sys_module('authn_core_module', 'mod_authn_core.so'))
597251881Speter    if self.httpd_ver >= 2.2:
598251881Speter      fp.write(self._sys_module('auth_basic_module', 'mod_auth_basic.so'))
599251881Speter      fp.write(self._sys_module('authn_file_module', 'mod_authn_file.so'))
600286506Speter      fp.write(self._sys_module('authz_groupfile_module', 'mod_authz_groupfile.so'))
601286506Speter      fp.write(self._sys_module('authz_host_module', 'mod_authz_host.so'))
602251881Speter    else:
603251881Speter      fp.write(self._sys_module('auth_module', 'mod_auth.so'))
604251881Speter    fp.write(self._sys_module('alias_module', 'mod_alias.so'))
605251881Speter    fp.write(self._sys_module('mime_module', 'mod_mime.so'))
606251881Speter    fp.write(self._sys_module('log_config_module', 'mod_log_config.so'))
607251881Speter
608251881Speter    # Write LoadModule for Subversion modules
609251881Speter    fp.write(self._svn_module('dav_svn_module', 'mod_dav_svn.so'))
610251881Speter    fp.write(self._svn_module('authz_svn_module', 'mod_authz_svn.so'))
611251881Speter
612251881Speter    # And for mod_dontdothat
613251881Speter    fp.write(self._svn_module('dontdothat_module', 'mod_dontdothat.so'))
614251881Speter
615362181Sdim    if use_ssl:
616362181Sdim      fp.write('SSLEngine on\n')
617362181Sdim      fp.write('SSLProtocol All -SSLv2 -SSLv3\n')
618362181Sdim      fp.write('SSLCertificateFile %s\n' % self._quote(self.certfile))
619362181Sdim      fp.write('SSLCertificateKeyFile %s\n' % self._quote(self.certkeyfile))
620362181Sdim
621362181Sdim    if use_ssl and use_http2:
622362181Sdim      fp.write('Protocols h2 http/1.1\n')
623362181Sdim    elif use_http2:
624362181Sdim      fp.write('Protocols h2c http/1.1\n')
625362181Sdim      fp.write('H2Direct on\n')
626362181Sdim
627362181Sdim    if use_mod_deflate:
628362181Sdim      fp.write('SetOutputFilter DEFLATE\n')
629362181Sdim
630251881Speter    # Don't handle .htaccess, symlinks, etc.
631251881Speter    fp.write('<Directory />\n')
632251881Speter    fp.write('AllowOverride None\n')
633251881Speter    fp.write('Options None\n')
634251881Speter    fp.write('</Directory>\n\n')
635251881Speter
636251881Speter    # Define two locations for repositories
637251881Speter    fp.write(self._svn_repo('repositories'))
638251881Speter    fp.write(self._svn_repo('local_tmp'))
639286506Speter    fp.write(self._svn_authz_repo())
640251881Speter
641251881Speter    # And two redirects for the redirect tests
642251881Speter    fp.write('RedirectMatch permanent ^/svn-test-work/repositories/'
643251881Speter             'REDIRECT-PERM-(.*)$ /svn-test-work/repositories/$1\n')
644251881Speter    fp.write('RedirectMatch           ^/svn-test-work/repositories/'
645251881Speter             'REDIRECT-TEMP-(.*)$ /svn-test-work/repositories/$1\n')
646251881Speter
647251881Speter    fp.write('TypesConfig     ' + self._quote(self.httpd_mime_types) + '\n')
648251881Speter    fp.write('HostNameLookups Off\n')
649251881Speter
650251881Speter    fp.close()
651251881Speter
652251881Speter  def __del__(self):
653251881Speter    "Stop httpd when the object is deleted"
654251881Speter    self.stop()
655251881Speter
656251881Speter  def _quote(self, arg):
657251881Speter    if ' ' in arg:
658251881Speter      return '"' + arg + '"'
659251881Speter    else:
660251881Speter      return arg
661251881Speter
662251881Speter  def _create_users_file(self):
663251881Speter    "Create users file"
664251881Speter    htpasswd = os.path.join(self.httpd_dir, 'bin', 'htpasswd.exe')
665251881Speter    # Create the cheapest to compare password form for our testsuite
666251881Speter    os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bcp', self.httpd_users,
667251881Speter                                    'jrandom', 'rayjandom'])
668251881Speter    os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp',  self.httpd_users,
669251881Speter                                    'jconstant', 'rayjandom'])
670286506Speter    os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp',  self.httpd_users,
671362181Sdim                                    '__dumpster__', '__loadster__'])
672362181Sdim    os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp',  self.httpd_users,
673286506Speter                                    'JRANDOM', 'rayjandom'])
674286506Speter    os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp',  self.httpd_users,
675286506Speter                                    'JCONSTANT', 'rayjandom'])
676251881Speter
677286506Speter  def _create_groups_file(self):
678286506Speter    "Create groups for mod_authz_svn tests"
679286506Speter    fp = open(self.httpd_groups, 'w')
680286506Speter    fp.write('random: jrandom\n')
681286506Speter    fp.write('constant: jconstant\n')
682286506Speter    fp.close()
683286506Speter
684251881Speter  def _create_mime_types_file(self):
685251881Speter    "Create empty mime.types file"
686251881Speter    fp = open(self.httpd_mime_types, 'w')
687251881Speter    fp.close()
688251881Speter
689251881Speter  def _create_dontdothat_file(self):
690251881Speter    "Create empty mime.types file"
691253734Speter    # If the tests have not previously been run or were cleaned
692253734Speter    # up, then 'svn-test-work' does not exist yet.
693253734Speter    parent_dir = os.path.dirname(self.dontdothat_file)
694253734Speter    if not os.path.exists(parent_dir):
695253734Speter      os.makedirs(parent_dir)
696253734Speter
697251881Speter    fp = open(self.dontdothat_file, 'w')
698251881Speter    fp.write('[recursive-actions]\n')
699251881Speter    fp.write('/ = deny\n')
700251881Speter    fp.close()
701251881Speter
702362181Sdim  def _create_cert_files(self):
703362181Sdim    "Create certificate files"
704362181Sdim    # The unix build uses certificates encoded in davautocheck.sh
705362181Sdim    # Let's just read them from there
706362181Sdim
707362181Sdim    sh_path = os.path.join(self.abs_srcdir, 'subversion', 'tests', 'cmdline',
708362181Sdim                           'davautocheck.sh')
709362181Sdim    sh = open(sh_path).readlines()
710362181Sdim
711362181Sdim    def cert_extract(lines, what):
712362181Sdim      r = []
713362181Sdim      pattern = r'cat\s*\>\s*' + re.escape(what) + r'\s*\<\<([A-Z_a-z0-9]+)'
714362181Sdim      exit_marker = None
715362181Sdim      for i in lines:
716362181Sdim        if exit_marker:
717362181Sdim          if i.startswith(exit_marker):
718362181Sdim            return r
719362181Sdim          r.append(i)
720362181Sdim        else:
721362181Sdim          m = re.match(pattern, i)
722362181Sdim          if m:
723362181Sdim            exit_marker = m.groups(1)
724362181Sdim
725362181Sdim    cert_file = cert_extract(sh, '"$SSL_CERTIFICATE_FILE"')
726362181Sdim    cert_key = cert_extract(sh, '"$SSL_CERTIFICATE_KEY_FILE"')
727362181Sdim    open(self.certfile, 'w').write(''.join(cert_file))
728362181Sdim    open(self.certkeyfile, 'w').write(''.join(cert_key))
729362181Sdim
730251881Speter  def _sys_module(self, name, path):
731251881Speter    full_path = os.path.join(self.httpd_dir, 'modules', path)
732251881Speter    return 'LoadModule ' + name + " " + self._quote(full_path) + '\n'
733251881Speter
734251881Speter  def _svn_module(self, name, path):
735289180Speter    full_path = os.path.join(self.abs_builddir, path)
736251881Speter    return 'LoadModule ' + name + ' ' + self._quote(full_path) + '\n'
737251881Speter
738251881Speter  def _svn_repo(self, name):
739251881Speter    path = os.path.join(self.abs_builddir,
740251881Speter                        CMDLINE_TEST_SCRIPT_NATIVE_PATH,
741251881Speter                        'svn-test-work', name)
742251881Speter    location = '/svn-test-work/' + name
743251881Speter    ddt_location = '/ddt-test-work/' + name
744251881Speter    return \
745251881Speter      '<Location ' + location + '>\n' \
746251881Speter      '  DAV             svn\n' \
747251881Speter      '  SVNParentPath   ' + self._quote(path) + '\n' \
748251881Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
749251881Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
750251881Speter      '  SVNAllowBulkUpdates ' + self.bulkupdates_option + '\n' \
751251881Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
752251881Speter      '  AuthType        Basic\n' \
753251881Speter      '  AuthName        "Subversion Repository"\n' \
754251881Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
755251881Speter      '  Require         valid-user\n' \
756251881Speter      '</Location>\n' \
757251881Speter      '<Location ' + ddt_location + '>\n' \
758251881Speter      '  DAV             svn\n' \
759251881Speter      '  SVNParentPath   ' + self._quote(path) + '\n' \
760251881Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
761251881Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
762251881Speter      '  SVNAllowBulkUpdates ' + self.bulkupdates_option + '\n' \
763251881Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
764251881Speter      '  AuthType        Basic\n' \
765251881Speter      '  AuthName        "Subversion Repository"\n' \
766251881Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
767251881Speter      '  Require         valid-user\n' \
768251881Speter      '  DontDoThatConfigFile ' + self._quote(self.dontdothat_file) + '\n' \
769251881Speter      '</Location>\n'
770251881Speter
771286506Speter  def _svn_authz_repo(self):
772286506Speter    local_tmp = os.path.join(self.abs_builddir,
773286506Speter                             CMDLINE_TEST_SCRIPT_NATIVE_PATH,
774286506Speter                             'svn-test-work', 'local_tmp')
775286506Speter    return \
776286506Speter      '<Location /authz-test-work/anon>' + '\n' \
777286506Speter      '  DAV               svn' + '\n' \
778286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
779286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
780286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
781286506Speter      '  SVNListParentPath On' + '\n' \
782286506Speter      '  <IfModule mod_authz_core.c>' + '\n' \
783286506Speter      '    Require all granted' + '\n' \
784286506Speter      '  </IfModule>' + '\n' \
785286506Speter      '  <IfModule !mod_authz_core.c>' + '\n' \
786286506Speter      '    Allow from all' + '\n' \
787286506Speter      '  </IfModule>' + '\n' \
788286506Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
789286506Speter      '</Location>' + '\n' \
790286506Speter      '<Location /authz-test-work/mixed>' + '\n' \
791286506Speter      '  DAV               svn' + '\n' \
792286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
793286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
794286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
795286506Speter      '  SVNListParentPath On' + '\n' \
796286506Speter      '  AuthType          Basic' + '\n' \
797286506Speter      '  AuthName          "Subversion Repository"' + '\n' \
798286506Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
799286506Speter      '  Require           valid-user' + '\n' \
800286506Speter      '  Satisfy Any' + '\n' \
801286506Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
802286506Speter      '</Location>' + '\n' \
803286506Speter      '<Location /authz-test-work/mixed-noauthwhenanon>' + '\n' \
804286506Speter      '  DAV               svn' + '\n' \
805286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
806286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
807286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
808286506Speter      '  SVNListParentPath On' + '\n' \
809286506Speter      '  AuthType          Basic' + '\n' \
810286506Speter      '  AuthName          "Subversion Repository"' + '\n' \
811286506Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
812286506Speter      '  Require           valid-user' + '\n' \
813286506Speter      '  AuthzSVNNoAuthWhenAnonymousAllowed On' + '\n' \
814286506Speter      '  SVNPathAuthz On' + '\n' \
815286506Speter      '</Location>' + '\n' \
816286506Speter      '<Location /authz-test-work/authn>' + '\n' \
817286506Speter      '  DAV               svn' + '\n' \
818286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
819286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
820286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
821286506Speter      '  SVNListParentPath On' + '\n' \
822286506Speter      '  AuthType          Basic' + '\n' \
823286506Speter      '  AuthName          "Subversion Repository"' + '\n' \
824286506Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
825286506Speter      '  Require           valid-user' + '\n' \
826286506Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
827286506Speter      '</Location>' + '\n' \
828286506Speter      '<Location /authz-test-work/authn-anonoff>' + '\n' \
829286506Speter      '  DAV               svn' + '\n' \
830286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
831286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
832286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
833286506Speter      '  SVNListParentPath On' + '\n' \
834286506Speter      '  AuthType          Basic' + '\n' \
835286506Speter      '  AuthName          "Subversion Repository"' + '\n' \
836286506Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
837286506Speter      '  Require           valid-user' + '\n' \
838286506Speter      '  AuthzSVNAnonymous Off' + '\n' \
839286506Speter      '  SVNPathAuthz On' + '\n' \
840286506Speter      '</Location>' + '\n' \
841286506Speter      '<Location /authz-test-work/authn-lcuser>' + '\n' \
842286506Speter      '  DAV               svn' + '\n' \
843286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
844286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
845286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
846286506Speter      '  SVNListParentPath On' + '\n' \
847286506Speter      '  AuthType          Basic' + '\n' \
848286506Speter      '  AuthName          "Subversion Repository"' + '\n' \
849286506Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
850286506Speter      '  Require           valid-user' + '\n' \
851286506Speter      '  AuthzForceUsernameCase Lower' + '\n' \
852286506Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
853286506Speter      '</Location>' + '\n' \
854286506Speter      '<Location /authz-test-work/authn-lcuser>' + '\n' \
855286506Speter      '  DAV               svn' + '\n' \
856286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
857286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
858286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
859286506Speter      '  SVNListParentPath On' + '\n' \
860286506Speter      '  AuthType          Basic' + '\n' \
861286506Speter      '  AuthName          "Subversion Repository"' + '\n' \
862286506Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
863286506Speter      '  Require           valid-user' + '\n' \
864286506Speter      '  AuthzForceUsernameCase Lower' + '\n' \
865286506Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
866286506Speter      '</Location>' + '\n' \
867286506Speter      '<Location /authz-test-work/authn-group>' + '\n' \
868286506Speter      '  DAV               svn' + '\n' \
869286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
870286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
871286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
872286506Speter      '  SVNListParentPath On' + '\n' \
873286506Speter      '  AuthType          Basic' + '\n' \
874286506Speter      '  AuthName          "Subversion Repository"' + '\n' \
875286506Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
876286506Speter      '  AuthGroupFile    ' + self._quote(self.httpd_groups) + '\n' \
877286506Speter      '  Require           group random' + '\n' \
878286506Speter      '  AuthzSVNAuthoritative Off' + '\n' \
879286506Speter      '  SVNPathAuthz On' + '\n' \
880286506Speter      '</Location>' + '\n' \
881286506Speter      '<IfModule mod_authz_core.c>' + '\n' \
882286506Speter      '<Location /authz-test-work/sallrany>' + '\n' \
883286506Speter      '  DAV               svn' + '\n' \
884286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
885286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
886286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
887286506Speter      '  SVNListParentPath On' + '\n' \
888286506Speter      '  AuthType          Basic' + '\n' \
889286506Speter      '  AuthName          "Subversion Repository"' + '\n' \
890286506Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
891286506Speter      '  AuthzSendForbiddenOnFailure On' + '\n' \
892286506Speter      '  Satisfy All' + '\n' \
893286506Speter      '  <RequireAny>' + '\n' \
894286506Speter      '    Require valid-user' + '\n' \
895286506Speter      '    Require expr req(\'ALLOW\') == \'1\'' + '\n' \
896286506Speter      '  </RequireAny>' + '\n' \
897286506Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
898286506Speter      '</Location>' + '\n' \
899286506Speter      '<Location /authz-test-work/sallrall>'+ '\n' \
900286506Speter      '  DAV               svn' + '\n' \
901286506Speter      '  SVNParentPath     ' + local_tmp + '\n' \
902286506Speter      '  AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \
903286506Speter      '  SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \
904286506Speter      '  SVNListParentPath On' + '\n' \
905286506Speter      '  AuthType          Basic' + '\n' \
906286506Speter      '  AuthName          "Subversion Repository"' + '\n' \
907286506Speter      '  AuthUserFile    ' + self._quote(self.httpd_users) + '\n' \
908286506Speter      '  AuthzSendForbiddenOnFailure On' + '\n' \
909286506Speter      '  Satisfy All' + '\n' \
910286506Speter      '  <RequireAll>' + '\n' \
911362181Sdim      '    Require valid-user' + '\n' \
912362181Sdim      '    Require expr req(\'ALLOW\') == \'1\'' + '\n' \
913362181Sdim      '  </RequireAll>' + '\n' \
914286506Speter      '  SVNPathAuthz ' + self.path_authz_option + '\n' \
915286506Speter      '</Location>' + '\n' \
916286506Speter      '</IfModule>' + '\n' \
917286506Speter
918251881Speter  def start(self):
919251881Speter    if self.service:
920251881Speter      self._start_service()
921251881Speter    else:
922251881Speter      self._start_daemon()
923251881Speter
924362181Sdim    # Avoid output from starting and preparing between test results
925362181Sdim    sys.stderr.flush()
926362181Sdim    sys.stdout.flush()
927362181Sdim
928251881Speter  def stop(self):
929251881Speter    if self.service:
930251881Speter      self._stop_service()
931251881Speter    else:
932251881Speter      self._stop_daemon()
933251881Speter
934251881Speter  def _start_service(self):
935251881Speter    "Install and start HTTPD service"
936251881Speter    print('Installing service %s' % self.service_name)
937251881Speter    os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'install'])
938251881Speter    print('Starting service %s' % self.service_name)
939251881Speter    os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'start'])
940251881Speter
941251881Speter  def _stop_service(self):
942251881Speter    "Stop and uninstall HTTPD service"
943251881Speter    os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'stop'])
944251881Speter    os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'uninstall'])
945251881Speter
946251881Speter  def _start_daemon(self):
947251881Speter    "Start HTTPD as daemon"
948251881Speter    print('Starting httpd as daemon')
949251881Speter    print(self.httpd_args)
950289180Speter    self.proc = subprocess.Popen([self.path] + self.httpd_args[1:])
951251881Speter
952251881Speter  def _stop_daemon(self):
953251881Speter    "Stop the HTTPD daemon"
954289180Speter    if self.proc is not None:
955251881Speter      try:
956251881Speter        print('Stopping %s' % self.name)
957289180Speter        self.proc.poll();
958289180Speter        if self.proc.returncode is None:
959289180Speter          self.proc.kill();
960251881Speter        return
961289180Speter      except AttributeError:
962251881Speter        pass
963251881Speter    print('Httpd.stop_daemon not implemented')
964251881Speter
965362181Sdimclass Memcached:
966362181Sdim  "Run memcached for tests"
967362181Sdim  def __init__(self, abs_memcached_dir, memcached_server):
968362181Sdim    self.name = 'memcached.exe'
969362181Sdim
970362181Sdim    self.memcached_host, self.memcached_port = memcached_server.split(':')
971362181Sdim    self.memcached_dir = abs_memcached_dir
972362181Sdim
973362181Sdim    self.proc = None
974362181Sdim    self.path = os.path.join(self.memcached_dir, self.name)
975362181Sdim
976362181Sdim    self.memcached_args = [
977362181Sdim                            self.name,
978362181Sdim                            '-p', self.memcached_port,
979362181Sdim                            '-l', self.memcached_host
980362181Sdim                          ]
981362181Sdim
982362181Sdim  def __del__(self):
983362181Sdim    "Stop memcached when the object is deleted"
984362181Sdim    self.stop()
985362181Sdim
986362181Sdim  def start(self):
987362181Sdim    "Start memcached as daemon"
988362181Sdim    print('Starting %s as daemon' % self.name)
989362181Sdim    print(self.memcached_args)
990362181Sdim    self.proc = subprocess.Popen([self.path] + self.memcached_args)
991362181Sdim
992362181Sdim  def stop(self):
993362181Sdim    "Stop memcached"
994362181Sdim    if self.proc is not None:
995362181Sdim      try:
996362181Sdim        print('Stopping %s' % self.name)
997362181Sdim        self.proc.poll();
998362181Sdim        if self.proc.returncode is None:
999362181Sdim          self.proc.kill();
1000362181Sdim        return
1001362181Sdim      except AttributeError:
1002362181Sdim        pass
1003362181Sdim
1004251881Speter# Move the binaries to the test directory
1005289180Spetercreate_target_dir(abs_builddir)
1006251881Speterlocate_libs()
1007251881Speterif create_dirs:
1008289180Speter  for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL):
1009289180Speter    if isinstance(i, gen_base.TargetExe):
1010289180Speter      src = os.path.join(abs_objdir, i.filename)
1011251881Speter
1012289180Speter      if os.path.isfile(src):
1013289180Speter        dst = os.path.join(abs_builddir, i.filename)
1014289180Speter        create_target_dir(os.path.dirname(dst))
1015289180Speter        copy_changed_file(src, dst)
1016289180Speter
1017251881Speter# Create the base directory for Python tests
1018251881Spetercreate_target_dir(CMDLINE_TEST_SCRIPT_NATIVE_PATH)
1019251881Speter
1020251881Speter# Ensure the tests directory is correctly cased
1021251881Speterabs_builddir = fix_case(abs_builddir)
1022251881Speter
1023362181Sdimfailed = None
1024251881Speterdaemon = None
1025362181Sdimmemcached = None
1026251881Speter# Run the tests
1027251881Speter
1028251881Speter# No need to start any servers if we are only listing the tests.
1029251881Speterif not list_tests:
1030362181Sdim  if run_memcached:
1031362181Sdim    memcached = Memcached(memcached_dir, memcached_server)
1032362181Sdim    memcached.start()
1033362181Sdim
1034251881Speter  if run_svnserve:
1035251881Speter    daemon = Svnserve(svnserve_args, objdir, abs_objdir, abs_builddir)
1036251881Speter
1037251881Speter  if run_httpd:
1038362181Sdim    daemon = Httpd(abs_httpd_dir, abs_objdir, abs_builddir, abs_srcdir,
1039362181Sdim                   httpd_port, httpd_service, use_ssl, use_http2,
1040362181Sdim                   use_mod_deflate, httpd_no_log, advertise_httpv2,
1041362181Sdim                   http_short_circuit, http_bulk_updates)
1042251881Speter
1043362181Sdim    if use_ssl and not ssl_cert:
1044362181Sdim      ssl_cert = daemon.certfile
1045362181Sdim
1046251881Speter  # Start service daemon, if any
1047251881Speter  if daemon:
1048251881Speter    daemon.start()
1049251881Speter
1050251881Speter# Find the full path and filename of any test that is specified just by
1051251881Speter# its base name.
1052251881Speterif len(tests_to_run) != 0:
1053251881Speter  tests = []
1054251881Speter  for t in tests_to_run:
1055251881Speter    tns = None
1056251881Speter    if '#' in t:
1057251881Speter      t, tns = t.split('#')
1058251881Speter
1059251881Speter    test = [x for x in all_tests if x.split('/')[-1] == t]
1060251881Speter    if not test and not (t.endswith('-test.exe') or t.endswith('_tests.py')):
1061251881Speter      # The lengths of '-test.exe' and of '_tests.py' are both 9.
1062251881Speter      test = [x for x in all_tests if x.split('/')[-1][:-9] == t]
1063251881Speter
1064251881Speter    if not test:
1065251881Speter      print("Skipping test '%s', test not found." % t)
1066251881Speter    elif tns:
1067251881Speter      tests.append('%s#%s' % (test[0], tns))
1068251881Speter    else:
1069251881Speter      tests.extend(test)
1070251881Speter
1071251881Speter  tests_to_run = tests
1072251881Speterelse:
1073251881Speter  tests_to_run = all_tests
1074251881Speter
1075251881Speter
1076251881Speterif list_tests:
1077251881Speter  print('Listing %s configuration on %s' % (objdir, repo_loc))
1078251881Speterelse:
1079251881Speter  print('Testing %s configuration on %s' % (objdir, repo_loc))
1080251881Spetersys.path.insert(0, os.path.join(abs_srcdir, 'build'))
1081251881Speter
1082289180Speterif not test_javahl and not test_swig:
1083251881Speter  import run_tests
1084251881Speter  if log_to_stdout:
1085251881Speter    log_file = None
1086251881Speter    fail_log_file = None
1087251881Speter  else:
1088251881Speter    log_file = os.path.join(abs_builddir, log)
1089251881Speter    fail_log_file = os.path.join(abs_builddir, faillog)
1090251881Speter
1091286506Speter  if run_httpd:
1092289180Speter    httpd_version = gen_obj._libraries['httpd'].version
1093286506Speter  else:
1094286506Speter    httpd_version = None
1095289180Speter
1096289180Speter  opts, args = run_tests.create_parser().parse_args([])
1097289180Speter  opts.url = base_url
1098289180Speter  opts.fs_type = fs_type
1099362181Sdim  opts.global_scheduler = global_scheduler
1100289180Speter  opts.http_library = 'serf'
1101289180Speter  opts.server_minor_version = server_minor_version
1102289180Speter  opts.cleanup = cleanup
1103289180Speter  opts.enable_sasl = enable_sasl
1104289180Speter  opts.parallel = parallel
1105289180Speter  opts.config_file = config_file
1106289180Speter  opts.fsfs_sharding = fsfs_sharding
1107289180Speter  opts.fsfs_packing = fsfs_packing
1108289180Speter  opts.list_tests = list_tests
1109289180Speter  opts.svn_bin = svn_bin
1110289180Speter  opts.mode_filter = mode_filter
1111289180Speter  opts.milestone_filter = milestone_filter
1112289180Speter  opts.httpd_version = httpd_version
1113289180Speter  opts.set_log_level = log_level
1114289180Speter  opts.ssl_cert = ssl_cert
1115362181Sdim  opts.exclusive_wc_locks = exclusive_wc_locks
1116362181Sdim  opts.memcached_server = memcached_server
1117362181Sdim  opts.skip_c_tests = skip_c_tests
1118362181Sdim  opts.dump_load_cross_check = dump_load_cross_check
1119362181Sdim  opts.fsfs_compression = fsfs_compression
1120362181Sdim  opts.fsfs_dir_deltification = fsfs_dir_deltification
1121251881Speter  th = run_tests.TestHarness(abs_srcdir, abs_builddir,
1122289180Speter                             log_file, fail_log_file, opts)
1123251881Speter  old_cwd = os.getcwd()
1124251881Speter  try:
1125251881Speter    os.chdir(abs_builddir)
1126251881Speter    failed = th.run(tests_to_run)
1127251881Speter  except:
1128251881Speter    os.chdir(old_cwd)
1129251881Speter    raise
1130251881Speter  else:
1131251881Speter    os.chdir(old_cwd)
1132289180Speterelif test_javahl:
1133251881Speter  failed = False
1134251881Speter
1135289180Speter  java_exe = None
1136251881Speter
1137289180Speter  for path in os.environ["PATH"].split(os.pathsep):
1138289180Speter    if os.path.isfile(os.path.join(path, 'java.exe')):
1139289180Speter      java_exe = os.path.join(path, 'java.exe')
1140289180Speter      break
1141289180Speter
1142289180Speter  if not java_exe and 'java_sdk' in gen_obj._libraries:
1143289180Speter    jdk = gen_obj._libraries['java_sdk']
1144289180Speter
1145289180Speter    if os.path.isfile(os.path.join(jdk.lib_dir, '../bin/java.exe')):
1146289180Speter      java_exe = os.path.join(jdk.lib_dir, '../bin/java.exe')
1147289180Speter
1148289180Speter  if not java_exe:
1149289180Speter    print('Java not found. Skipping Java tests')
1150289180Speter  else:
1151289180Speter    args = (os.path.abspath(java_exe),)
1152289180Speter    if (objdir == 'Debug'):
1153289180Speter      args = args + ('-Xcheck:jni',)
1154289180Speter
1155362181Sdim    if cleanup:
1156362181Sdim      args = args + ('-Dtest.cleanup=1',)
1157362181Sdim
1158289180Speter    args = args + (
1159289180Speter            '-Dtest.rootdir=' + os.path.join(abs_builddir, 'javahl'),
1160289180Speter            '-Dtest.srcdir=' + os.path.join(abs_srcdir,
1161289180Speter                                            'subversion/bindings/javahl'),
1162289180Speter            '-Dtest.rooturl=',
1163289180Speter            '-Dtest.fstype=' + fs_type ,
1164289180Speter            '-Dtest.tests=',
1165289180Speter
1166289180Speter            '-Djava.library.path='
1167289180Speter                      + os.path.join(abs_objdir,
1168289180Speter                                     'subversion/bindings/javahl/native'),
1169289180Speter            '-classpath',
1170289180Speter            os.path.join(abs_srcdir, 'subversion/bindings/javahl/classes') +';' +
1171289180Speter              gen_obj.junit_path
1172289180Speter           )
1173289180Speter
1174289180Speter    sys.stderr.flush()
1175289180Speter    print('Running org.apache.subversion tests:')
1176289180Speter    sys.stdout.flush()
1177289180Speter
1178289180Speter    r = subprocess.call(args + tuple(['org.apache.subversion.javahl.RunTests']))
1179289180Speter    sys.stdout.flush()
1180289180Speter    sys.stderr.flush()
1181289180Speter    if (r != 0):
1182289180Speter      print('[Test runner reported failure]')
1183289180Speter      failed = True
1184289180Speter
1185289180Speter    print('Running org.tigris.subversion tests:')
1186289180Speter    sys.stdout.flush()
1187289180Speter    r = subprocess.call(args + tuple(['org.tigris.subversion.javahl.RunTests']))
1188289180Speter    sys.stdout.flush()
1189289180Speter    sys.stderr.flush()
1190289180Speter    if (r != 0):
1191289180Speter      print('[Test runner reported failure]')
1192289180Speter      failed = True
1193289180Speterelif test_swig == 'perl':
1194289180Speter  failed = False
1195289180Speter  swig_dir = os.path.join(abs_builddir, 'swig')
1196289180Speter  swig_pl_dir = os.path.join(swig_dir, 'p5lib')
1197289180Speter  swig_pl_svn = os.path.join(swig_pl_dir, 'SVN')
1198289180Speter  swig_pl_auto_svn = os.path.join(swig_pl_dir, 'auto', 'SVN')
1199289180Speter
1200289180Speter  create_target_dir(swig_pl_svn)
1201289180Speter
1202289180Speter  for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL):
1203289180Speter    if isinstance(i, gen_base.TargetSWIG) and i.lang == 'perl':
1204289180Speter      mod_dir = os.path.join(swig_pl_auto_svn, '_' + i.name[5:].capitalize())
1205289180Speter      create_target_dir(mod_dir)
1206289180Speter      copy_changed_file(os.path.join(abs_objdir, i.filename), to_dir=mod_dir)
1207289180Speter
1208289180Speter    elif isinstance(i, gen_base.TargetSWIGLib) and i.lang == 'perl':
1209289180Speter      copy_changed_file(os.path.join(abs_objdir, i.filename),
1210289180Speter                        to_dir=abs_builddir)
1211289180Speter
1212289180Speter  pm_src = os.path.join(abs_srcdir, 'subversion', 'bindings', 'swig', 'perl',
1213289180Speter                        'native')
1214289180Speter
1215289180Speter  tests = []
1216289180Speter
1217289180Speter  for root, dirs, files in os.walk(pm_src):
1218289180Speter    for name in files:
1219289180Speter      if name.endswith('.pm'):
1220289180Speter        fn = os.path.join(root, name)
1221289180Speter        copy_changed_file(fn, to_dir=swig_pl_svn)
1222289180Speter      elif name.endswith('.t'):
1223289180Speter        tests.append(os.path.relpath(os.path.join(root, name), pm_src))
1224289180Speter
1225289180Speter  perl5lib = swig_pl_dir
1226289180Speter  if 'PERL5LIB' in os.environ:
1227289180Speter    perl5lib += os.pathsep + os.environ['PERL5LIB']
1228289180Speter
1229289180Speter  perl_exe = 'perl.exe'
1230289180Speter
1231289180Speter  print('-- Running Swig Perl tests --')
1232251881Speter  sys.stdout.flush()
1233289180Speter  old_cwd = os.getcwd()
1234289180Speter  try:
1235289180Speter    os.chdir(pm_src)
1236251881Speter
1237289180Speter    os.environ['PERL5LIB'] = perl5lib
1238289180Speter    os.environ["SVN_DBG_NO_ABORT_ON_ERROR_LEAK"] = 'YES'
1239289180Speter
1240289180Speter    r = subprocess.call([
1241289180Speter              perl_exe,
1242289180Speter              '-MExtUtils::Command::MM',
1243289180Speter              '-e', 'test_harness()'
1244289180Speter              ] + tests)
1245289180Speter  finally:
1246289180Speter    os.chdir(old_cwd)
1247289180Speter
1248251881Speter  if (r != 0):
1249251881Speter    print('[Test runner reported failure]')
1250251881Speter    failed = True
1251289180Speterelif test_swig == 'python':
1252289180Speter  failed = False
1253289180Speter  swig_dir = os.path.join(abs_builddir, 'swig')
1254289180Speter  swig_py_dir = os.path.join(swig_dir, 'pylib')
1255289180Speter  swig_py_libsvn = os.path.join(swig_py_dir, 'libsvn')
1256289180Speter  swig_py_svn = os.path.join(swig_py_dir, 'svn')
1257251881Speter
1258289180Speter  create_target_dir(swig_py_libsvn)
1259289180Speter  create_target_dir(swig_py_svn)
1260289180Speter
1261289180Speter  for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL):
1262289180Speter    if (isinstance(i, gen_base.TargetSWIG)
1263289180Speter        or isinstance(i, gen_base.TargetSWIGLib)) and i.lang == 'python':
1264289180Speter
1265289180Speter      src = os.path.join(abs_objdir, i.filename)
1266369302Sdim      basename = os.path.basename(src)
1267369302Sdim      if sys.version_info[:2] >= (3, 5) \
1268369302Sdim          and basename.endswith('.pyd') and objdir == 'Debug':
1269369302Sdim        basename = basename[:-4] + '_d.pyd'
1270369302Sdim      copy_changed_file(src, os.path.join(swig_py_libsvn, basename))
1271289180Speter
1272289180Speter  py_src = os.path.join(abs_srcdir, 'subversion', 'bindings', 'swig', 'python')
1273289180Speter
1274289180Speter  for py_file in os.listdir(py_src):
1275289180Speter    if py_file.endswith('.py'):
1276289180Speter      copy_changed_file(os.path.join(py_src, py_file),
1277289180Speter                        to_dir=swig_py_libsvn)
1278289180Speter
1279289180Speter  py_src_svn = os.path.join(py_src, 'svn')
1280289180Speter  for py_file in os.listdir(py_src_svn):
1281289180Speter    if py_file.endswith('.py'):
1282289180Speter      copy_changed_file(os.path.join(py_src_svn, py_file),
1283289180Speter                        to_dir=swig_py_svn)
1284289180Speter
1285289180Speter  print('-- Running Swig Python tests --')
1286251881Speter  sys.stdout.flush()
1287251881Speter
1288289180Speter  pythonpath = swig_py_dir
1289289180Speter  if 'PYTHONPATH' in os.environ:
1290289180Speter    pythonpath += os.pathsep + os.environ['PYTHONPATH']
1291289180Speter
1292369302Sdim  python_exe = sys.executable if objdir != 'Debug' else \
1293369302Sdim               os.path.join(os.path.dirname(sys.executable), 'python_d.exe')
1294289180Speter  old_cwd = os.getcwd()
1295289180Speter  try:
1296289180Speter    os.environ['PYTHONPATH'] = pythonpath
1297289180Speter
1298289180Speter    r = subprocess.call([
1299289180Speter              python_exe,
1300289180Speter              os.path.join(py_src, 'tests', 'run_all.py')
1301289180Speter              ])
1302289180Speter  finally:
1303289180Speter    os.chdir(old_cwd)
1304289180Speter
1305289180Speter    if (r != 0):
1306289180Speter      print('[Test runner reported failure]')
1307289180Speter      failed = True
1308289180Speter
1309289180Speterelif test_swig == 'ruby':
1310289180Speter  failed = False
1311289180Speter
1312289180Speter  if 'ruby' not in gen_obj._libraries:
1313289180Speter    print('Ruby not found. Skipping Ruby tests')
1314289180Speter  else:
1315289180Speter    ruby_lib = gen_obj._libraries['ruby']
1316289180Speter
1317289180Speter    ruby_exe = 'ruby.exe'
1318289180Speter    ruby_subdir = os.path.join('subversion', 'bindings', 'swig', 'ruby')
1319289180Speter    ruby_args = [
1320289180Speter        '-I', os.path.join(abs_srcdir, ruby_subdir),
1321289180Speter        os.path.join(abs_srcdir, ruby_subdir, 'test', 'run-test.rb'),
1322289180Speter        '--verbose'
1323289180Speter      ]
1324289180Speter
1325289180Speter    print('-- Running Swig Ruby tests --')
1326289180Speter    sys.stdout.flush()
1327289180Speter    old_cwd = os.getcwd()
1328289180Speter    try:
1329289180Speter      os.chdir(ruby_subdir)
1330289180Speter
1331289180Speter      os.environ["BUILD_TYPE"] = objdir
1332289180Speter      os.environ["SVN_DBG_NO_ABORT_ON_ERROR_LEAK"] = 'YES'
1333289180Speter      r = subprocess.call([ruby_exe] + ruby_args)
1334289180Speter    finally:
1335289180Speter      os.chdir(old_cwd)
1336289180Speter
1337289180Speter    sys.stdout.flush()
1338289180Speter    sys.stderr.flush()
1339289180Speter    if (r != 0):
1340289180Speter      print('[Test runner reported failure]')
1341289180Speter      failed = True
1342289180Speter
1343362181Sdimelif test_swig:
1344362181Sdim  print('Unknown Swig binding type: ' + str(test_swig))
1345362181Sdim  failed = True
1346362181Sdim
1347251881Speter# Stop service daemon, if any
1348251881Speterif daemon:
1349251881Speter  del daemon
1350251881Speter
1351362181Sdimif memcached:
1352362181Sdim  del memcached
1353362181Sdim
1354251881Speter# Remove the execs again
1355251881Speterfor tgt in copied_execs:
1356251881Speter  try:
1357251881Speter    if os.path.isfile(tgt):
1358251881Speter      if verbose:
1359251881Speter        print("kill: %s" % tgt)
1360251881Speter      os.unlink(tgt)
1361251881Speter  except:
1362251881Speter    traceback.print_exc(file=sys.stdout)
1363251881Speter    pass
1364251881Speter
1365251881Speter
1366251881Speterif failed:
1367251881Speter  sys.exit(1)
1368