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: http://svn.apache.org/repos/asf/subversion/branches/1.8.x/win-tests.py $ 28# $LastChangedRevision: 1492044 $ 29 30import os, sys, subprocess 31import filecmp 32import shutil 33import traceback 34try: 35 # Python >=3.0 36 import configparser 37except ImportError: 38 # Python <3.0 39 import ConfigParser as configparser 40import string 41import random 42 43import getopt 44try: 45 my_getopt = getopt.gnu_getopt 46except AttributeError: 47 my_getopt = getopt.getopt 48 49def _usage_exit(): 50 "print usage, exit the script" 51 52 print("Driver for running the tests on Windows.") 53 print("Usage: python win-tests.py [option] [test-path]") 54 print("") 55 print("Valid options:") 56 print(" -r, --release : test the Release configuration") 57 print(" -d, --debug : test the Debug configuration (default)") 58 print(" --bin=PATH : use the svn binaries installed in PATH") 59 print(" -u URL, --url=URL : run ra_dav or ra_svn tests against URL;") 60 print(" will start svnserve for ra_svn tests") 61 print(" -v, --verbose : talk more") 62 print(" -q, --quiet : talk less") 63 print(" -f, --fs-type=type : filesystem type to use (fsfs is default)") 64 print(" -c, --cleanup : cleanup after running a test") 65 print(" -t, --test=TEST : Run the TEST test (all is default); use") 66 print(" TEST#n to run a particular test number,") 67 print(" multiples also accepted e.g. '2,4-7'") 68 print(" --log-level=LEVEL : Set log level to LEVEL (E.g. DEBUG)") 69 print(" --log-to-stdout : Write log results to stdout") 70 71 print(" --svnserve-args=list : comma-separated list of arguments for") 72 print(" svnserve") 73 print(" default is '-d,-r,<test-path-root>'") 74 print(" --asp.net-hack : use '_svn' instead of '.svn' for the admin") 75 print(" dir name") 76 print(" --httpd-dir : location where Apache HTTPD is installed") 77 print(" --httpd-port : port for Apache HTTPD; random port number") 78 print(" will be used, if not specified") 79 print(" --httpd-daemon : Run Apache httpd as daemon") 80 print(" --httpd-service : Run Apache httpd as Windows service (default)") 81 print(" --httpd-no-log : Disable httpd logging") 82 print(" --http-short-circuit : Use SVNPathAuthz short_circuit on HTTP server") 83 print(" --disable-http-v2 : Do not advertise support for HTTPv2 on server") 84 print(" --disable-bulk-updates : Disable bulk updates on HTTP server") 85 print(" --ssl-cert : Path to SSL server certificate to trust.") 86 print(" --javahl : Run the javahl tests instead of the normal tests") 87 print(" --list : print test doc strings only") 88 print(" --milestone-filter=RE : RE is a regular expression pattern that (when") 89 print(" used with --list) limits the tests listed to") 90 print(" those with an associated issue in the tracker") 91 print(" which has a target milestone that matches RE.") 92 print(" --mode-filter=TYPE : limit tests to expected TYPE = XFAIL, SKIP, PASS,") 93 print(" or 'ALL' (default)") 94 print(" --enable-sasl : enable Cyrus SASL authentication for") 95 print(" svnserve") 96 print(" -p, --parallel : run multiple tests in parallel") 97 print(" --server-minor-version : the minor version of the server being") 98 print(" tested") 99 print(" --config-file : Configuration file for tests") 100 print(" --fsfs-sharding : Specify shard size (for fsfs)") 101 print(" --fsfs-packing : Run 'svnadmin pack' automatically") 102 103 sys.exit(0) 104 105CMDLINE_TEST_SCRIPT_PATH = 'subversion/tests/cmdline/' 106CMDLINE_TEST_SCRIPT_NATIVE_PATH = CMDLINE_TEST_SCRIPT_PATH.replace('/', os.sep) 107 108sys.path.insert(0, os.path.join('build', 'generator')) 109sys.path.insert(1, 'build') 110 111import gen_win 112version_header = os.path.join('subversion', 'include', 'svn_version.h') 113cp = configparser.ConfigParser() 114cp.read('gen-make.opts') 115gen_obj = gen_win.GeneratorBase('build.conf', version_header, 116 cp.items('options')) 117all_tests = gen_obj.test_progs + gen_obj.bdb_test_progs \ 118 + gen_obj.scripts + gen_obj.bdb_scripts 119client_tests = [x for x in all_tests if x.startswith(CMDLINE_TEST_SCRIPT_PATH)] 120 121svn_dlls = [] 122for section in gen_obj.sections.values(): 123 if section.options.get("msvc-export"): 124 dll_basename = section.name + "-" + str(gen_obj.version) + ".dll" 125 svn_dlls.append(os.path.join("subversion", section.name, dll_basename)) 126 127opts, args = my_getopt(sys.argv[1:], 'hrdvqct:pu:f:', 128 ['release', 'debug', 'verbose', 'quiet', 'cleanup', 129 'test=', 'url=', 'svnserve-args=', 'fs-type=', 'asp.net-hack', 130 'httpd-dir=', 'httpd-port=', 'httpd-daemon', 131 'httpd-server', 'http-short-circuit', 'httpd-no-log', 132 'disable-http-v2', 'disable-bulk-updates', 'help', 133 'fsfs-packing', 'fsfs-sharding=', 'javahl', 134 'list', 'enable-sasl', 'bin=', 'parallel', 135 'config-file=', 'server-minor-version=', 'log-level=', 136 'log-to-stdout', 'mode-filter=', 'milestone-filter=', 137 'ssl-cert=']) 138if len(args) > 1: 139 print('Warning: non-option arguments after the first one will be ignored') 140 141# Interpret the options and set parameters 142base_url, fs_type, verbose, quiet, cleanup = None, None, None, None, None 143repo_loc = 'local repository.' 144objdir = 'Debug' 145log = 'tests.log' 146faillog = 'fails.log' 147run_svnserve = None 148svnserve_args = None 149run_httpd = None 150httpd_port = None 151httpd_service = None 152httpd_no_log = None 153http_short_circuit = False 154advertise_httpv2 = True 155http_bulk_updates = True 156list_tests = None 157milestone_filter = None 158test_javahl = None 159enable_sasl = None 160svn_bin = None 161parallel = None 162fsfs_sharding = None 163fsfs_packing = None 164server_minor_version = None 165config_file = None 166log_to_stdout = None 167mode_filter=None 168tests_to_run = [] 169log_level = None 170ssl_cert = None 171 172for opt, val in opts: 173 if opt in ('-h', '--help'): 174 _usage_exit() 175 elif opt in ('-u', '--url'): 176 base_url = val 177 elif opt in ('-f', '--fs-type'): 178 fs_type = val 179 elif opt in ('-v', '--verbose'): 180 verbose = 1 181 elif opt in ('-q', '--quiet'): 182 quiet = 1 183 elif opt in ('-c', '--cleanup'): 184 cleanup = 1 185 elif opt in ('-t', '--test'): 186 tests_to_run.append(val) 187 elif opt in ['-r', '--release']: 188 objdir = 'Release' 189 elif opt in ['-d', '--debug']: 190 objdir = 'Debug' 191 elif opt == '--svnserve-args': 192 svnserve_args = val.split(',') 193 run_svnserve = 1 194 elif opt == '--asp.net-hack': 195 os.environ['SVN_ASP_DOT_NET_HACK'] = opt 196 elif opt == '--httpd-dir': 197 abs_httpd_dir = os.path.abspath(val) 198 run_httpd = 1 199 elif opt == '--httpd-port': 200 httpd_port = int(val) 201 elif opt == '--httpd-daemon': 202 httpd_service = 0 203 elif opt == '--httpd-service': 204 httpd_service = 1 205 elif opt == '--httpd-no-log': 206 httpd_no_log = 1 207 elif opt == '--http-short-circuit': 208 http_short_circuit = True 209 elif opt == '--disable-http-v2': 210 advertise_httpv2 = False 211 elif opt == '--disable-bulk-updates': 212 http_bulk_updates = False 213 elif opt == '--fsfs-sharding': 214 fsfs_sharding = int(val) 215 elif opt == '--fsfs-packing': 216 fsfs_packing = 1 217 elif opt == '--javahl': 218 test_javahl = 1 219 elif opt == '--list': 220 list_tests = 1 221 elif opt == '--milestone-filter': 222 milestone_filter = val 223 elif opt == '--mode-filter': 224 mode_filter = val 225 elif opt == '--enable-sasl': 226 enable_sasl = 1 227 base_url = "svn://localhost/" 228 elif opt == '--server-minor-version': 229 server_minor_version = val 230 elif opt == '--bin': 231 svn_bin = val 232 elif opt in ('-p', '--parallel'): 233 parallel = 1 234 elif opt in ('--config-file'): 235 config_file = val 236 elif opt == '--log-to-stdout': 237 log_to_stdout = 1 238 elif opt == '--log-level': 239 log_level = val 240 elif opt == '--ssl-cert': 241 ssl_cert = val 242 243# Calculate the source and test directory names 244abs_srcdir = os.path.abspath("") 245abs_objdir = os.path.join(abs_srcdir, objdir) 246if len(args) == 0: 247 abs_builddir = abs_objdir 248 create_dirs = 0 249else: 250 abs_builddir = os.path.abspath(args[0]) 251 create_dirs = 1 252 253# Default to fsfs explicitly 254if not fs_type: 255 fs_type = 'fsfs' 256 257# Don't run bdb tests if they want to test fsfs 258if fs_type == 'fsfs': 259 all_tests = gen_obj.test_progs + gen_obj.scripts 260 261if run_httpd: 262 if not httpd_port: 263 httpd_port = random.randrange(1024, 30000) 264 if not base_url: 265 base_url = 'http://localhost:' + str(httpd_port) 266 267if base_url: 268 repo_loc = 'remote repository ' + base_url + '.' 269 if base_url[:4] == 'http': 270 log = 'dav-tests.log' 271 faillog = 'dav-fails.log' 272 elif base_url[:3] == 'svn': 273 log = 'svn-tests.log' 274 faillog = 'svn-fails.log' 275 run_svnserve = 1 276 else: 277 # Don't know this scheme, but who're we to judge whether it's 278 # correct or not? 279 log = 'url-tests.log' 280 faillog = 'url-fails.log' 281 282# Have to move the executables where the tests expect them to be 283copied_execs = [] # Store copied exec files to avoid the final dir scan 284 285def create_target_dir(dirname): 286 tgt_dir = os.path.join(abs_builddir, dirname) 287 if not os.path.exists(tgt_dir): 288 if verbose: 289 print("mkdir: %s" % tgt_dir) 290 os.makedirs(tgt_dir) 291 292def copy_changed_file(src, tgt): 293 if not os.path.isfile(src): 294 print('Could not find ' + src) 295 sys.exit(1) 296 if os.path.isdir(tgt): 297 tgt = os.path.join(tgt, os.path.basename(src)) 298 if os.path.exists(tgt): 299 assert os.path.isfile(tgt) 300 if filecmp.cmp(src, tgt): 301 if verbose: 302 print("same: %s" % src) 303 print(" and: %s" % tgt) 304 return 0 305 if verbose: 306 print("copy: %s" % src) 307 print(" to: %s" % tgt) 308 shutil.copy(src, tgt) 309 return 1 310 311def copy_execs(baton, dirname, names): 312 copied_execs = baton 313 for name in names: 314 if not name.endswith('.exe'): 315 continue 316 src = os.path.join(dirname, name) 317 tgt = os.path.join(abs_builddir, dirname, name) 318 create_target_dir(dirname) 319 if copy_changed_file(src, tgt): 320 copied_execs.append(tgt) 321 322def locate_libs(): 323 "Move DLLs to a known location and set env vars" 324 325 dlls = [] 326 327 # look for APR 1.x dll's and use those if found 328 apr_test_path = os.path.join(gen_obj.apr_path, objdir, 'libapr-1.dll') 329 if os.path.exists(apr_test_path): 330 suffix = "-1" 331 else: 332 suffix = "" 333 334 if cp.has_option('options', '--with-static-apr'): 335 dlls.append(os.path.join(gen_obj.apr_path, objdir, 336 'libapr%s.dll' % (suffix))) 337 dlls.append(os.path.join(gen_obj.apr_util_path, objdir, 338 'libaprutil%s.dll' % (suffix))) 339 340 if gen_obj.libintl_path is not None: 341 dlls.append(os.path.join(gen_obj.libintl_path, 'bin', 'intl3_svn.dll')) 342 343 if gen_obj.bdb_lib is not None: 344 partial_path = os.path.join(gen_obj.bdb_path, 'bin', gen_obj.bdb_lib) 345 if objdir == 'Debug': 346 dlls.append(partial_path + 'd.dll') 347 else: 348 dlls.append(partial_path + '.dll') 349 350 if gen_obj.sasl_path is not None: 351 dlls.append(os.path.join(gen_obj.sasl_path, 'lib', 'libsasl.dll')) 352 353 for dll in dlls: 354 copy_changed_file(dll, abs_objdir) 355 356 # Copy the Subversion library DLLs 357 if not cp.has_option('options', '--disable-shared'): 358 for svn_dll in svn_dlls: 359 copy_changed_file(os.path.join(abs_objdir, svn_dll), abs_objdir) 360 361 # Copy the Apache modules 362 if run_httpd and cp.has_option('options', '--with-httpd'): 363 mod_dav_svn_path = os.path.join(abs_objdir, 'subversion', 364 'mod_dav_svn', 'mod_dav_svn.so') 365 mod_authz_svn_path = os.path.join(abs_objdir, 'subversion', 366 'mod_authz_svn', 'mod_authz_svn.so') 367 mod_dontdothat_path = os.path.join(abs_objdir, 'tools', 'server-side', 368 'mod_dontdothat', 'mod_dontdothat.so') 369 370 copy_changed_file(mod_dav_svn_path, abs_objdir) 371 copy_changed_file(mod_authz_svn_path, abs_objdir) 372 copy_changed_file(mod_dontdothat_path, abs_objdir) 373 374 os.environ['PATH'] = abs_objdir + os.pathsep + os.environ['PATH'] 375 376def fix_case(path): 377 path = os.path.normpath(path) 378 parts = path.split(os.path.sep) 379 drive = parts[0].upper() 380 parts = parts[1:] 381 path = drive + os.path.sep 382 for part in parts: 383 dirs = os.listdir(path) 384 for dir in dirs: 385 if dir.lower() == part.lower(): 386 path = os.path.join(path, dir) 387 break 388 return path 389 390class Svnserve: 391 "Run svnserve for ra_svn tests" 392 def __init__(self, svnserve_args, objdir, abs_objdir, abs_builddir): 393 self.args = svnserve_args 394 self.name = 'svnserve.exe' 395 self.kind = objdir 396 self.path = os.path.join(abs_objdir, 397 'subversion', 'svnserve', self.name) 398 self.root = os.path.join(abs_builddir, CMDLINE_TEST_SCRIPT_NATIVE_PATH) 399 self.proc_handle = None 400 401 def __del__(self): 402 "Stop svnserve when the object is deleted" 403 self.stop() 404 405 def _quote(self, arg): 406 if ' ' in arg: 407 return '"' + arg + '"' 408 else: 409 return arg 410 411 def start(self): 412 if not self.args: 413 args = [self.name, '-d', '-r', self.root] 414 else: 415 args = [self.name] + self.args 416 print('Starting %s %s' % (self.kind, self.name)) 417 try: 418 import win32process 419 import win32con 420 args = ' '.join([self._quote(x) for x in args]) 421 self.proc_handle = ( 422 win32process.CreateProcess(self._quote(self.path), args, 423 None, None, 0, 424 win32con.CREATE_NEW_CONSOLE, 425 None, None, win32process.STARTUPINFO()))[0] 426 except ImportError: 427 os.spawnv(os.P_NOWAIT, self.path, args) 428 429 def stop(self): 430 if self.proc_handle is not None: 431 try: 432 import win32process 433 print('Stopping %s' % self.name) 434 win32process.TerminateProcess(self.proc_handle, 0) 435 return 436 except ImportError: 437 pass 438 print('Svnserve.stop not implemented') 439 440class Httpd: 441 "Run httpd for DAV tests" 442 def __init__(self, abs_httpd_dir, abs_objdir, abs_builddir, httpd_port, 443 service, no_log, httpv2, short_circuit, bulk_updates): 444 self.name = 'apache.exe' 445 self.httpd_port = httpd_port 446 self.httpd_dir = abs_httpd_dir 447 448 if httpv2: 449 self.httpv2_option = 'on' 450 else: 451 self.httpv2_option = 'off' 452 453 if bulk_updates: 454 self.bulkupdates_option = 'on' 455 else: 456 self.bulkupdates_option = 'off' 457 458 self.service = service 459 self.proc_handle = None 460 self.path = os.path.join(self.httpd_dir, 'bin', self.name) 461 462 if short_circuit: 463 self.path_authz_option = 'short_circuit' 464 else: 465 self.path_authz_option = 'on' 466 467 if not os.path.exists(self.path): 468 self.name = 'httpd.exe' 469 self.path = os.path.join(self.httpd_dir, 'bin', self.name) 470 if not os.path.exists(self.path): 471 raise RuntimeError("Could not find a valid httpd binary!") 472 473 self.root_dir = os.path.join(CMDLINE_TEST_SCRIPT_NATIVE_PATH, 'httpd') 474 self.root = os.path.join(abs_builddir, self.root_dir) 475 self.authz_file = os.path.join(abs_builddir, 476 CMDLINE_TEST_SCRIPT_NATIVE_PATH, 477 'svn-test-work', 'authz') 478 self.dontdothat_file = os.path.join(abs_builddir, 479 CMDLINE_TEST_SCRIPT_NATIVE_PATH, 480 'svn-test-work', 'dontdothat') 481 self.httpd_config = os.path.join(self.root, 'httpd.conf') 482 self.httpd_users = os.path.join(self.root, 'users') 483 self.httpd_mime_types = os.path.join(self.root, 'mime.types') 484 self.abs_builddir = abs_builddir 485 self.abs_objdir = abs_objdir 486 self.service_name = 'svn-test-httpd-' + str(httpd_port) 487 488 if self.service: 489 self.httpd_args = [self.name, '-n', self._quote(self.service_name), 490 '-f', self._quote(self.httpd_config)] 491 else: 492 self.httpd_args = [self.name, '-f', self._quote(self.httpd_config)] 493 494 create_target_dir(self.root_dir) 495 496 self._create_users_file() 497 self._create_mime_types_file() 498 self._create_dontdothat_file() 499 500 # Determine version. 501 if os.path.exists(os.path.join(self.httpd_dir, 502 'modules', 'mod_access_compat.so')): 503 self.httpd_ver = 2.3 504 elif os.path.exists(os.path.join(self.httpd_dir, 505 'modules', 'mod_auth_basic.so')): 506 self.httpd_ver = 2.2 507 else: 508 self.httpd_ver = 2.0 509 510 # Create httpd config file 511 fp = open(self.httpd_config, 'w') 512 513 # Limit the number of threads (default = 64) 514 fp.write('<IfModule mpm_winnt.c>\n') 515 fp.write('ThreadsPerChild 16\n') 516 fp.write('</IfModule>\n') 517 518 # Global Environment 519 fp.write('ServerRoot ' + self._quote(self.root) + '\n') 520 fp.write('DocumentRoot ' + self._quote(self.root) + '\n') 521 fp.write('ServerName localhost\n') 522 fp.write('PidFile pid\n') 523 fp.write('ErrorLog log\n') 524 fp.write('Listen ' + str(self.httpd_port) + '\n') 525 526 if not no_log: 527 fp.write('LogFormat "%h %l %u %t \\"%r\\" %>s %b" common\n') 528 fp.write('Customlog log common\n') 529 fp.write('LogLevel Debug\n') 530 else: 531 fp.write('LogLevel Crit\n') 532 533 # Write LoadModule for minimal system module 534 fp.write(self._sys_module('dav_module', 'mod_dav.so')) 535 if self.httpd_ver >= 2.3: 536 fp.write(self._sys_module('access_compat_module', 'mod_access_compat.so')) 537 fp.write(self._sys_module('authz_core_module', 'mod_authz_core.so')) 538 fp.write(self._sys_module('authz_user_module', 'mod_authz_user.so')) 539 fp.write(self._sys_module('authn_core_module', 'mod_authn_core.so')) 540 if self.httpd_ver >= 2.2: 541 fp.write(self._sys_module('auth_basic_module', 'mod_auth_basic.so')) 542 fp.write(self._sys_module('authn_file_module', 'mod_authn_file.so')) 543 else: 544 fp.write(self._sys_module('auth_module', 'mod_auth.so')) 545 fp.write(self._sys_module('alias_module', 'mod_alias.so')) 546 fp.write(self._sys_module('mime_module', 'mod_mime.so')) 547 fp.write(self._sys_module('log_config_module', 'mod_log_config.so')) 548 549 # Write LoadModule for Subversion modules 550 fp.write(self._svn_module('dav_svn_module', 'mod_dav_svn.so')) 551 fp.write(self._svn_module('authz_svn_module', 'mod_authz_svn.so')) 552 553 # And for mod_dontdothat 554 fp.write(self._svn_module('dontdothat_module', 'mod_dontdothat.so')) 555 556 # Don't handle .htaccess, symlinks, etc. 557 fp.write('<Directory />\n') 558 fp.write('AllowOverride None\n') 559 fp.write('Options None\n') 560 fp.write('</Directory>\n\n') 561 562 # Define two locations for repositories 563 fp.write(self._svn_repo('repositories')) 564 fp.write(self._svn_repo('local_tmp')) 565 566 # And two redirects for the redirect tests 567 fp.write('RedirectMatch permanent ^/svn-test-work/repositories/' 568 'REDIRECT-PERM-(.*)$ /svn-test-work/repositories/$1\n') 569 fp.write('RedirectMatch ^/svn-test-work/repositories/' 570 'REDIRECT-TEMP-(.*)$ /svn-test-work/repositories/$1\n') 571 572 fp.write('TypesConfig ' + self._quote(self.httpd_mime_types) + '\n') 573 fp.write('HostNameLookups Off\n') 574 575 fp.close() 576 577 def __del__(self): 578 "Stop httpd when the object is deleted" 579 self.stop() 580 581 def _quote(self, arg): 582 if ' ' in arg: 583 return '"' + arg + '"' 584 else: 585 return arg 586 587 def _create_users_file(self): 588 "Create users file" 589 htpasswd = os.path.join(self.httpd_dir, 'bin', 'htpasswd.exe') 590 # Create the cheapest to compare password form for our testsuite 591 os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bcp', self.httpd_users, 592 'jrandom', 'rayjandom']) 593 os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 594 'jconstant', 'rayjandom']) 595 596 def _create_mime_types_file(self): 597 "Create empty mime.types file" 598 fp = open(self.httpd_mime_types, 'w') 599 fp.close() 600 601 def _create_dontdothat_file(self): 602 "Create empty mime.types file" 603 # If the tests have not previously been run or were cleaned 604 # up, then 'svn-test-work' does not exist yet. 605 parent_dir = os.path.dirname(self.dontdothat_file) 606 if not os.path.exists(parent_dir): 607 os.makedirs(parent_dir) 608 609 fp = open(self.dontdothat_file, 'w') 610 fp.write('[recursive-actions]\n') 611 fp.write('/ = deny\n') 612 fp.close() 613 614 def _sys_module(self, name, path): 615 full_path = os.path.join(self.httpd_dir, 'modules', path) 616 return 'LoadModule ' + name + " " + self._quote(full_path) + '\n' 617 618 def _svn_module(self, name, path): 619 full_path = os.path.join(self.abs_objdir, path) 620 return 'LoadModule ' + name + ' ' + self._quote(full_path) + '\n' 621 622 def _svn_repo(self, name): 623 path = os.path.join(self.abs_builddir, 624 CMDLINE_TEST_SCRIPT_NATIVE_PATH, 625 'svn-test-work', name) 626 location = '/svn-test-work/' + name 627 ddt_location = '/ddt-test-work/' + name 628 return \ 629 '<Location ' + location + '>\n' \ 630 ' DAV svn\n' \ 631 ' SVNParentPath ' + self._quote(path) + '\n' \ 632 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 633 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 634 ' SVNAllowBulkUpdates ' + self.bulkupdates_option + '\n' \ 635 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 636 ' AuthType Basic\n' \ 637 ' AuthName "Subversion Repository"\n' \ 638 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 639 ' Require valid-user\n' \ 640 '</Location>\n' \ 641 '<Location ' + ddt_location + '>\n' \ 642 ' DAV svn\n' \ 643 ' SVNParentPath ' + self._quote(path) + '\n' \ 644 ' SVNAdvertiseV2Protocol ' + self.httpv2_option + '\n' \ 645 ' SVNPathAuthz ' + self.path_authz_option + '\n' \ 646 ' SVNAllowBulkUpdates ' + self.bulkupdates_option + '\n' \ 647 ' AuthzSVNAccessFile ' + self._quote(self.authz_file) + '\n' \ 648 ' AuthType Basic\n' \ 649 ' AuthName "Subversion Repository"\n' \ 650 ' AuthUserFile ' + self._quote(self.httpd_users) + '\n' \ 651 ' Require valid-user\n' \ 652 ' DontDoThatConfigFile ' + self._quote(self.dontdothat_file) + '\n' \ 653 '</Location>\n' 654 655 def start(self): 656 if self.service: 657 self._start_service() 658 else: 659 self._start_daemon() 660 661 def stop(self): 662 if self.service: 663 self._stop_service() 664 else: 665 self._stop_daemon() 666 667 def _start_service(self): 668 "Install and start HTTPD service" 669 print('Installing service %s' % self.service_name) 670 os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'install']) 671 print('Starting service %s' % self.service_name) 672 os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'start']) 673 674 def _stop_service(self): 675 "Stop and uninstall HTTPD service" 676 os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'stop']) 677 os.spawnv(os.P_WAIT, self.path, self.httpd_args + ['-k', 'uninstall']) 678 679 def _start_daemon(self): 680 "Start HTTPD as daemon" 681 print('Starting httpd as daemon') 682 print(self.httpd_args) 683 try: 684 import win32process 685 import win32con 686 args = ' '.join([self._quote(x) for x in self.httpd_args]) 687 self.proc_handle = ( 688 win32process.CreateProcess(self._quote(self.path), args, 689 None, None, 0, 690 win32con.CREATE_NEW_CONSOLE, 691 None, None, win32process.STARTUPINFO()))[0] 692 except ImportError: 693 os.spawnv(os.P_NOWAIT, self.path, self.httpd_args) 694 695 def _stop_daemon(self): 696 "Stop the HTTPD daemon" 697 if self.proc_handle is not None: 698 try: 699 import win32process 700 print('Stopping %s' % self.name) 701 win32process.TerminateProcess(self.proc_handle, 0) 702 return 703 except ImportError: 704 pass 705 print('Httpd.stop_daemon not implemented') 706 707# Move the binaries to the test directory 708locate_libs() 709if create_dirs: 710 old_cwd = os.getcwd() 711 try: 712 os.chdir(abs_objdir) 713 baton = copied_execs 714 for dirpath, dirs, files in os.walk('subversion'): 715 copy_execs(baton, dirpath, files) 716 for dirpath, dirs, files in os.walk('tools/server-side'): 717 copy_execs(baton, dirpath, files) 718 except: 719 os.chdir(old_cwd) 720 raise 721 else: 722 os.chdir(old_cwd) 723 724# Create the base directory for Python tests 725create_target_dir(CMDLINE_TEST_SCRIPT_NATIVE_PATH) 726 727# Ensure the tests directory is correctly cased 728abs_builddir = fix_case(abs_builddir) 729 730daemon = None 731# Run the tests 732 733# No need to start any servers if we are only listing the tests. 734if not list_tests: 735 if run_svnserve: 736 daemon = Svnserve(svnserve_args, objdir, abs_objdir, abs_builddir) 737 738 if run_httpd: 739 daemon = Httpd(abs_httpd_dir, abs_objdir, abs_builddir, httpd_port, 740 httpd_service, httpd_no_log, 741 advertise_httpv2, http_short_circuit, 742 http_bulk_updates) 743 744 # Start service daemon, if any 745 if daemon: 746 daemon.start() 747 748# Find the full path and filename of any test that is specified just by 749# its base name. 750if len(tests_to_run) != 0: 751 tests = [] 752 for t in tests_to_run: 753 tns = None 754 if '#' in t: 755 t, tns = t.split('#') 756 757 test = [x for x in all_tests if x.split('/')[-1] == t] 758 if not test and not (t.endswith('-test.exe') or t.endswith('_tests.py')): 759 # The lengths of '-test.exe' and of '_tests.py' are both 9. 760 test = [x for x in all_tests if x.split('/')[-1][:-9] == t] 761 762 if not test: 763 print("Skipping test '%s', test not found." % t) 764 elif tns: 765 tests.append('%s#%s' % (test[0], tns)) 766 else: 767 tests.extend(test) 768 769 tests_to_run = tests 770else: 771 tests_to_run = all_tests 772 773 774if list_tests: 775 print('Listing %s configuration on %s' % (objdir, repo_loc)) 776else: 777 print('Testing %s configuration on %s' % (objdir, repo_loc)) 778sys.path.insert(0, os.path.join(abs_srcdir, 'build')) 779 780if not test_javahl: 781 import run_tests 782 if log_to_stdout: 783 log_file = None 784 fail_log_file = None 785 else: 786 log_file = os.path.join(abs_builddir, log) 787 fail_log_file = os.path.join(abs_builddir, faillog) 788 789 th = run_tests.TestHarness(abs_srcdir, abs_builddir, 790 log_file, 791 fail_log_file, 792 base_url, fs_type, 'serf', 793 server_minor_version, not quiet, 794 cleanup, enable_sasl, parallel, config_file, 795 fsfs_sharding, fsfs_packing, 796 list_tests, svn_bin, mode_filter, 797 milestone_filter, 798 set_log_level=log_level, ssl_cert=ssl_cert) 799 old_cwd = os.getcwd() 800 try: 801 os.chdir(abs_builddir) 802 failed = th.run(tests_to_run) 803 except: 804 os.chdir(old_cwd) 805 raise 806 else: 807 os.chdir(old_cwd) 808else: 809 failed = False 810 args = ( 811 'java.exe', 812 '-Dtest.rootdir=' + os.path.join(abs_builddir, 'javahl'), 813 '-Dtest.srcdir=' + os.path.join(abs_srcdir, 814 'subversion/bindings/javahl'), 815 '-Dtest.rooturl=', 816 '-Dtest.fstype=' + fs_type , 817 '-Dtest.tests=', 818 819 '-Djava.library.path=' 820 + os.path.join(abs_objdir, 821 'subversion/bindings/javahl/native'), 822 '-classpath', 823 os.path.join(abs_srcdir, 'subversion/bindings/javahl/classes') +';' + 824 gen_obj.junit_path 825 ) 826 827 sys.stderr.flush() 828 print('Running org.apache.subversion tests:') 829 sys.stdout.flush() 830 831 r = subprocess.call(args + tuple(['org.apache.subversion.javahl.RunTests'])) 832 sys.stdout.flush() 833 sys.stderr.flush() 834 if (r != 0): 835 print('[Test runner reported failure]') 836 failed = True 837 838 print('Running org.tigris.subversion tests:') 839 sys.stdout.flush() 840 r = subprocess.call(args + tuple(['org.tigris.subversion.javahl.RunTests'])) 841 sys.stdout.flush() 842 sys.stderr.flush() 843 if (r != 0): 844 print('[Test runner reported failure]') 845 failed = True 846 847# Stop service daemon, if any 848if daemon: 849 del daemon 850 851# Remove the execs again 852for tgt in copied_execs: 853 try: 854 if os.path.isfile(tgt): 855 if verbose: 856 print("kill: %s" % tgt) 857 os.unlink(tgt) 858 except: 859 traceback.print_exc(file=sys.stdout) 860 pass 861 862 863if failed: 864 sys.exit(1) 865