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