diff options
Diffstat (limited to 'win-tests.py')
-rw-r--r-- | win-tests.py | 229 |
1 files changed, 210 insertions, 19 deletions
diff --git a/win-tests.py b/win-tests.py index 44ff110b15e7..5aaa37c80b40 100644 --- a/win-tests.py +++ b/win-tests.py @@ -24,14 +24,15 @@ Driver for running the tests on Windows. For a list of options, run this script with the --help option. """ -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.9.x/win-tests.py $ -# $LastChangedRevision: 1718291 $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/win-tests.py $ +# $LastChangedRevision: 1813897 $ import os, sys, subprocess import filecmp import shutil import traceback import logging +import re try: # Python >=3.0 import configparser @@ -83,6 +84,17 @@ def _usage_exit(): print(" --disable-http-v2 : Do not advertise support for HTTPv2 on server") print(" --disable-bulk-updates : Disable bulk updates on HTTP server") print(" --ssl-cert : Path to SSL server certificate to trust.") + print(" --https : Run Apache httpd with an https setup.") + print(" --http2 : Enable http2 in Apache Httpd (>= 2.4.17).") + print(" --mod-deflate : Enable mod_deflate in Apache Httpd.") + print(" --global-scheduler : Enable global scheduler.") + print(" --exclusive-wc-locks : Enable exclusive working copy locks") + print(" --memcached-dir=DIR : Run memcached from dir") + print(" --memcached-server= : Enable usage of the specified memcached server") + print(" <url:port>") + print(" --skip-c-tests : Skip all C tests") + print(" --dump-load-cross-check: Run the dump load cross check after every test") + print(" --javahl : Run the javahl tests instead of the normal tests") print(" --swig=language : Run the swig perl/python/ruby tests instead of") print(" the normal tests") @@ -101,6 +113,7 @@ def _usage_exit(): print(" --config-file : Configuration file for tests") print(" --fsfs-sharding : Specify shard size (for fsfs)") print(" --fsfs-packing : Run 'svnadmin pack' automatically") + print(" --fsfs-compression=VAL : Set compression type to VAL (for fsfs)") print(" -q, --quiet : Deprecated; this is the default.") print(" Use --set-log-level instead.") @@ -122,19 +135,24 @@ gen_obj = gen_win_dependencies.GenDependenciesBase('build.conf', version_header, opts, args = my_getopt(sys.argv[1:], 'hrdvqct:pu:f:', ['release', 'debug', 'verbose', 'quiet', 'cleanup', 'test=', 'url=', 'svnserve-args=', 'fs-type=', 'asp.net-hack', - 'httpd-dir=', 'httpd-port=', 'httpd-daemon', + 'httpd-dir=', 'httpd-port=', 'httpd-daemon', 'https', 'httpd-server', 'http-short-circuit', 'httpd-no-log', 'disable-http-v2', 'disable-bulk-updates', 'help', 'fsfs-packing', 'fsfs-sharding=', 'javahl', 'swig=', - 'list', 'enable-sasl', 'bin=', 'parallel', + 'list', 'enable-sasl', 'bin=', 'parallel', 'http2', + 'mod-deflate', 'global-scheduler', 'config-file=', 'server-minor-version=', 'log-level=', 'log-to-stdout', 'mode-filter=', 'milestone-filter=', - 'ssl-cert=']) + 'ssl-cert=', 'exclusive-wc-locks', 'memcached-server=', + 'skip-c-tests', 'dump-load-cross-check', 'memcached-dir=', + 'fsfs-compression=', + ]) if len(args) > 1: print('Warning: non-option arguments after the first one will be ignored') # Interpret the options and set parameters base_url, fs_type, verbose, cleanup = None, None, None, None +global_scheduler = None repo_loc = 'local repository.' objdir = 'Debug' log = 'tests.log' @@ -145,6 +163,9 @@ run_httpd = None httpd_port = None httpd_service = None httpd_no_log = None +use_ssl = False +use_http2 = False +use_mod_deflate = False http_short_circuit = False advertise_httpv2 = True http_bulk_updates = True @@ -164,6 +185,14 @@ mode_filter=None tests_to_run = [] log_level = None ssl_cert = None +exclusive_wc_locks = None +run_memcached = None +memcached_server = None +memcached_dir = None +skip_c_tests = None +dump_load_cross_check = None +fsfs_compression = None +fsfs_dir_deltification = None for opt, val in opts: if opt in ('-h', '--help'): @@ -199,6 +228,12 @@ for opt, val in opts: httpd_service = 1 elif opt == '--httpd-no-log': httpd_no_log = 1 + elif opt == '--https': + use_ssl = 1 + elif opt == '--http2': + use_http2 = 1 + elif opt == '--mod-deflate': + use_mod_deflate = 1 elif opt == '--http-short-circuit': http_short_circuit = True elif opt == '--disable-http-v2': @@ -211,6 +246,8 @@ for opt, val in opts: fsfs_packing = 1 elif opt == '--javahl': test_javahl = 1 + elif opt == '--global-scheduler': + global_scheduler = 1 elif opt == '--swig': if val not in ['perl', 'python', 'ruby']: sys.stderr.write('Running \'%s\' swig tests not supported (yet).\n' @@ -239,6 +276,21 @@ for opt, val in opts: log_level = getattr(logging, val, None) or int(val) elif opt == '--ssl-cert': ssl_cert = val + elif opt == '--exclusive-wc-locks': + exclusive_wc_locks = 1 + elif opt == '--memcached-server': + memcached_server = val + elif opt == '--skip-c-tests': + skip_c_tests = 1 + elif opt == '--dump-load-cross-check': + dump_load_cross_check = 1 + elif opt == '--memcached-dir': + memcached_dir = val + run_memcached = 1 + elif opt == '--fsfs-compression': + fsfs_compression = val + elif opt == '--fsfs-dir-deltification': + fsfs_dir_deltification = val # Calculate the source and test directory names abs_srcdir = os.path.abspath("") @@ -266,7 +318,12 @@ if run_httpd: if not httpd_port: httpd_port = random.randrange(1024, 30000) if not base_url: - base_url = 'http://localhost:' + str(httpd_port) + if use_ssl: + scheme = 'https' + else: + scheme = 'http' + + base_url = '%s://localhost:%d' % (scheme, httpd_port) if base_url: repo_loc = 'remote repository ' + base_url + '.' @@ -407,7 +464,9 @@ class Svnserve: args = [self.name] + self.args print('Starting %s %s' % (self.kind, self.name)) - self.proc = subprocess.Popen([self.path] + args[1:]) + env = os.environ.copy() + env['SVN_DBG_STACKTRACES_TO_STDERR'] = 'y' + self.proc = subprocess.Popen([self.path] + args[1:], env=env) def stop(self): if self.proc is not None: @@ -423,8 +482,9 @@ class Svnserve: class Httpd: "Run httpd for DAV tests" - def __init__(self, abs_httpd_dir, abs_objdir, abs_builddir, httpd_port, - service, no_log, httpv2, short_circuit, bulk_updates): + def __init__(self, abs_httpd_dir, abs_objdir, abs_builddir, abs_srcdir, + httpd_port, service, use_ssl, use_http2, use_mod_deflate, + no_log, httpv2, short_circuit, bulk_updates): self.name = 'apache.exe' self.httpd_port = httpd_port self.httpd_dir = abs_httpd_dir @@ -462,12 +522,19 @@ class Httpd: self.dontdothat_file = os.path.join(abs_builddir, CMDLINE_TEST_SCRIPT_NATIVE_PATH, 'svn-test-work', 'dontdothat') + self.certfile = os.path.join(abs_builddir, + CMDLINE_TEST_SCRIPT_NATIVE_PATH, + 'svn-test-work', 'cert.pem') + self.certkeyfile = os.path.join(abs_builddir, + CMDLINE_TEST_SCRIPT_NATIVE_PATH, + 'svn-test-work', 'cert-key.pem') self.httpd_config = os.path.join(self.root, 'httpd.conf') self.httpd_users = os.path.join(self.root, 'users') self.httpd_mime_types = os.path.join(self.root, 'mime.types') self.httpd_groups = os.path.join(self.root, 'groups') self.abs_builddir = abs_builddir self.abs_objdir = abs_objdir + self.abs_srcdir = abs_srcdir self.service_name = 'svn-test-httpd-' + str(httpd_port) if self.service: @@ -483,6 +550,9 @@ class Httpd: self._create_mime_types_file() self._create_dontdothat_file() + if use_ssl: + self._create_cert_files() + # Obtain version. version_vals = gen_obj._libraries['httpd'].version.split('.') self.httpd_ver = float('%s.%s' % (version_vals[0], version_vals[1])) @@ -491,9 +561,10 @@ class Httpd: fp = open(self.httpd_config, 'w') # Limit the number of threads (default = 64) - fp.write('<IfModule mpm_winnt.c>\n') - fp.write('ThreadsPerChild 16\n') - fp.write('</IfModule>\n') + if not use_http2: + fp.write('<IfModule mpm_winnt.c>\n') + fp.write('ThreadsPerChild 16\n') + fp.write('</IfModule>\n') # Global Environment fp.write('ServerRoot ' + self._quote(self.root) + '\n') @@ -511,6 +582,12 @@ class Httpd: fp.write('LogLevel Crit\n') # Write LoadModule for minimal system module + if use_ssl: + fp.write(self._sys_module('ssl_module', 'mod_ssl.so')) + if use_http2: + fp.write(self._sys_module('http2_module', 'mod_http2.so')) + if use_mod_deflate: + fp.write(self._sys_module('deflate_module', 'mod_deflate.so')) fp.write(self._sys_module('dav_module', 'mod_dav.so')) if self.httpd_ver >= 2.3: fp.write(self._sys_module('access_compat_module', 'mod_access_compat.so')) @@ -535,6 +612,21 @@ class Httpd: # And for mod_dontdothat fp.write(self._svn_module('dontdothat_module', 'mod_dontdothat.so')) + if use_ssl: + fp.write('SSLEngine on\n') + fp.write('SSLProtocol All -SSLv2 -SSLv3\n') + fp.write('SSLCertificateFile %s\n' % self._quote(self.certfile)) + fp.write('SSLCertificateKeyFile %s\n' % self._quote(self.certkeyfile)) + + if use_ssl and use_http2: + fp.write('Protocols h2 http/1.1\n') + elif use_http2: + fp.write('Protocols h2c http/1.1\n') + fp.write('H2Direct on\n') + + if use_mod_deflate: + fp.write('SetOutputFilter DEFLATE\n') + # Don't handle .htaccess, symlinks, etc. fp.write('<Directory />\n') fp.write('AllowOverride None\n') @@ -576,6 +668,8 @@ class Httpd: os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 'jconstant', 'rayjandom']) os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, + '__dumpster__', '__loadster__']) + os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 'JRANDOM', 'rayjandom']) os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 'JCONSTANT', 'rayjandom']) @@ -605,6 +699,34 @@ class Httpd: fp.write('/ = deny\n') fp.close() + def _create_cert_files(self): + "Create certificate files" + # The unix build uses certificates encoded in davautocheck.sh + # Let's just read them from there + + sh_path = os.path.join(self.abs_srcdir, 'subversion', 'tests', 'cmdline', + 'davautocheck.sh') + sh = open(sh_path).readlines() + + def cert_extract(lines, what): + r = [] + pattern = r'cat\s*\>\s*' + re.escape(what) + r'\s*\<\<([A-Z_a-z0-9]+)' + exit_marker = None + for i in lines: + if exit_marker: + if i.startswith(exit_marker): + return r + r.append(i) + else: + m = re.match(pattern, i) + if m: + exit_marker = m.groups(1) + + cert_file = cert_extract(sh, '"$SSL_CERTIFICATE_FILE"') + cert_key = cert_extract(sh, '"$SSL_CERTIFICATE_KEY_FILE"') + open(self.certfile, 'w').write(''.join(cert_file)) + open(self.certkeyfile, 'w').write(''.join(cert_key)) + def _sys_module(self, name, path): full_path = os.path.join(self.httpd_dir, 'modules', path) return 'LoadModule ' + name + " " + self._quote(full_path) + '\n' @@ -786,9 +908,9 @@ class Httpd: ' AuthzSendForbiddenOnFailure On' + '\n' \ ' Satisfy All' + '\n' \ ' <RequireAll>' + '\n' \ - ' Require valid-user' + '\n' \ - ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ - '</RequireAll>' + '\n' \ + ' Require valid-user' + '\n' \ + ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ + ' </RequireAll>' + '\n' \ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ '</Location>' + '\n' \ '</IfModule>' + '\n' \ @@ -799,6 +921,10 @@ class Httpd: else: self._start_daemon() + # Avoid output from starting and preparing between test results + sys.stderr.flush() + sys.stdout.flush() + def stop(self): if self.service: self._stop_service() @@ -836,6 +962,45 @@ class Httpd: pass print('Httpd.stop_daemon not implemented') +class Memcached: + "Run memcached for tests" + def __init__(self, abs_memcached_dir, memcached_server): + self.name = 'memcached.exe' + + self.memcached_host, self.memcached_port = memcached_server.split(':') + self.memcached_dir = abs_memcached_dir + + self.proc = None + self.path = os.path.join(self.memcached_dir, self.name) + + self.memcached_args = [ + self.name, + '-p', self.memcached_port, + '-l', self.memcached_host + ] + + def __del__(self): + "Stop memcached when the object is deleted" + self.stop() + + def start(self): + "Start memcached as daemon" + print('Starting %s as daemon' % self.name) + print(self.memcached_args) + self.proc = subprocess.Popen([self.path] + self.memcached_args) + + def stop(self): + "Stop memcached" + if self.proc is not None: + try: + print('Stopping %s' % self.name) + self.proc.poll(); + if self.proc.returncode is None: + self.proc.kill(); + return + except AttributeError: + pass + # Move the binaries to the test directory create_target_dir(abs_builddir) locate_libs() @@ -855,19 +1020,28 @@ create_target_dir(CMDLINE_TEST_SCRIPT_NATIVE_PATH) # Ensure the tests directory is correctly cased abs_builddir = fix_case(abs_builddir) +failed = None daemon = None +memcached = None # Run the tests # No need to start any servers if we are only listing the tests. if not list_tests: + if run_memcached: + memcached = Memcached(memcached_dir, memcached_server) + memcached.start() + if run_svnserve: daemon = Svnserve(svnserve_args, objdir, abs_objdir, abs_builddir) if run_httpd: - daemon = Httpd(abs_httpd_dir, abs_objdir, abs_builddir, httpd_port, - httpd_service, httpd_no_log, - advertise_httpv2, http_short_circuit, - http_bulk_updates) + daemon = Httpd(abs_httpd_dir, abs_objdir, abs_builddir, abs_srcdir, + httpd_port, httpd_service, use_ssl, use_http2, + use_mod_deflate, httpd_no_log, advertise_httpv2, + http_short_circuit, http_bulk_updates) + + if use_ssl and not ssl_cert: + ssl_cert = daemon.certfile # Start service daemon, if any if daemon: @@ -922,6 +1096,7 @@ if not test_javahl and not test_swig: opts, args = run_tests.create_parser().parse_args([]) opts.url = base_url opts.fs_type = fs_type + opts.global_scheduler = global_scheduler opts.http_library = 'serf' opts.server_minor_version = server_minor_version opts.cleanup = cleanup @@ -937,6 +1112,12 @@ if not test_javahl and not test_swig: opts.httpd_version = httpd_version opts.set_log_level = log_level opts.ssl_cert = ssl_cert + opts.exclusive_wc_locks = exclusive_wc_locks + opts.memcached_server = memcached_server + opts.skip_c_tests = skip_c_tests + opts.dump_load_cross_check = dump_load_cross_check + opts.fsfs_compression = fsfs_compression + opts.fsfs_dir_deltification = fsfs_dir_deltification th = run_tests.TestHarness(abs_srcdir, abs_builddir, log_file, fail_log_file, opts) old_cwd = os.getcwd() @@ -971,6 +1152,9 @@ elif test_javahl: if (objdir == 'Debug'): args = args + ('-Xcheck:jni',) + if cleanup: + args = args + ('-Dtest.cleanup=1',) + args = args + ( '-Dtest.rootdir=' + os.path.join(abs_builddir, 'javahl'), '-Dtest.srcdir=' + os.path.join(abs_srcdir, @@ -1151,10 +1335,17 @@ elif test_swig == 'ruby': print('[Test runner reported failure]') failed = True +elif test_swig: + print('Unknown Swig binding type: ' + str(test_swig)) + failed = True + # Stop service daemon, if any if daemon: del daemon +if memcached: + del memcached + # Remove the execs again for tgt in copied_execs: try: |