win-tests.py revision 369302
1# 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20# 21""" 22Driver for running the tests on Windows. 23 24For a list of options, run this script with the --help option. 25""" 26 27# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.14.x/win-tests.py $ 28# $LastChangedRevision: 1884665 $ 29 30import os, sys, subprocess 31import filecmp 32import shutil 33import traceback 34import logging 35import re 36try: 37 # Python >=3.0 38 import configparser 39except ImportError: 40 # Python <3.0 41 import ConfigParser as configparser 42import string 43import random 44 45import getopt 46try: 47 my_getopt = getopt.gnu_getopt 48except AttributeError: 49 my_getopt = getopt.getopt 50 51def _usage_exit(): 52 "print usage, exit the script" 53 54 print("Driver for running the tests on Windows.") 55 print("Usage: python win-tests.py [option] [test-path]") 56 print("") 57 print("Valid options:") 58 print(" -r, --release : test the Release configuration") 59 print(" -d, --debug : test the Debug configuration (default)") 60 print(" --bin=PATH : use the svn binaries installed in PATH") 61 print(" -u URL, --url=URL : run ra_dav or ra_svn tests against URL;") 62 print(" will start svnserve for ra_svn tests") 63 print(" -v, --verbose : talk more") 64 print(" -f, --fs-type=type : filesystem type to use (fsfs is default)") 65 print(" -c, --cleanup : cleanup after running a test") 66 print(" -t, --test=TEST : Run the TEST test (all is default); use") 67 print(" TEST#n to run a particular test number,") 68 print(" multiples also accepted e.g. '2,4-7'") 69 print(" --log-level=LEVEL : Set log level to LEVEL (E.g. DEBUG)") 70 print(" --log-to-stdout : Write log results to stdout") 71 72 print(" --svnserve-args=list : comma-separated list of arguments for") 73 print(" svnserve") 74 print(" default is '-d,-r,<test-path-root>'") 75 print(" --asp.net-hack : use '_svn' instead of '.svn' for the admin") 76 print(" dir name") 77 print(" --httpd-dir : location where Apache HTTPD is installed") 78 print(" --httpd-port : port for Apache HTTPD; random port number") 79 print(" will be used, if not specified") 80 print(" --httpd-daemon : Run Apache httpd as daemon") 81 print(" --httpd-service : Run Apache httpd as Windows service (default)") 82 print(" --httpd-no-log : Disable httpd logging") 83 print(" --http-short-circuit : Use SVNPathAuthz short_circuit on HTTP server") 84 print(" --disable-http-v2 : Do not advertise support for HTTPv2 on server") 85 print(" --disable-bulk-updates : Disable bulk updates on HTTP server") 86 print(" --ssl-cert : Path to SSL server certificate to trust.") 87 print(" --https : Run Apache httpd with an https setup.") 88 print(" --http2 : Enable http2 in Apache Httpd (>= 2.4.17).") 89 print(" --mod-deflate : Enable mod_deflate in Apache Httpd.") 90 print(" --global-scheduler : Enable global scheduler.") 91 print(" --exclusive-wc-locks : Enable exclusive working copy locks") 92 print(" --memcached-dir=DIR : Run memcached from dir") 93 print(" --memcached-server= : Enable usage of the specified memcached server") 94 print(" <url:port>") 95 print(" --skip-c-tests : Skip all C tests") 96 print(" --dump-load-cross-check: Run the dump load cross check after every test") 97 98 print(" --javahl : Run the javahl tests instead of the normal tests") 99 print(" --swig=language : Run the swig perl/python/ruby tests instead of") 100 print(" the normal tests") 101 print(" --list : print test doc strings only") 102 print(" --milestone-filter=RE : RE is a regular expression pattern that (when") 103 print(" used with --list) limits the tests listed to") 104 print(" those with an associated issue in the tracker") 105 print(" which has a target milestone that matches RE.") 106 print(" --mode-filter=TYPE : limit tests to expected TYPE = XFAIL, SKIP, PASS,") 107 print(" or 'ALL' (default)") 108 print(" --enable-sasl : enable Cyrus SASL authentication for") 109 print(" svnserve") 110 print(" -p, --parallel : run multiple tests in parallel") 111 print(" --server-minor-version : the minor version of the server being") 112 print(" tested") 113 print(" --config-file : Configuration file for tests") 114 print(" --fsfs-sharding : Specify shard size (for fsfs)") 115 print(" --fsfs-packing : Run 'svnadmin pack' automatically") 116 print(" --fsfs-compression=VAL : Set compression type to VAL (for fsfs)") 117 print(" -q, --quiet : Deprecated; this is the default.") 118 print(" Use --set-log-level instead.") 119 120 sys.exit(0) 121 122CMDLINE_TEST_SCRIPT_PATH = 'subversion/tests/cmdline/' 123CMDLINE_TEST_SCRIPT_NATIVE_PATH = CMDLINE_TEST_SCRIPT_PATH.replace('/', os.sep) 124 125sys.path.insert(0, os.path.join('build', 'generator')) 126sys.path.insert(1, 'build') 127 128import gen_win_dependencies 129import gen_base 130version_header = os.path.join('subversion', 'include', 'svn_version.h') 131cp = configparser.ConfigParser() 132cp.read('gen-make.opts') 133gen_obj = gen_win_dependencies.GenDependenciesBase('build.conf', version_header, 134 cp.items('options')) 135opts, args = my_getopt(sys.argv[1:], 'hrdvqct:pu:f:', 136 ['release', 'debug', 'verbose', 'quiet', 'cleanup', 137 'test=', 'url=', 'svnserve-args=', 'fs-type=', 'asp.net-hack', 138 'httpd-dir=', 'httpd-port=', 'httpd-daemon', 'https', 139 'httpd-server', 'http-short-circuit', 'httpd-no-log', 140 'disable-http-v2', 'disable-bulk-updates', 'help', 141 'fsfs-packing', 'fsfs-sharding=', 'javahl', 'swig=', 142 'list', 'enable-sasl', 'bin=', 'parallel', 'http2', 143 'mod-deflate', 'global-scheduler', 144 'config-file=', 'server-minor-version=', 'log-level=', 145 'log-to-stdout', 'mode-filter=', 'milestone-filter=', 146 'ssl-cert=', 'exclusive-wc-locks', 'memcached-server=', 147 'skip-c-tests', 'dump-load-cross-check', 'memcached-dir=', 148 'fsfs-compression=', 149 ]) 150if len(args) > 1: 151 print('Warning: non-option arguments after the first one will be ignored') 152 153# Interpret the options and set parameters 154base_url, fs_type, verbose, cleanup = None, None, None, None 155global_scheduler = None 156repo_loc = 'local repository.' 157objdir = 'Debug' 158log = 'tests.log' 159faillog = 'fails.log' 160run_svnserve = None 161svnserve_args = None 162run_httpd = None 163httpd_port = None 164httpd_service = None 165httpd_no_log = None 166use_ssl = False 167use_http2 = False 168use_mod_deflate = False 169http_short_circuit = False 170advertise_httpv2 = True 171http_bulk_updates = True 172list_tests = None 173milestone_filter = None 174test_javahl = None 175test_swig = None 176enable_sasl = None 177svn_bin = None 178parallel = None 179fsfs_sharding = None 180fsfs_packing = None 181server_minor_version = None 182config_file = None 183log_to_stdout = None 184mode_filter=None 185tests_to_run = [] 186log_level = None 187ssl_cert = None 188exclusive_wc_locks = None 189run_memcached = None 190memcached_server = None 191memcached_dir = None 192skip_c_tests = None 193dump_load_cross_check = None 194fsfs_compression = None 195fsfs_dir_deltification = None 196 197for opt, val in opts: 198 if opt in ('-h', '--help'): 199 _usage_exit() 200 elif opt in ('-u', '--url'): 201 base_url = val 202 elif opt in ('-f', '--fs-type'): 203 fs_type = val 204 elif opt in ('-v', '--verbose'): 205 verbose = 1 206 log_level = logging.DEBUG 207 elif opt in ('-c', '--cleanup'): 208 cleanup = 1 209 elif opt in ('-t', '--test'): 210 tests_to_run.append(val) 211 elif opt in ['-r', '--release']: 212 objdir = 'Release' 213 elif opt in ['-d', '--debug']: 214 objdir = 'Debug' 215 elif opt == '--svnserve-args': 216 svnserve_args = val.split(',') 217 run_svnserve = 1 218 elif opt == '--asp.net-hack': 219 os.environ['SVN_ASP_DOT_NET_HACK'] = opt 220 elif opt == '--httpd-dir': 221 abs_httpd_dir = os.path.abspath(val) 222 run_httpd = 1 223 elif opt == '--httpd-port': 224 httpd_port = int(val) 225 elif opt == '--httpd-daemon': 226 httpd_service = 0 227 elif opt == '--httpd-service': 228 httpd_service = 1 229 elif opt == '--httpd-no-log': 230 httpd_no_log = 1 231 elif opt == '--https': 232 use_ssl = 1 233 elif opt == '--http2': 234 use_http2 = 1 235 elif opt == '--mod-deflate': 236 use_mod_deflate = 1 237 elif opt == '--http-short-circuit': 238 http_short_circuit = True 239 elif opt == '--disable-http-v2': 240 advertise_httpv2 = False 241 elif opt == '--disable-bulk-updates': 242 http_bulk_updates = False 243 elif opt == '--fsfs-sharding': 244 fsfs_sharding = int(val) 245 elif opt == '--fsfs-packing': 246 fsfs_packing = 1 247 elif opt == '--javahl': 248 test_javahl = 1 249 elif opt == '--global-scheduler': 250 global_scheduler = 1 251 elif opt == '--swig': 252 if val not in ['perl', 'python', 'ruby']: 253 sys.stderr.write('Running \'%s\' swig tests not supported (yet).\n' 254 % (val,)) 255 test_swig = val 256 elif opt == '--list': 257 list_tests = 1 258 elif opt == '--milestone-filter': 259 milestone_filter = val 260 elif opt == '--mode-filter': 261 mode_filter = val 262 elif opt == '--enable-sasl': 263 enable_sasl = 1 264 base_url = "svn://localhost/" 265 elif opt == '--server-minor-version': 266 server_minor_version = int(val) 267 elif opt == '--bin': 268 svn_bin = val 269 elif opt in ('-p', '--parallel'): 270 parallel = 1 271 elif opt in ('--config-file'): 272 config_file = val 273 elif opt == '--log-to-stdout': 274 log_to_stdout = 1 275 elif opt == '--log-level': 276 log_level = getattr(logging, val, None) or int(val) 277 elif opt == '--ssl-cert': 278 ssl_cert = val 279 elif opt == '--exclusive-wc-locks': 280 exclusive_wc_locks = 1 281 elif opt == '--memcached-server': 282 memcached_server = val 283 elif opt == '--skip-c-tests': 284 skip_c_tests = 1 285 elif opt == '--dump-load-cross-check': 286 dump_load_cross_check = 1 287 elif opt == '--memcached-dir': 288 memcached_dir = val 289 run_memcached = 1 290 elif opt == '--fsfs-compression': 291 fsfs_compression = val 292 elif opt == '--fsfs-dir-deltification': 293 fsfs_dir_deltification = val 294 295# Calculate the source and test directory names 296abs_srcdir = os.path.abspath("") 297abs_objdir = os.path.join(abs_srcdir, objdir) 298if len(args) == 0: 299 abs_builddir = abs_objdir 300 create_dirs = 0 301else: 302 abs_builddir = os.path.abspath(args[0]) 303 create_dirs = 1 304 305# Default to fsfs explicitly 306if not fs_type: 307 fs_type = 'fsfs' 308 309if fs_type == 'bdb': 310 all_tests = gen_obj.test_progs + gen_obj.bdb_test_progs \ 311 + gen_obj.scripts + gen_obj.bdb_scripts 312else: 313 all_tests = gen_obj.test_progs + gen_obj.scripts 314 315client_tests = [x for x in all_tests if x.startswith(CMDLINE_TEST_SCRIPT_PATH)] 316 317if run_httpd: 318 if not httpd_port: 319 httpd_port = random.randrange(1024, 30000) 320 if not base_url: 321 if use_ssl: 322 scheme = 'https' 323 else: 324 scheme = 'http' 325 326 base_url = '%s://localhost:%d' % (scheme, httpd_port) 327 328if base_url: 329 repo_loc = 'remote repository ' + base_url + '.' 330 if base_url[:4] == 'http': 331 log = 'dav-tests.log' 332 faillog = 'dav-fails.log' 333 elif base_url[:3] == 'svn': 334 log = 'svn-tests.log' 335 faillog = 'svn-fails.log' 336 run_svnserve = 1 337 else: 338 # Don't know this scheme, but who're we to judge whether it's 339 # correct or not? 340 log = 'url-tests.log' 341 faillog = 'url-fails.log' 342 343# Have to move the executables where the tests expect them to be 344copied_execs = [] # Store copied exec files to avoid the final dir scan 345 346def create_target_dir(dirname): 347 tgt_dir = os.path.join(abs_builddir, dirname) 348 if not os.path.exists(tgt_dir): 349 if verbose: 350 print("mkdir: %s" % tgt_dir) 351 os.makedirs(tgt_dir) 352 353def copy_changed_file(src, tgt=None, to_dir=None, cleanup=True): 354 if not os.path.isfile(src): 355 print('Could not find ' + src) 356 sys.exit(1) 357 358 if to_dir and not tgt: 359 tgt = os.path.join(to_dir, os.path.basename(src)) 360 elif not tgt or (tgt and to_dir): 361 raise RuntimeError("Using 'tgt' *or* 'to_dir' is required" % (tgt,)) 362 elif tgt and os.path.isdir(tgt): 363 raise RuntimeError("'%s' is a directory. Use to_dir=" % (tgt,)) 364 365 if os.path.exists(tgt): 366 assert os.path.isfile(tgt) 367 if filecmp.cmp(src, tgt): 368 if verbose: 369 print("same: %s" % src) 370 print(" and: %s" % tgt) 371 return 0 372 if verbose: 373 print("copy: %s" % src) 374 print(" to: %s" % tgt) 375 shutil.copy(src, tgt) 376 377 if cleanup: 378 copied_execs.append(tgt) 379 380def locate_libs(): 381 "Move DLLs to a known location and set env vars" 382 383 debug = (objdir == 'Debug') 384 385 for lib in gen_obj._libraries.values(): 386 387 if debug: 388 name, dir = lib.debug_dll_name, lib.debug_dll_dir 389 else: 390 name, dir = lib.dll_name, lib.dll_dir 391 392 if name and dir: 393 src = os.path.join(dir, name) 394 if os.path.exists(src): 395 copy_changed_file(src, to_dir=abs_builddir, cleanup=False) 396 397 for name in lib.extra_bin: 398 src = os.path.join(dir, name) 399 copy_changed_file(src, to_dir=abs_builddir) 400 401 402 # Copy the Subversion library DLLs 403 for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL): 404 if isinstance(i, gen_base.TargetLib) and i.msvc_export: 405 src = os.path.join(abs_objdir, i.filename) 406 if os.path.isfile(src): 407 copy_changed_file(src, to_dir=abs_builddir, 408 cleanup=False) 409 410 # Copy the Apache modules 411 if run_httpd and cp.has_option('options', '--with-httpd'): 412 mod_dav_svn_path = os.path.join(abs_objdir, 'subversion', 413 'mod_dav_svn', 'mod_dav_svn.so') 414 mod_authz_svn_path = os.path.join(abs_objdir, 'subversion', 415 'mod_authz_svn', 'mod_authz_svn.so') 416 mod_dontdothat_path = os.path.join(abs_objdir, 'tools', 'server-side', 417 'mod_dontdothat', 'mod_dontdothat.so') 418 419 copy_changed_file(mod_dav_svn_path, to_dir=abs_builddir, cleanup=False) 420 copy_changed_file(mod_authz_svn_path, to_dir=abs_builddir, cleanup=False) 421 copy_changed_file(mod_dontdothat_path, to_dir=abs_builddir, cleanup=False) 422 423 os.environ['PATH'] = abs_builddir + os.pathsep + os.environ['PATH'] 424 425def fix_case(path): 426 path = os.path.normpath(path) 427 parts = path.split(os.path.sep) 428 drive = parts[0].upper() 429 parts = parts[1:] 430 path = drive + os.path.sep 431 for part in parts: 432 dirs = os.listdir(path) 433 for dir in dirs: 434 if dir.lower() == part.lower(): 435 path = os.path.join(path, dir) 436 break 437 return path 438 439class Svnserve: 440 "Run svnserve for ra_svn tests" 441 def __init__(self, svnserve_args, objdir, abs_objdir, abs_builddir): 442 self.args = svnserve_args 443 self.name = 'svnserve.exe' 444 self.kind = objdir 445 self.path = os.path.join(abs_objdir, 446 'subversion', 'svnserve', self.name) 447 self.root = os.path.join(abs_builddir, CMDLINE_TEST_SCRIPT_NATIVE_PATH) 448 self.proc = None 449 450 def __del__(self): 451 "Stop svnserve when the object is deleted" 452 self.stop() 453 454 def _quote(self, arg): 455 if ' ' in arg: 456 return '"' + arg + '"' 457 else: 458 return arg 459 460 def start(self): 461 if not self.args: 462 args = [self.name, '-d', '-r', self.root] 463 else: 464 args = [self.name] + self.args 465 print('Starting %s %s' % (self.kind, self.name)) 466 467 env = os.environ.copy() 468 env['SVN_DBG_STACKTRACES_TO_STDERR'] = 'y' 469 self.proc = subprocess.Popen([self.path] + args[1:], env=env) 470 471 def stop(self): 472 if self.proc is not None: 473 try: 474 print('Stopping %s' % self.name) 475 self.proc.poll(); 476 if self.proc.returncode is None: 477 self.proc.kill(); 478 return 479 except AttributeError: 480 pass 481 print('Svnserve.stop not implemented') 482 483class Httpd: 484 "Run httpd for DAV tests" 485 def __init__(self, abs_httpd_dir, abs_objdir, abs_builddir, abs_srcdir, 486 httpd_port, service, use_ssl, use_http2, use_mod_deflate, 487 no_log, httpv2, short_circuit, bulk_updates): 488 self.name = 'apache.exe' 489 self.httpd_port = httpd_port 490 self.httpd_dir = abs_httpd_dir 491 492 if httpv2: 493 self.httpv2_option = 'on' 494 else: 495 self.httpv2_option = 'off' 496 497 if bulk_updates: 498 self.bulkupdates_option = 'on' 499 else: 500 self.bulkupdates_option = 'off' 501 502 self.service = service 503 self.proc = None 504 self.path = os.path.join(self.httpd_dir, 'bin', self.name) 505 506 if short_circuit: 507 self.path_authz_option = 'short_circuit' 508 else: 509 self.path_authz_option = 'on' 510 511 if not os.path.exists(self.path): 512 self.name = 'httpd.exe' 513 self.path = os.path.join(self.httpd_dir, 'bin', self.name) 514 if not os.path.exists(self.path): 515 raise RuntimeError("Could not find a valid httpd binary!") 516 517 self.root_dir = os.path.join(CMDLINE_TEST_SCRIPT_NATIVE_PATH, 'httpd') 518 self.root = os.path.join(abs_builddir, self.root_dir) 519 self.authz_file = os.path.join(abs_builddir, 520 CMDLINE_TEST_SCRIPT_NATIVE_PATH, 521 'svn-test-work', 'authz') 522 self.dontdothat_file = os.path.join(abs_builddir, 523 CMDLINE_TEST_SCRIPT_NATIVE_PATH, 524 'svn-test-work', 'dontdothat') 525 self.certfile = os.path.join(abs_builddir, 526 CMDLINE_TEST_SCRIPT_NATIVE_PATH, 527 'svn-test-work', 'cert.pem') 528 self.certkeyfile = os.path.join(abs_builddir, 529 CMDLINE_TEST_SCRIPT_NATIVE_PATH, 530 'svn-test-work', 'cert-key.pem') 531 self.httpd_config = os.path.join(self.root, 'httpd.conf') 532 self.httpd_users = os.path.join(self.root, 'users') 533 self.httpd_mime_types = os.path.join(self.root, 'mime.types') 534 self.httpd_groups = os.path.join(self.root, 'groups') 535 self.abs_builddir = abs_builddir 536 self.abs_objdir = abs_objdir 537 self.abs_srcdir = abs_srcdir 538 self.service_name = 'svn-test-httpd-' + str(httpd_port) 539 540 if self.service: 541 self.httpd_args = [self.name, '-n', self._quote(self.service_name), 542 '-f', self._quote(self.httpd_config)] 543 else: 544 self.httpd_args = [self.name, '-f', self._quote(self.httpd_config)] 545 546 create_target_dir(self.root_dir) 547 548 self._create_users_file() 549 self._create_groups_file() 550 self._create_mime_types_file() 551 self._create_dontdothat_file() 552 553 if use_ssl: 554 self._create_cert_files() 555 556 # Obtain version. 557 version_vals = gen_obj._libraries['httpd'].version.split('.') 558 self.httpd_ver = float('%s.%s' % (version_vals[0], version_vals[1])) 559 560 # Create httpd config file 561 fp = open(self.httpd_config, 'w') 562 563 # Limit the number of threads (default = 64) 564 if not use_http2: 565 fp.write('<IfModule mpm_winnt.c>\n') 566 fp.write('ThreadsPerChild 16\n') 567 fp.write('</IfModule>\n') 568 569 # Global Environment 570 fp.write('ServerRoot ' + self._quote(self.root) + '\n') 571 fp.write('DocumentRoot ' + self._quote(self.root) + '\n') 572 fp.write('ServerName localhost\n') 573 fp.write('PidFile pid\n') 574 fp.write('ErrorLog log\n') 575 fp.write('Listen ' + str(self.httpd_port) + '\n') 576 577 if not no_log: 578 fp.write('LogFormat "%h %l %u %t \\"%r\\" %>s %b" common\n') 579 fp.write('Customlog log common\n') 580 fp.write('LogLevel Debug\n') 581 else: 582 fp.write('LogLevel Crit\n') 583 584 # Write LoadModule for minimal system module 585 if use_ssl: 586 fp.write(self._sys_module('ssl_module', 'mod_ssl.so')) 587 if use_http2: 588 fp.write(self._sys_module('http2_module', 'mod_http2.so')) 589 if use_mod_deflate: 590 fp.write(self._sys_module('deflate_module', 'mod_deflate.so')) 591 fp.write(self._sys_module('dav_module', 'mod_dav.so')) 592 if self.httpd_ver >= 2.3: 593 fp.write(self._sys_module('access_compat_module', 'mod_access_compat.so')) 594 fp.write(self._sys_module('authz_core_module', 'mod_authz_core.so')) 595 fp.write(self._sys_module('authz_user_module', 'mod_authz_user.so')) 596 fp.write(self._sys_module('authn_core_module', 'mod_authn_core.so')) 597 if self.httpd_ver >= 2.2: 598 fp.write(self._sys_module('auth_basic_module', 'mod_auth_basic.so')) 599 fp.write(self._sys_module('authn_file_module', 'mod_authn_file.so')) 600 fp.write(self._sys_module('authz_groupfile_module', 'mod_authz_groupfile.so')) 601 fp.write(self._sys_module('authz_host_module', 'mod_authz_host.so')) 602 else: 603 fp.write(self._sys_module('auth_module', 'mod_auth.so')) 604 fp.write(self._sys_module('alias_module', 'mod_alias.so')) 605 fp.write(self._sys_module('mime_module', 'mod_mime.so')) 606 fp.write(self._sys_module('log_config_module', 'mod_log_config.so')) 607 608 # Write LoadModule for Subversion modules 609 fp.write(self._svn_module('dav_svn_module', 'mod_dav_svn.so')) 610 fp.write(self._svn_module('authz_svn_module', 'mod_authz_svn.so')) 611 612 # And for mod_dontdothat 613 fp.write(self._svn_module('dontdothat_module', 'mod_dontdothat.so')) 614 615 if use_ssl: 616 fp.write('SSLEngine on\n') 617 fp.write('SSLProtocol All -SSLv2 -SSLv3\n') 618 fp.write('SSLCertificateFile %s\n' % self._quote(self.certfile)) 619 fp.write('SSLCertificateKeyFile %s\n' % self._quote(self.certkeyfile)) 620 621 if use_ssl and use_http2: 622 fp.write('Protocols h2 http/1.1\n') 623 elif use_http2: 624 fp.write('Protocols h2c http/1.1\n') 625 fp.write('H2Direct on\n') 626 627 if use_mod_deflate: 628 fp.write('SetOutputFilter DEFLATE\n') 629 630 # Don't handle .htaccess, symlinks, etc. 631 fp.write('<Directory />\n') 632 fp.write('AllowOverride None\n') 633 fp.write('Options None\n') 634 fp.write('</Directory>\n\n') 635 636 # Define two locations for repositories 637 fp.write(self._svn_repo('repositories')) 638 fp.write(self._svn_repo('local_tmp')) 639 fp.write(self._svn_authz_repo()) 640 641 # And two redirects for the redirect tests 642 fp.write('RedirectMatch permanent ^/svn-test-work/repositories/' 643 'REDIRECT-PERM-(.*)$ /svn-test-work/repositories/$1\n') 644 fp.write('RedirectMatch ^/svn-test-work/repositories/' 645 'REDIRECT-TEMP-(.*)$ /svn-test-work/repositories/$1\n') 646 647 fp.write('TypesConfig ' + self._quote(self.httpd_mime_types) + '\n') 648 fp.write('HostNameLookups Off\n') 649 650 fp.close() 651 652 def __del__(self): 653 "Stop httpd when the object is deleted" 654 self.stop() 655 656 def _quote(self, arg): 657 if ' ' in arg: 658 return '"' + arg + '"' 659 else: 660 return arg 661 662 def _create_users_file(self): 663 "Create users file" 664 htpasswd = os.path.join(self.httpd_dir, 'bin', 'htpasswd.exe') 665 # Create the cheapest to compare password form for our testsuite 666 os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bcp', self.httpd_users, 667 'jrandom', 'rayjandom']) 668 os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 669 'jconstant', 'rayjandom']) 670 os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 671 '__dumpster__', '__loadster__']) 672 os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 673 'JRANDOM', 'rayjandom']) 674 os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 675 'JCONSTANT', 'rayjandom']) 676 677 def _create_groups_file(self): 678 "Create groups for mod_authz_svn tests" 679 fp = open(self.httpd_groups, 'w') 680 fp.write('random: jrandom\n') 681 fp.write('constant: jconstant\n') 682 fp.close() 683 684 def _create_mime_types_file(self): 685 "Create empty mime.types file" 686 fp = open(self.httpd_mime_types, 'w') 687 fp.close() 688 689 def _create_dontdothat_file(self): 690 "Create empty mime.types file" 691 # If the tests have not previously been run or were cleaned 692 # up, then 'svn-test-work' does not exist yet. 693 parent_dir = os.path.dirname(self.dontdothat_file) 694 if not os.path.exists(parent_dir): 695 os.makedirs(parent_dir) 696 697 fp = open(self.dontdothat_file, 'w') 698 fp.write('[recursive-actions]\n') 699 fp.write('/ = deny\n') 700 fp.close() 701 702 def _create_cert_files(self): 703 "Create certificate files" 704 # The unix build uses certificates encoded in davautocheck.sh 705 # Let's just read them from there 706 707 sh_path = os.path.join(self.abs_srcdir, 'subversion', 'tests', 'cmdline', 708 'davautocheck.sh') 709 sh = open(sh_path).readlines() 710 711 def cert_extract(lines, what): 712 r = [] 713 pattern = r'cat\s*\>\s*' + re.escape(what) + r'\s*\<\<([A-Z_a-z0-9]+)' 714 exit_marker = None 715 for i in lines: 716 if exit_marker: 717 if i.startswith(exit_marker): 718 return r 719 r.append(i) 720 else: 721 m = re.match(pattern, i) 722 if m: 723 exit_marker = m.groups(1) 724 725 cert_file = cert_extract(sh, '"$SSL_CERTIFICATE_FILE"') 726 cert_key = cert_extract(sh, '"$SSL_CERTIFICATE_KEY_FILE"') 727 open(self.certfile, 'w').write(''.join(cert_file)) 728 open(self.certkeyfile, 'w').write(''.join(cert_key)) 729 730 def _sys_module(self, name, path): 731 full_path = os.path.join(self.httpd_dir, 'modules', path) 732 return 'LoadModule ' + name + " " + self._quote(full_path) + '\n' 733 734 def _svn_module(self, name, path): 735 full_path = os.path.join(self.abs_builddir, path) 736 return 'LoadModule ' + name + ' ' + self._quote(full_path) + '\n' 737 738 def _svn_repo(self, name): 739 path = os.path.join(self.abs_builddir, 740 CMDLINE_TEST_SCRIPT_NATIVE_PATH, 741 'svn-test-work', name) 742 location = '/svn-test-work/' + name 743 ddt_location = '/ddt-test-work/' + name 744 return \ 745 '<Location ' + location + '>\n' \ 746 ' DAV svn\n' \ 747 ' SVNParentPath ' + self._quote(path) + '\n' \ 748 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 749 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 750 ' SVNAllowBulkUpdates ' + self.bulkupdates_option + '\n' \ 751 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 752 ' AuthType Basic\n' \ 753 ' AuthName "Subversion Repository"\n' \ 754 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 755 ' Require valid-user\n' \ 756 '</Location>\n' \ 757 '<Location ' + ddt_location + '>\n' \ 758 ' DAV svn\n' \ 759 ' SVNParentPath ' + self._quote(path) + '\n' \ 760 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 761 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 762 ' SVNAllowBulkUpdates ' + self.bulkupdates_option + '\n' \ 763 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 764 ' AuthType Basic\n' \ 765 ' AuthName "Subversion Repository"\n' \ 766 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 767 ' Require valid-user\n' \ 768 ' DontDoThatConfigFile ' + self._quote(self.dontdothat_file) + '\n' \ 769 '</Location>\n' 770 771 def _svn_authz_repo(self): 772 local_tmp = os.path.join(self.abs_builddir, 773 CMDLINE_TEST_SCRIPT_NATIVE_PATH, 774 'svn-test-work', 'local_tmp') 775 return \ 776 '<Location /authz-test-work/anon>' + '\n' \ 777 ' DAV svn' + '\n' \ 778 ' SVNParentPath ' + local_tmp + '\n' \ 779 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 780 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 781 ' SVNListParentPath On' + '\n' \ 782 ' <IfModule mod_authz_core.c>' + '\n' \ 783 ' Require all granted' + '\n' \ 784 ' </IfModule>' + '\n' \ 785 ' <IfModule !mod_authz_core.c>' + '\n' \ 786 ' Allow from all' + '\n' \ 787 ' </IfModule>' + '\n' \ 788 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 789 '</Location>' + '\n' \ 790 '<Location /authz-test-work/mixed>' + '\n' \ 791 ' DAV svn' + '\n' \ 792 ' SVNParentPath ' + local_tmp + '\n' \ 793 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 794 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 795 ' SVNListParentPath On' + '\n' \ 796 ' AuthType Basic' + '\n' \ 797 ' AuthName "Subversion Repository"' + '\n' \ 798 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 799 ' Require valid-user' + '\n' \ 800 ' Satisfy Any' + '\n' \ 801 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 802 '</Location>' + '\n' \ 803 '<Location /authz-test-work/mixed-noauthwhenanon>' + '\n' \ 804 ' DAV svn' + '\n' \ 805 ' SVNParentPath ' + local_tmp + '\n' \ 806 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 807 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 808 ' SVNListParentPath On' + '\n' \ 809 ' AuthType Basic' + '\n' \ 810 ' AuthName "Subversion Repository"' + '\n' \ 811 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 812 ' Require valid-user' + '\n' \ 813 ' AuthzSVNNoAuthWhenAnonymousAllowed On' + '\n' \ 814 ' SVNPathAuthz On' + '\n' \ 815 '</Location>' + '\n' \ 816 '<Location /authz-test-work/authn>' + '\n' \ 817 ' DAV svn' + '\n' \ 818 ' SVNParentPath ' + local_tmp + '\n' \ 819 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 820 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 821 ' SVNListParentPath On' + '\n' \ 822 ' AuthType Basic' + '\n' \ 823 ' AuthName "Subversion Repository"' + '\n' \ 824 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 825 ' Require valid-user' + '\n' \ 826 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 827 '</Location>' + '\n' \ 828 '<Location /authz-test-work/authn-anonoff>' + '\n' \ 829 ' DAV svn' + '\n' \ 830 ' SVNParentPath ' + local_tmp + '\n' \ 831 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 832 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 833 ' SVNListParentPath On' + '\n' \ 834 ' AuthType Basic' + '\n' \ 835 ' AuthName "Subversion Repository"' + '\n' \ 836 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 837 ' Require valid-user' + '\n' \ 838 ' AuthzSVNAnonymous Off' + '\n' \ 839 ' SVNPathAuthz On' + '\n' \ 840 '</Location>' + '\n' \ 841 '<Location /authz-test-work/authn-lcuser>' + '\n' \ 842 ' DAV svn' + '\n' \ 843 ' SVNParentPath ' + local_tmp + '\n' \ 844 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 845 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 846 ' SVNListParentPath On' + '\n' \ 847 ' AuthType Basic' + '\n' \ 848 ' AuthName "Subversion Repository"' + '\n' \ 849 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 850 ' Require valid-user' + '\n' \ 851 ' AuthzForceUsernameCase Lower' + '\n' \ 852 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 853 '</Location>' + '\n' \ 854 '<Location /authz-test-work/authn-lcuser>' + '\n' \ 855 ' DAV svn' + '\n' \ 856 ' SVNParentPath ' + local_tmp + '\n' \ 857 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 858 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 859 ' SVNListParentPath On' + '\n' \ 860 ' AuthType Basic' + '\n' \ 861 ' AuthName "Subversion Repository"' + '\n' \ 862 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 863 ' Require valid-user' + '\n' \ 864 ' AuthzForceUsernameCase Lower' + '\n' \ 865 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 866 '</Location>' + '\n' \ 867 '<Location /authz-test-work/authn-group>' + '\n' \ 868 ' DAV svn' + '\n' \ 869 ' SVNParentPath ' + local_tmp + '\n' \ 870 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 871 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 872 ' SVNListParentPath On' + '\n' \ 873 ' AuthType Basic' + '\n' \ 874 ' AuthName "Subversion Repository"' + '\n' \ 875 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 876 ' AuthGroupFile ' + self._quote(self.httpd_groups) + '\n' \ 877 ' Require group random' + '\n' \ 878 ' AuthzSVNAuthoritative Off' + '\n' \ 879 ' SVNPathAuthz On' + '\n' \ 880 '</Location>' + '\n' \ 881 '<IfModule mod_authz_core.c>' + '\n' \ 882 '<Location /authz-test-work/sallrany>' + '\n' \ 883 ' DAV svn' + '\n' \ 884 ' SVNParentPath ' + local_tmp + '\n' \ 885 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 886 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 887 ' SVNListParentPath On' + '\n' \ 888 ' AuthType Basic' + '\n' \ 889 ' AuthName "Subversion Repository"' + '\n' \ 890 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 891 ' AuthzSendForbiddenOnFailure On' + '\n' \ 892 ' Satisfy All' + '\n' \ 893 ' <RequireAny>' + '\n' \ 894 ' Require valid-user' + '\n' \ 895 ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ 896 ' </RequireAny>' + '\n' \ 897 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 898 '</Location>' + '\n' \ 899 '<Location /authz-test-work/sallrall>'+ '\n' \ 900 ' DAV svn' + '\n' \ 901 ' SVNParentPath ' + local_tmp + '\n' \ 902 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 903 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 904 ' SVNListParentPath On' + '\n' \ 905 ' AuthType Basic' + '\n' \ 906 ' AuthName "Subversion Repository"' + '\n' \ 907 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 908 ' AuthzSendForbiddenOnFailure On' + '\n' \ 909 ' Satisfy All' + '\n' \ 910 ' <RequireAll>' + '\n' \ 911 ' Require valid-user' + '\n' \ 912 ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ 913 ' </RequireAll>' + '\n' \ 914 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 915 '</Location>' + '\n' \ 916 '</IfModule>' + '\n' \ 917 918 def start(self): 919 if self.service: 920 self._start_service() 921 else: 922 self._start_daemon() 923 924 # Avoid output from starting and preparing between test results 925 sys.stderr.flush() 926 sys.stdout.flush() 927 928 def stop(self): 929 if self.service: 930 self._stop_service() 931 else: 932 self._stop_daemon() 933 934 def _start_service(self): 935 "Install and start HTTPD service" 936 print('Installing service %s' % self.service_name) 937 os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'install']) 938 print('Starting service %s' % self.service_name) 939 os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'start']) 940 941 def _stop_service(self): 942 "Stop and uninstall HTTPD service" 943 os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'stop']) 944 os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'uninstall']) 945 946 def _start_daemon(self): 947 "Start HTTPD as daemon" 948 print('Starting httpd as daemon') 949 print(self.httpd_args) 950 self.proc = subprocess.Popen([self.path] + self.httpd_args[1:]) 951 952 def _stop_daemon(self): 953 "Stop the HTTPD daemon" 954 if self.proc is not None: 955 try: 956 print('Stopping %s' % self.name) 957 self.proc.poll(); 958 if self.proc.returncode is None: 959 self.proc.kill(); 960 return 961 except AttributeError: 962 pass 963 print('Httpd.stop_daemon not implemented') 964 965class Memcached: 966 "Run memcached for tests" 967 def __init__(self, abs_memcached_dir, memcached_server): 968 self.name = 'memcached.exe' 969 970 self.memcached_host, self.memcached_port = memcached_server.split(':') 971 self.memcached_dir = abs_memcached_dir 972 973 self.proc = None 974 self.path = os.path.join(self.memcached_dir, self.name) 975 976 self.memcached_args = [ 977 self.name, 978 '-p', self.memcached_port, 979 '-l', self.memcached_host 980 ] 981 982 def __del__(self): 983 "Stop memcached when the object is deleted" 984 self.stop() 985 986 def start(self): 987 "Start memcached as daemon" 988 print('Starting %s as daemon' % self.name) 989 print(self.memcached_args) 990 self.proc = subprocess.Popen([self.path] + self.memcached_args) 991 992 def stop(self): 993 "Stop memcached" 994 if self.proc is not None: 995 try: 996 print('Stopping %s' % self.name) 997 self.proc.poll(); 998 if self.proc.returncode is None: 999 self.proc.kill(); 1000 return 1001 except AttributeError: 1002 pass 1003 1004# Move the binaries to the test directory 1005create_target_dir(abs_builddir) 1006locate_libs() 1007if create_dirs: 1008 for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL): 1009 if isinstance(i, gen_base.TargetExe): 1010 src = os.path.join(abs_objdir, i.filename) 1011 1012 if os.path.isfile(src): 1013 dst = os.path.join(abs_builddir, i.filename) 1014 create_target_dir(os.path.dirname(dst)) 1015 copy_changed_file(src, dst) 1016 1017# Create the base directory for Python tests 1018create_target_dir(CMDLINE_TEST_SCRIPT_NATIVE_PATH) 1019 1020# Ensure the tests directory is correctly cased 1021abs_builddir = fix_case(abs_builddir) 1022 1023failed = None 1024daemon = None 1025memcached = None 1026# Run the tests 1027 1028# No need to start any servers if we are only listing the tests. 1029if not list_tests: 1030 if run_memcached: 1031 memcached = Memcached(memcached_dir, memcached_server) 1032 memcached.start() 1033 1034 if run_svnserve: 1035 daemon = Svnserve(svnserve_args, objdir, abs_objdir, abs_builddir) 1036 1037 if run_httpd: 1038 daemon = Httpd(abs_httpd_dir, abs_objdir, abs_builddir, abs_srcdir, 1039 httpd_port, httpd_service, use_ssl, use_http2, 1040 use_mod_deflate, httpd_no_log, advertise_httpv2, 1041 http_short_circuit, http_bulk_updates) 1042 1043 if use_ssl and not ssl_cert: 1044 ssl_cert = daemon.certfile 1045 1046 # Start service daemon, if any 1047 if daemon: 1048 daemon.start() 1049 1050# Find the full path and filename of any test that is specified just by 1051# its base name. 1052if len(tests_to_run) != 0: 1053 tests = [] 1054 for t in tests_to_run: 1055 tns = None 1056 if '#' in t: 1057 t, tns = t.split('#') 1058 1059 test = [x for x in all_tests if x.split('/')[-1] == t] 1060 if not test and not (t.endswith('-test.exe') or t.endswith('_tests.py')): 1061 # The lengths of '-test.exe' and of '_tests.py' are both 9. 1062 test = [x for x in all_tests if x.split('/')[-1][:-9] == t] 1063 1064 if not test: 1065 print("Skipping test '%s', test not found." % t) 1066 elif tns: 1067 tests.append('%s#%s' % (test[0], tns)) 1068 else: 1069 tests.extend(test) 1070 1071 tests_to_run = tests 1072else: 1073 tests_to_run = all_tests 1074 1075 1076if list_tests: 1077 print('Listing %s configuration on %s' % (objdir, repo_loc)) 1078else: 1079 print('Testing %s configuration on %s' % (objdir, repo_loc)) 1080sys.path.insert(0, os.path.join(abs_srcdir, 'build')) 1081 1082if not test_javahl and not test_swig: 1083 import run_tests 1084 if log_to_stdout: 1085 log_file = None 1086 fail_log_file = None 1087 else: 1088 log_file = os.path.join(abs_builddir, log) 1089 fail_log_file = os.path.join(abs_builddir, faillog) 1090 1091 if run_httpd: 1092 httpd_version = gen_obj._libraries['httpd'].version 1093 else: 1094 httpd_version = None 1095 1096 opts, args = run_tests.create_parser().parse_args([]) 1097 opts.url = base_url 1098 opts.fs_type = fs_type 1099 opts.global_scheduler = global_scheduler 1100 opts.http_library = 'serf' 1101 opts.server_minor_version = server_minor_version 1102 opts.cleanup = cleanup 1103 opts.enable_sasl = enable_sasl 1104 opts.parallel = parallel 1105 opts.config_file = config_file 1106 opts.fsfs_sharding = fsfs_sharding 1107 opts.fsfs_packing = fsfs_packing 1108 opts.list_tests = list_tests 1109 opts.svn_bin = svn_bin 1110 opts.mode_filter = mode_filter 1111 opts.milestone_filter = milestone_filter 1112 opts.httpd_version = httpd_version 1113 opts.set_log_level = log_level 1114 opts.ssl_cert = ssl_cert 1115 opts.exclusive_wc_locks = exclusive_wc_locks 1116 opts.memcached_server = memcached_server 1117 opts.skip_c_tests = skip_c_tests 1118 opts.dump_load_cross_check = dump_load_cross_check 1119 opts.fsfs_compression = fsfs_compression 1120 opts.fsfs_dir_deltification = fsfs_dir_deltification 1121 th = run_tests.TestHarness(abs_srcdir, abs_builddir, 1122 log_file, fail_log_file, opts) 1123 old_cwd = os.getcwd() 1124 try: 1125 os.chdir(abs_builddir) 1126 failed = th.run(tests_to_run) 1127 except: 1128 os.chdir(old_cwd) 1129 raise 1130 else: 1131 os.chdir(old_cwd) 1132elif test_javahl: 1133 failed = False 1134 1135 java_exe = None 1136 1137 for path in os.environ["PATH"].split(os.pathsep): 1138 if os.path.isfile(os.path.join(path, 'java.exe')): 1139 java_exe = os.path.join(path, 'java.exe') 1140 break 1141 1142 if not java_exe and 'java_sdk' in gen_obj._libraries: 1143 jdk = gen_obj._libraries['java_sdk'] 1144 1145 if os.path.isfile(os.path.join(jdk.lib_dir, '../bin/java.exe')): 1146 java_exe = os.path.join(jdk.lib_dir, '../bin/java.exe') 1147 1148 if not java_exe: 1149 print('Java not found. Skipping Java tests') 1150 else: 1151 args = (os.path.abspath(java_exe),) 1152 if (objdir == 'Debug'): 1153 args = args + ('-Xcheck:jni',) 1154 1155 if cleanup: 1156 args = args + ('-Dtest.cleanup=1',) 1157 1158 args = args + ( 1159 '-Dtest.rootdir=' + os.path.join(abs_builddir, 'javahl'), 1160 '-Dtest.srcdir=' + os.path.join(abs_srcdir, 1161 'subversion/bindings/javahl'), 1162 '-Dtest.rooturl=', 1163 '-Dtest.fstype=' + fs_type , 1164 '-Dtest.tests=', 1165 1166 '-Djava.library.path=' 1167 + os.path.join(abs_objdir, 1168 'subversion/bindings/javahl/native'), 1169 '-classpath', 1170 os.path.join(abs_srcdir, 'subversion/bindings/javahl/classes') +';' + 1171 gen_obj.junit_path 1172 ) 1173 1174 sys.stderr.flush() 1175 print('Running org.apache.subversion tests:') 1176 sys.stdout.flush() 1177 1178 r = subprocess.call(args + tuple(['org.apache.subversion.javahl.RunTests'])) 1179 sys.stdout.flush() 1180 sys.stderr.flush() 1181 if (r != 0): 1182 print('[Test runner reported failure]') 1183 failed = True 1184 1185 print('Running org.tigris.subversion tests:') 1186 sys.stdout.flush() 1187 r = subprocess.call(args + tuple(['org.tigris.subversion.javahl.RunTests'])) 1188 sys.stdout.flush() 1189 sys.stderr.flush() 1190 if (r != 0): 1191 print('[Test runner reported failure]') 1192 failed = True 1193elif test_swig == 'perl': 1194 failed = False 1195 swig_dir = os.path.join(abs_builddir, 'swig') 1196 swig_pl_dir = os.path.join(swig_dir, 'p5lib') 1197 swig_pl_svn = os.path.join(swig_pl_dir, 'SVN') 1198 swig_pl_auto_svn = os.path.join(swig_pl_dir, 'auto', 'SVN') 1199 1200 create_target_dir(swig_pl_svn) 1201 1202 for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL): 1203 if isinstance(i, gen_base.TargetSWIG) and i.lang == 'perl': 1204 mod_dir = os.path.join(swig_pl_auto_svn, '_' + i.name[5:].capitalize()) 1205 create_target_dir(mod_dir) 1206 copy_changed_file(os.path.join(abs_objdir, i.filename), to_dir=mod_dir) 1207 1208 elif isinstance(i, gen_base.TargetSWIGLib) and i.lang == 'perl': 1209 copy_changed_file(os.path.join(abs_objdir, i.filename), 1210 to_dir=abs_builddir) 1211 1212 pm_src = os.path.join(abs_srcdir, 'subversion', 'bindings', 'swig', 'perl', 1213 'native') 1214 1215 tests = [] 1216 1217 for root, dirs, files in os.walk(pm_src): 1218 for name in files: 1219 if name.endswith('.pm'): 1220 fn = os.path.join(root, name) 1221 copy_changed_file(fn, to_dir=swig_pl_svn) 1222 elif name.endswith('.t'): 1223 tests.append(os.path.relpath(os.path.join(root, name), pm_src)) 1224 1225 perl5lib = swig_pl_dir 1226 if 'PERL5LIB' in os.environ: 1227 perl5lib += os.pathsep + os.environ['PERL5LIB'] 1228 1229 perl_exe = 'perl.exe' 1230 1231 print('-- Running Swig Perl tests --') 1232 sys.stdout.flush() 1233 old_cwd = os.getcwd() 1234 try: 1235 os.chdir(pm_src) 1236 1237 os.environ['PERL5LIB'] = perl5lib 1238 os.environ["SVN_DBG_NO_ABORT_ON_ERROR_LEAK"] = 'YES' 1239 1240 r = subprocess.call([ 1241 perl_exe, 1242 '-MExtUtils::Command::MM', 1243 '-e', 'test_harness()' 1244 ] + tests) 1245 finally: 1246 os.chdir(old_cwd) 1247 1248 if (r != 0): 1249 print('[Test runner reported failure]') 1250 failed = True 1251elif test_swig == 'python': 1252 failed = False 1253 swig_dir = os.path.join(abs_builddir, 'swig') 1254 swig_py_dir = os.path.join(swig_dir, 'pylib') 1255 swig_py_libsvn = os.path.join(swig_py_dir, 'libsvn') 1256 swig_py_svn = os.path.join(swig_py_dir, 'svn') 1257 1258 create_target_dir(swig_py_libsvn) 1259 create_target_dir(swig_py_svn) 1260 1261 for i in gen_obj.graph.get_all_sources(gen_base.DT_INSTALL): 1262 if (isinstance(i, gen_base.TargetSWIG) 1263 or isinstance(i, gen_base.TargetSWIGLib)) and i.lang == 'python': 1264 1265 src = os.path.join(abs_objdir, i.filename) 1266 basename = os.path.basename(src) 1267 if sys.version_info[:2] >= (3, 5) \ 1268 and basename.endswith('.pyd') and objdir == 'Debug': 1269 basename = basename[:-4] + '_d.pyd' 1270 copy_changed_file(src, os.path.join(swig_py_libsvn, basename)) 1271 1272 py_src = os.path.join(abs_srcdir, 'subversion', 'bindings', 'swig', 'python') 1273 1274 for py_file in os.listdir(py_src): 1275 if py_file.endswith('.py'): 1276 copy_changed_file(os.path.join(py_src, py_file), 1277 to_dir=swig_py_libsvn) 1278 1279 py_src_svn = os.path.join(py_src, 'svn') 1280 for py_file in os.listdir(py_src_svn): 1281 if py_file.endswith('.py'): 1282 copy_changed_file(os.path.join(py_src_svn, py_file), 1283 to_dir=swig_py_svn) 1284 1285 print('-- Running Swig Python tests --') 1286 sys.stdout.flush() 1287 1288 pythonpath = swig_py_dir 1289 if 'PYTHONPATH' in os.environ: 1290 pythonpath += os.pathsep + os.environ['PYTHONPATH'] 1291 1292 python_exe = sys.executable if objdir != 'Debug' else \ 1293 os.path.join(os.path.dirname(sys.executable), 'python_d.exe') 1294 old_cwd = os.getcwd() 1295 try: 1296 os.environ['PYTHONPATH'] = pythonpath 1297 1298 r = subprocess.call([ 1299 python_exe, 1300 os.path.join(py_src, 'tests', 'run_all.py') 1301 ]) 1302 finally: 1303 os.chdir(old_cwd) 1304 1305 if (r != 0): 1306 print('[Test runner reported failure]') 1307 failed = True 1308 1309elif test_swig == 'ruby': 1310 failed = False 1311 1312 if 'ruby' not in gen_obj._libraries: 1313 print('Ruby not found. Skipping Ruby tests') 1314 else: 1315 ruby_lib = gen_obj._libraries['ruby'] 1316 1317 ruby_exe = 'ruby.exe' 1318 ruby_subdir = os.path.join('subversion', 'bindings', 'swig', 'ruby') 1319 ruby_args = [ 1320 '-I', os.path.join(abs_srcdir, ruby_subdir), 1321 os.path.join(abs_srcdir, ruby_subdir, 'test', 'run-test.rb'), 1322 '--verbose' 1323 ] 1324 1325 print('-- Running Swig Ruby tests --') 1326 sys.stdout.flush() 1327 old_cwd = os.getcwd() 1328 try: 1329 os.chdir(ruby_subdir) 1330 1331 os.environ["BUILD_TYPE"] = objdir 1332 os.environ["SVN_DBG_NO_ABORT_ON_ERROR_LEAK"] = 'YES' 1333 r = subprocess.call([ruby_exe] + ruby_args) 1334 finally: 1335 os.chdir(old_cwd) 1336 1337 sys.stdout.flush() 1338 sys.stderr.flush() 1339 if (r != 0): 1340 print('[Test runner reported failure]') 1341 failed = True 1342 1343elif test_swig: 1344 print('Unknown Swig binding type: ' + str(test_swig)) 1345 failed = True 1346 1347# Stop service daemon, if any 1348if daemon: 1349 del daemon 1350 1351if memcached: 1352 del memcached 1353 1354# Remove the execs again 1355for tgt in copied_execs: 1356 try: 1357 if os.path.isfile(tgt): 1358 if verbose: 1359 print("kill: %s" % tgt) 1360 os.unlink(tgt) 1361 except: 1362 traceback.print_exc(file=sys.stdout) 1363 pass 1364 1365 1366if failed: 1367 sys.exit(1) 1368