2 Driver for running the tests on Windows.
4 For a list of options, run this script with the --help option.
10 # $LastChangedRevision$
22 my_getopt
= getopt
.gnu_getopt
23 except AttributeError:
24 my_getopt
= getopt
.getopt
27 "print usage, exit the script"
29 print "Driver for running the tests on Windows."
30 print "Usage: python win-tests.py [option] [test-path]"
32 print "Valid options:"
33 print " -r, --release : test the Release configuration"
34 print " -d, --debug : test the Debug configuration (default)"
35 print " --bin=PATH : use the svn binaries installed in PATH"
36 print " -u URL, --url=URL : run ra_dav or ra_svn tests against URL;"
37 print " will start svnserve for ra_svn tests"
38 print " -v, --verbose : talk more"
39 print " -f, --fs-type=type : filesystem type to use (fsfs is default)"
40 print " -c, --cleanup : cleanup after running a test"
42 print " --svnserve-args=list : comma-separated list of arguments for"
44 print " default is '-d,-r,<test-path-root>'"
45 print " --asp.net-hack : use '_svn' instead of '.svn' for the admin"
47 print " --httpd-dir : location where Apache HTTPD is installed"
48 print " --httpd-port : port for Apache HTTPD; random port number"
49 print " will be used, if not specified"
50 print " --http-library : dav library to use, neon (default) or serf"
51 print " --list : print test doc strings only"
52 print " --enable-sasl : enable Cyrus SASL authentication for"
54 print " -p, --parallel : run multiple tests in parallel"
55 print " --server-minor-version : the minor version of the server being"
60 CMDLINE_TEST_SCRIPT_PATH
= 'subversion/tests/cmdline/'
61 CMDLINE_TEST_SCRIPT_NATIVE_PATH
= CMDLINE_TEST_SCRIPT_PATH
.replace('/', os
.sep
)
63 sys
.path
.insert(0, os
.path
.join('build', 'generator'))
64 sys
.path
.insert(1, 'build')
67 version_header
= os
.path
.join('subversion', 'include', 'svn_version.h')
68 cp
= ConfigParser
.ConfigParser()
69 cp
.read('gen-make.opts')
70 gen_obj
= gen_win
.GeneratorBase('build.conf', version_header
,
72 all_tests
= gen_obj
.test_progs
+ gen_obj
.bdb_test_progs \
73 + gen_obj
.scripts
+ gen_obj
.bdb_scripts
74 client_tests
= filter(lambda x
: x
.startswith(CMDLINE_TEST_SCRIPT_PATH
),
78 for section
in gen_obj
.sections
.values():
79 if section
.options
.get("msvc-export"):
80 dll_basename
= section
.name
+ "-" + str(gen_obj
.version
) + ".dll"
81 svn_dlls
.append(os
.path
.join("subversion", section
.name
, dll_basename
))
83 opts
, args
= my_getopt(sys
.argv
[1:], 'hrdvcpu:f:',
84 ['release', 'debug', 'verbose', 'cleanup', 'url=',
85 'svnserve-args=', 'fs-type=', 'asp.net-hack',
86 'httpd-dir=', 'httpd-port=', 'http-library=', 'help',
87 'list', 'enable-sasl', 'bin=', 'parallel'])
89 print 'Warning: non-option arguments after the first one will be ignored'
91 # Interpret the options and set parameters
92 base_url
, fs_type
, verbose
, cleanup
= None, None, None, None
93 repo_loc
= 'local repository.'
100 http_library
= 'neon'
105 server_minor_version
= None
107 for opt
, val
in opts
:
108 if opt
in ('-h', '--help'):
110 elif opt
in ('-u', '--url'):
112 elif opt
in ('-f', '--fs-type'):
114 elif opt
in ('-v', '--verbose'):
116 elif opt
in ('-c', '--cleanup'):
118 elif opt
in ['-r', '--release']:
120 elif opt
in ['-d', '--debug']:
122 elif opt
== '--svnserve-args':
123 svnserve_args
= val
.split(',')
125 elif opt
== '--asp.net-hack':
126 os
.environ
['SVN_ASP_DOT_NET_HACK'] = opt
127 elif opt
== '--httpd-dir':
128 abs_httpd_dir
= os
.path
.abspath(val
)
130 elif opt
== '--httpd-port':
131 httpd_port
= int(val
)
132 elif opt
== '--http-library':
134 elif opt
== '--list':
136 elif opt
== '--enable-sasl':
138 base_url
= "svn://localhost/"
139 elif opt
== '--server-minor-version':
140 server_minor_version
= val
143 elif opt
in ('-p', '--parallel'):
146 # Calculate the source and test directory names
147 abs_srcdir
= os
.path
.abspath("")
148 abs_objdir
= os
.path
.join(abs_srcdir
, objdir
)
150 abs_builddir
= abs_objdir
153 abs_builddir
= os
.path
.abspath(args
[0])
156 # Default to fsfs explicitly
160 # Don't run bdb tests if they want to test fsfs
161 if fs_type
== 'fsfs':
162 all_tests
= gen_obj
.test_progs
+ gen_obj
.scripts
166 httpd_port
= random
.randrange(1024, 30000)
168 base_url
= 'http://localhost:' + str(httpd_port
)
171 all_tests
= client_tests
172 repo_loc
= 'remote repository ' + base_url
+ '.'
173 if base_url
[:4] == 'http':
174 log
= 'dav-tests.log'
175 elif base_url
[:3] == 'svn':
176 log
= 'svn-tests.log'
179 # Don't know this scheme, but who're we to judge whether it's
181 log
= 'url-tests.log'
183 # Have to move the executables where the tests expect them to be
184 copied_execs
= [] # Store copied exec files to avoid the final dir scan
186 def create_target_dir(dirname
):
187 tgt_dir
= os
.path
.join(abs_builddir
, dirname
)
188 if not os
.path
.exists(tgt_dir
):
190 print "mkdir:", tgt_dir
193 def copy_changed_file(src
, tgt
):
194 if not os
.path
.isfile(src
):
195 print 'Could not find ' + src
197 if os
.path
.isdir(tgt
):
198 tgt
= os
.path
.join(tgt
, os
.path
.basename(src
))
199 if os
.path
.exists(tgt
):
200 assert os
.path
.isfile(tgt
)
201 if filecmp
.cmp(src
, tgt
):
209 shutil
.copy(src
, tgt
)
212 def copy_execs(baton
, dirname
, names
):
215 ext
= os
.path
.splitext(name
)[1]
218 src
= os
.path
.join(dirname
, name
)
219 tgt
= os
.path
.join(abs_builddir
, dirname
, name
)
220 create_target_dir(dirname
)
221 if copy_changed_file(src
, tgt
):
222 copied_execs
.append(tgt
)
225 "Move DLLs to a known location and set env vars"
229 # look for APR 1.x dll's and use those if found
230 apr_test_path
= os
.path
.join(gen_obj
.apr_path
, objdir
, 'libapr-1.dll')
231 if os
.path
.exists(apr_test_path
):
235 dlls
.append(os
.path
.join(gen_obj
.apr_path
, objdir
,
236 'libapr%s.dll' % (suffix
)))
237 dlls
.append(os
.path
.join(gen_obj
.apr_util_path
, objdir
,
238 'libaprutil%s.dll' % (suffix
)))
239 dlls
.append(os
.path
.join(gen_obj
.apr_iconv_path
, objdir
,
240 'libapriconv%s.dll' % (suffix
)))
242 if gen_obj
.libintl_path
is not None:
243 dlls
.append(os
.path
.join(gen_obj
.libintl_path
, 'bin', 'intl3_svn.dll'))
245 dlls
.append(os
.path
.join(gen_obj
.sqlite_path
, 'bin', 'sqlite3.dll'))
247 if gen_obj
.bdb_lib
is not None:
248 partial_path
= os
.path
.join(gen_obj
.bdb_path
, 'bin', gen_obj
.bdb_lib
)
249 if objdir
== 'Debug':
250 dlls
.append(partial_path
+ 'd.dll')
252 dlls
.append(partial_path
+ '.dll')
254 if gen_obj
.sasl_path
is not None:
255 dlls
.append(os
.path
.join(gen_obj
.sasl_path
, 'lib', 'libsasl.dll'))
258 copy_changed_file(dll
, abs_objdir
)
260 # Copy the Subversion library DLLs
261 if not cp
.has_option('options', '--disable-shared'):
262 for svn_dll
in svn_dlls
:
263 copy_changed_file(os
.path
.join(abs_objdir
, svn_dll
), abs_objdir
)
265 # Copy the Apache modules
266 if run_httpd
and cp
.has_option('options', '--with-httpd'):
267 mod_dav_svn_path
= os
.path
.join(abs_objdir
, 'subversion',
268 'mod_dav_svn', 'mod_dav_svn.so')
269 mod_authz_svn_path
= os
.path
.join(abs_objdir
, 'subversion',
270 'mod_authz_svn', 'mod_authz_svn.so')
271 copy_changed_file(mod_dav_svn_path
, abs_objdir
)
272 copy_changed_file(mod_authz_svn_path
, abs_objdir
)
274 apriconv_so_path
= os
.path
.join(gen_obj
.apr_iconv_path
, objdir
, 'iconv')
275 os
.environ
['APR_ICONV_PATH'] = os
.path
.abspath(apriconv_so_path
)
276 os
.environ
['PATH'] = abs_objdir
+ os
.pathsep
+ os
.environ
['PATH']
279 path
= os
.path
.normpath(path
)
280 parts
= string
.split(path
, os
.path
.sep
)
281 drive
= string
.upper(parts
[0])
283 path
= drive
+ os
.path
.sep
285 dirs
= os
.listdir(path
)
287 if string
.lower(dir) == string
.lower(part
):
288 path
= os
.path
.join(path
, dir)
293 "Run svnserve for ra_svn tests"
294 def __init__(self
, svnserve_args
, objdir
, abs_objdir
, abs_builddir
):
295 self
.args
= svnserve_args
296 self
.name
= 'svnserve.exe'
298 self
.path
= os
.path
.join(abs_objdir
,
299 'subversion', 'svnserve', self
.name
)
300 self
.root
= os
.path
.join(abs_builddir
, CMDLINE_TEST_SCRIPT_NATIVE_PATH
)
301 self
.proc_handle
= None
304 "Stop svnserve when the object is deleted"
307 def _quote(self
, arg
):
309 return '"' + arg
+ '"'
315 args
= [self
.name
, '-d', '-r', self
.root
]
317 args
= [self
.name
] + self
.args
318 print 'Starting', self
.kind
, self
.name
322 args
= ' '.join(map(lambda x
: self
._quote
(x
), args
))
324 win32process
.CreateProcess(self
._quote
(self
.path
), args
,
326 win32con
.CREATE_NEW_CONSOLE
,
327 None, None, win32process
.STARTUPINFO()))[0]
329 os
.spawnv(os
.P_NOWAIT
, self
.path
, args
)
332 if self
.proc_handle
is not None:
335 print 'Stopping', self
.name
336 win32process
.TerminateProcess(self
.proc_handle
, 0)
340 print 'Svnserve.stop not implemented'
343 "Run httpd for DAV tests"
344 def __init__(self
, abs_httpd_dir
, abs_objdir
, abs_builddir
, httpd_port
):
345 self
.name
= 'apache.exe'
346 self
.httpd_port
= httpd_port
347 self
.httpd_dir
= abs_httpd_dir
348 self
.path
= os
.path
.join(self
.httpd_dir
, 'bin', self
.name
)
350 if not os
.path
.exists(self
.path
):
351 self
.name
= 'httpd.exe'
352 self
.path
= os
.path
.join(self
.httpd_dir
, 'bin', self
.name
)
353 if not os
.path
.exists(self
.path
):
354 raise RuntimeError, "Could not find a valid httpd binary!"
356 self
.root_dir
= os
.path
.join(CMDLINE_TEST_SCRIPT_NATIVE_PATH
, 'httpd')
357 self
.root
= os
.path
.join(abs_builddir
, self
.root_dir
)
358 self
.authz_file
= os
.path
.join(abs_builddir
,
359 CMDLINE_TEST_SCRIPT_NATIVE_PATH
,
360 'svn-test-work', 'authz')
361 self
.httpd_config
= os
.path
.join(self
.root
, 'httpd.conf')
362 self
.httpd_users
= os
.path
.join(self
.root
, 'users')
363 self
.httpd_mime_types
= os
.path
.join(self
.root
, 'mime.types')
364 self
.abs_builddir
= abs_builddir
365 self
.abs_objdir
= abs_objdir
366 self
.service_name
= 'svn-test-httpd-' + str(httpd_port
)
367 self
.httpd_args
= [self
.name
, '-n', self
._quote
(self
.service_name
),
368 '-f', self
._quote
(self
.httpd_config
)]
370 create_target_dir(self
.root_dir
)
372 self
._create
_users
_file
()
373 self
._create
_mime
_types
_file
()
376 if os
.path
.exists(os
.path
.join(self
.httpd_dir
,
377 'modules', 'mod_access_compat.so')):
379 elif os
.path
.exists(os
.path
.join(self
.httpd_dir
,
380 'modules', 'mod_auth_basic.so')):
385 # Create httpd config file
386 fp
= open(self
.httpd_config
, 'w')
389 fp
.write('ServerRoot ' + self
._quote
(self
.root
) + '\n')
390 fp
.write('DocumentRoot ' + self
._quote
(self
.root
) + '\n')
391 fp
.write('ServerName localhost\n')
392 fp
.write('PidFile pid\n')
393 fp
.write('ErrorLog log\n')
394 fp
.write('Listen ' + str(self
.httpd_port
) + '\n')
396 # Write LoadModule for minimal system module
397 fp
.write(self
._sys
_module
('dav_module', 'mod_dav.so'))
398 if self
.httpd_ver
>= 2.3:
399 fp
.write(self
._sys
_module
('access_compat_module', 'mod_access_compat.so'))
400 fp
.write(self
._sys
_module
('authz_core_module', 'mod_authz_core.so'))
401 fp
.write(self
._sys
_module
('authz_user_module', 'mod_authz_user.so'))
402 fp
.write(self
._sys
_module
('authn_core_module', 'mod_authn_core.so'))
403 if self
.httpd_ver
>= 2.2:
404 fp
.write(self
._sys
_module
('auth_basic_module', 'mod_auth_basic.so'))
405 fp
.write(self
._sys
_module
('authn_file_module', 'mod_authn_file.so'))
407 fp
.write(self
._sys
_module
('auth_module', 'mod_auth.so'))
408 fp
.write(self
._sys
_module
('mime_module', 'mod_mime.so'))
409 fp
.write(self
._sys
_module
('log_config_module', 'mod_log_config.so'))
411 # Write LoadModule for Subversion modules
412 fp
.write(self
._svn
_module
('dav_svn_module', 'mod_dav_svn.so'))
413 fp
.write(self
._svn
_module
('authz_svn_module', 'mod_authz_svn.so'))
415 # Define two locations for repositories
416 fp
.write(self
._svn
_repo
('repositories'))
417 fp
.write(self
._svn
_repo
('local_tmp'))
419 fp
.write('TypesConfig ' + self
._quote
(self
.httpd_mime_types
) + '\n')
420 fp
.write('LogLevel Debug\n')
421 fp
.write('HostNameLookups Off\n')
426 "Stop httpd when the object is deleted"
429 def _quote(self
, arg
):
431 return '"' + arg
+ '"'
435 def _create_users_file(self
):
437 htpasswd
= os
.path
.join(self
.httpd_dir
, 'bin', 'htpasswd.exe')
438 os
.spawnv(os
.P_WAIT
, htpasswd
, ['htpasswd.exe', '-mbc', self
.httpd_users
,
439 'jrandom', 'rayjandom'])
440 os
.spawnv(os
.P_WAIT
, htpasswd
, ['htpasswd.exe', '-mb', self
.httpd_users
,
441 'jconstant', 'rayjandom'])
443 def _create_mime_types_file(self
):
444 "Create empty mime.types file"
445 fp
= open(self
.httpd_mime_types
, 'w')
448 def _sys_module(self
, name
, path
):
449 full_path
= os
.path
.join(self
.httpd_dir
, 'modules', path
)
450 return 'LoadModule ' + name
+ " " + self
._quote
(full_path
) + '\n'
452 def _svn_module(self
, name
, path
):
453 full_path
= os
.path
.join(self
.abs_objdir
, path
)
454 return 'LoadModule ' + name
+ ' ' + self
._quote
(full_path
) + '\n'
456 def _svn_repo(self
, name
):
457 path
= os
.path
.join(self
.abs_builddir
,
458 CMDLINE_TEST_SCRIPT_NATIVE_PATH
,
459 'svn-test-work', name
)
460 location
= '/svn-test-work/' + name
462 '<Location ' + location
+ '>\n' \
464 ' SVNParentPath ' + self
._quote
(path
) + '\n' \
465 ' AuthzSVNAccessFile ' + self
._quote
(self
.authz_file
) + '\n' \
466 ' AuthType Basic\n' \
467 ' AuthName "Subversion Repository"\n' \
468 ' AuthUserFile ' + self
._quote
(self
.httpd_users
) + '\n' \
469 ' Require valid-user\n' \
473 "Install and start HTTPD service"
474 print 'Installing service', self
.service_name
475 os
.spawnv(os
.P_WAIT
, self
.path
, self
.httpd_args
+ ['-k', 'install'])
476 print 'Starting service', self
.service_name
477 os
.spawnv(os
.P_WAIT
, self
.path
, self
.httpd_args
+ ['-k', 'start'])
480 "Stop and unintall HTTPD service"
481 os
.spawnv(os
.P_WAIT
, self
.path
, self
.httpd_args
+ ['-k', 'stop'])
482 os
.spawnv(os
.P_WAIT
, self
.path
, self
.httpd_args
+ ['-k', 'uninstall'])
484 # Move the binaries to the test directory
487 old_cwd
= os
.getcwd()
491 os
.path
.walk('subversion', copy_execs
, baton
)
498 # Create the base directory for Python tests
499 create_target_dir(CMDLINE_TEST_SCRIPT_NATIVE_PATH
)
501 # Ensure the tests directory is correctly cased
502 abs_builddir
= fix_case(abs_builddir
)
507 daemon
= Svnserve(svnserve_args
, objdir
, abs_objdir
, abs_builddir
)
510 daemon
= Httpd(abs_httpd_dir
, abs_objdir
, abs_builddir
, httpd_port
)
512 # Start service daemon, if any
516 print 'Testing', objdir
, 'configuration on', repo_loc
517 sys
.path
.insert(0, os
.path
.join(abs_srcdir
, 'build'))
519 th
= run_tests
.TestHarness(abs_srcdir
, abs_builddir
,
520 os
.path
.join(abs_builddir
, log
),
521 base_url
, fs_type
, http_library
,
522 server_minor_version
, 1, cleanup
,
523 enable_sasl
, parallel
, list_tests
,
525 old_cwd
= os
.getcwd()
527 os
.chdir(abs_builddir
)
528 failed
= th
.run(all_tests
)
535 # Stop service daemon, if any
539 # Remove the execs again
540 for tgt
in copied_execs
:
542 if os
.path
.isfile(tgt
):
547 traceback
.print_exc(file=sys
.stdout
)