2 # Bootstrap Samba and run a number of tests against it.
3 # Copyright (C) 2005-2012 Jelmer Vernooij <jelmer@samba.org>
4 # Copyright (C) 2007-2009 Stefan Metzmacher <metze@samba.org>
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 from cStringIO
import StringIO
25 from samba
import subunit
31 sys
.path
.insert(0, os
.path
.dirname(os
.path
.dirname(__file__
)))
33 from selftest
import (
38 from selftest
.client
import write_clientconf
39 from selftest
.run
import (
44 run_testsuite_command
,
46 from selftest
.target
import (
49 UnsupportedEnvironment
,
55 def read_excludes(fn
):
56 excludes
.extend(testlist
.read_test_regexes(fn
))
58 def read_includes(fn
):
59 includes
.extend(testlist
.read_test_regexes(fn
))
61 parser
= optparse
.OptionParser("TEST-REGEXES")
62 parser
.add_option("--target", type="choice", choices
=["samba", "samba3", "none"], default
="samba", help="Samba version to target")
63 parser
.add_option("--quick", help="run quick overall test", action
="store_true", default
=False)
64 parser
.add_option("--list", help="list available tests", action
="store_true", default
=False)
65 parser
.add_option("--socket-wrapper", help="enable socket wrapper", action
="store_true", default
=False)
66 parser
.add_option("--socket-wrapper-pcap", help="save traffic to pcap directories", type="str")
67 parser
.add_option("--socket-wrapper-keep-pcap", help="keep all pcap files, not just those for tests that failed", action
="store_true", default
=False)
68 parser
.add_option("--one", help="abort when the first test fails", action
="store_true", default
=False)
69 parser
.add_option("--exclude", action
="callback", help="Add file to exclude files", callback
=read_excludes
)
70 parser
.add_option("--include", action
="callback", help="Add file to include files", callback
=read_includes
)
71 parser
.add_option("--testenv", help="run a shell in the requested test environment", action
="store_true", default
=False)
72 parser
.add_option("--resetup-environment", help="Re-setup environment", action
="store_true", default
=False)
73 parser
.add_option("--binary-mapping", help="Map binaries to use", type=str)
74 parser
.add_option("--load-list", help="Load list of tests to load from a file", type=str)
75 parser
.add_option("--prefix", help="prefix to run tests in", type=str, default
="./st")
76 parser
.add_option("--srcdir", type=str, default
=".", help="source directory")
77 parser
.add_option("--bindir", type=str, default
="./bin", help="binaries directory")
78 parser
.add_option("--testlist", type=str, action
="append", help="file to read available tests from")
79 parser
.add_option("--ldap", help="back samba onto specified ldap server", choices
=["openldap", "fedora-ds"], type="choice")
81 opts
, args
= parser
.parse_args()
83 subunit_ops
= subunithelper
.SubunitOps(sys
.stdout
)
85 def handle_signal(sig
, frame
):
86 sys
.stderr
.write("Exiting early because of signal %s.\n" % sig
)
89 for sig
in (signal
.SIGINT
, signal
.SIGQUIT
, signal
.SIGTERM
, signal
.SIGPIPE
):
90 signal
.signal(sig
, handle_signal
)
93 return testlist
.find_in_list(excludes
, name
)
96 if (not opts
.socket_wrapper_pcap
or
97 not os
.environ
.get("SOCKET_WRAPPER_PCAP_DIR")):
100 fname
= "".join([x
for x
in name
if x
.isalnum() or x
== '-'])
102 pcap_file
= os
.path
.join(
103 os
.environ
["SOCKET_WRAPPER_PCAP_DIR"], "%s.pcap" % fname
)
105 socket_wrapper
.setup_pcap(pcap_file
)
109 def cleanup_pcap(pcap_file
, exit_code
):
110 if not opts
.socket_wrapper_pcap
:
112 if opts
.socket_wrapper_keep_pcap
:
116 if pcap_file
is None:
122 def run_testsuite(name
, cmd
, subunit_ops
, env
=None):
123 """Run a single testsuite.
125 :param env: Environment to run in
126 :param name: Name of the testsuite
127 :param cmd: Name of the (fully expanded) command to run
128 :return: exitcode of the command
130 pcap_file
= setup_pcap(name
)
132 exitcode
= run_testsuite_command(name
, cmd
, subunit_ops
, env
)
136 cleanup_pcap(pcap_file
, exitcode
)
138 if not opts
.socket_wrapper_keep_pcap
and pcap_file
is not None:
139 sys
.stdout
.write("PCAP FILE: %s\n" % pcap_file
)
141 if exitcode
!= 0 and opts
.one
:
147 if opts
.list and opts
.testenv
:
148 sys
.stderr
.write("--list and --testenv are mutually exclusive\n")
153 # quick hack to disable rpc validation when using valgrind - it is way too slow
154 if not os
.environ
.get("VALGRIND"):
155 os
.environ
["VALIDATE"] = "validate"
156 os
.environ
["MALLOC_CHECK_"] = "3"
158 # make all our python scripts unbuffered
159 os
.environ
["PYTHONUNBUFFERED"] = "1"
161 bindir_abs
= os
.path
.abspath(opts
.bindir
)
163 # Backwards compatibility:
164 if os
.environ
.get("TEST_LDAP") == "yes":
165 if os
.environ
.get("FEDORA_DS_ROOT"):
170 torture_maxtime
= int(os
.getenv("TORTURE_MAXTIME", "1200"))
175 prefix
= os
.path
.normpath(opts
.prefix
)
177 # Ensure we have the test prefix around.
179 # We need restrictive permissions on this as some subdirectories in this tree
180 # will have wider permissions (ie 0777) and this would allow other users on the
181 # host to subvert the test process.
182 if not os
.path
.isdir(prefix
):
183 os
.mkdir(prefix
, 0700)
185 os
.chmod(prefix
, 0700)
187 prefix_abs
= os
.path
.abspath(prefix
)
188 tmpdir_abs
= os
.path
.abspath(os
.path
.join(prefix_abs
, "tmp"))
189 if not os
.path
.isdir(tmpdir_abs
):
190 os
.mkdir(tmpdir_abs
, 0777)
192 srcdir_abs
= os
.path
.abspath(opts
.srcdir
)
194 if prefix_abs
== "/":
195 raise Exception("using '/' as absolute prefix is a bad idea")
197 os
.environ
["PREFIX"] = prefix
198 os
.environ
["KRB5CCNAME"] = os
.path
.join(prefix
, "krb5ticket")
199 os
.environ
["PREFIX_ABS"] = prefix_abs
200 os
.environ
["SRCDIR"] = opts
.srcdir
201 os
.environ
["SRCDIR_ABS"] = srcdir_abs
202 os
.environ
["BINDIR"] = bindir_abs
204 tls_enabled
= not opts
.quick
206 os
.environ
["TLS_ENABLED"] = "yes"
208 os
.environ
["TLS_ENABLED"] = "no"
210 def prefix_pathvar(name
, newpath
):
211 if name
in os
.environ
:
212 os
.environ
[name
] = "%s:%s" % (newpath
, os
.environ
[name
])
214 os
.environ
[name
] = newpath
215 prefix_pathvar("PKG_CONFIG_PATH", os
.path
.join(bindir_abs
, "pkgconfig"))
216 prefix_pathvar("PYTHONPATH", os
.path
.join(bindir_abs
, "python"))
218 if opts
.socket_wrapper_keep_pcap
:
219 # Socket wrapper keep pcap implies socket wrapper pcap
220 opts
.socket_wrapper_pcap
= True
222 if opts
.socket_wrapper_pcap
:
223 # Socket wrapper pcap implies socket wrapper
224 opts
.socket_wrapper
= True
226 if opts
.socket_wrapper
:
227 socket_wrapper_dir
= socket_wrapper
.setup_dir(os
.path
.join(prefix_abs
, "w"), opts
.socket_wrapper_pcap
)
228 sys
.stdout
.write("SOCKET_WRAPPER_DIR=%s\n" % socket_wrapper_dir
)
231 warnings
.warn("not using socket wrapper, but also not running as root. Will not be able to listen on proper ports")
233 testenv_default
= "none"
235 if opts
.binary_mapping
:
236 binary_mapping
= dict([l
.split(":") for l
in opts
.binary_mapping
.split(",")])
237 os
.environ
["BINARY_MAPPING"] = opts
.binary_mapping
240 os
.environ
["BINARY_MAPPING"] = ""
242 # After this many seconds, the server will self-terminate. All tests
243 # must terminate in this time, and testenv will only stay alive this
246 if os
.environ
.get("SMBD_MAXTIME", ""):
247 server_maxtime
= int(os
.environ
["SMBD_MAXTIME"])
249 server_maxtime
= 7500
252 def has_socket_wrapper(bindir
):
253 """Check if Samba has been built with socket wrapper support.
256 subprocess
.check_call([os
.path
.join(bindir
, "smbd"), "-b"], stdout
=f
)
257 for l
in f
.readlines():
258 if "SOCKET_WRAPPER" in l
:
264 if opts
.target
== "samba":
265 if opts
.socket_wrapper
and not has_socket_wrapper(opts
.bindir
):
266 sys
.stderr
.write("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....\n")
268 testenv_default
= "ad_dc_ntvfs"
269 from selftest
.target
.samba
import Samba
270 target
= Samba(opts
.bindir
, binary_mapping
, ldap
, opts
.srcdir
, server_maxtime
)
271 elif opts
.target
== "samba3":
272 if opts
.socket_wrapper
and not has_socket_wrapper(opts
.bindir
):
273 sys
.stderr
.write("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....\n")
275 testenv_default
= "member"
276 from selftest
.target
.samba3
import Samba3
277 target
= Samba3(opts
.bindir
, binary_mapping
, srcdir_abs
, server_maxtime
)
278 elif opts
.target
== "none":
279 testenv_default
= "none"
280 target
= NoneTarget()
282 env_manager
= EnvironmentManager(target
)
283 atexit
.register(env_manager
.teardown_all
)
285 interfaces
= ",".join([
293 clientdir
= os
.path
.join(prefix_abs
, "client")
295 conffile
= os
.path
.join(clientdir
, "client.conf")
296 os
.environ
["SMB_CONF_PATH"] = conffile
300 if not opts
.testlist
:
301 sys
.stderr
.write("No testlists specified\n")
304 os
.environ
["SELFTEST_PREFIX"] = prefix_abs
305 os
.environ
["SELFTEST_TMPDIR"] = tmpdir_abs
306 os
.environ
["TEST_DATA_PREFIX"] = tmpdir_abs
307 if opts
.socket_wrapper
:
308 os
.environ
["SELFTEST_INTERFACES"] = interfaces
310 os
.environ
["SELFTEST_INTERFACES"] = ""
312 os
.environ
["SELFTEST_QUICK"] = "1"
314 os
.environ
["SELFTEST_QUICK"] = ""
315 os
.environ
["SELFTEST_MAXTIME"] = str(torture_maxtime
)
319 for fn
in opts
.testlist
:
320 for testsuite
in testlist
.read_testlist_file(fn
):
321 if not testlist
.should_run_test(tests
, testsuite
):
324 if (includes
is not None and
325 testlist
.find_in_list(includes
, name
) is not None):
327 available
.append(testsuite
)
330 restricted_mgr
= testlist
.RestrictedTestManager
.from_path(opts
.load_list
)
332 restricted_mgr
= None
334 for testsuite
in available
:
336 skipreason
= skip(name
)
337 if restricted_mgr
is not None:
338 match
= restricted_mgr
.should_run_testsuite(name
)
343 if skipreason
is not None:
345 subunit_ops
.skip_testsuite(name
, skipreason
)
347 todo
.append(testsuite
+ (match
,))
349 if restricted_mgr
is not None:
350 for name
in restricted_mgr
.iter_unused():
351 sys
.stdout
.write("No test or testsuite found matching %s\n" % name
)
353 sys
.stderr
.write("No tests to run\n")
356 suitestotal
= len(todo
)
359 subunit_ops
.progress(suitestotal
, subunit
.PROGRESS_SET
)
360 subunit_ops
.time(now())
367 # domain controller stuff
376 "MEMBER_NETBIOSNAME",
377 "MEMBER_NETBIOSALIAS",
379 # rpc proxy controller stuff
381 "RPC_PROXY_SERVER_IP",
382 "RPC_PROXY_NETBIOSNAME",
383 "RPC_PROXY_NETBIOSALIAS",
385 # domain controller stuff for Vampired DC
387 "VAMPIRE_DC_SERVER_IP",
388 "VAMPIRE_DC_NETBIOSNAME",
389 "VAMPIRE_DC_NETBIOSALIAS",
391 # domain controller stuff for Vampired DC
392 "PROMOTED_DC_SERVER",
393 "PROMOTED_DC_SERVER_IP",
394 "PROMOTED_DC_NETBIOSNAME",
395 "PROMOTED_DC_NETBIOSALIAS",
412 "WINBINDD_SOCKET_DIR",
413 "WINBINDD_PRIV_PIPE_DIR",
418 def switch_env(name
, prefix
):
420 (envname
, option
) = name
.split(":", 1)
425 env
= env_manager
.setup_env(envname
, prefix
)
427 testenv_vars
= env
.get_vars()
429 if option
== "local":
430 socket_wrapper
.set_default_iface(testenv_vars
["SOCKET_WRAPPER_DEFAULT_IFACE"])
431 os
.environ
["SMB_CONF_PATH"] = testenv_vars
["SERVERCONFFILE"]
432 elif option
== "client":
433 socket_wrapper
.set_default_iface(11)
434 write_clientconf(conffile
, clientdir
, testenv_vars
)
435 os
.environ
["SMB_CONF_PATH"] = conffile
437 raise Exception("Unknown option[%s] for envname[%s]" % (option
,
440 for name
in exported_envvars
:
441 if name
in testenv_vars
:
442 os
.environ
[name
] = testenv_vars
[name
]
443 elif name
in os
.environ
:
448 # This 'global' file needs to be empty when we start
449 dns_host_file_path
= os
.path
.join(prefix_abs
, "dns_host_file")
450 if os
.path
.exists(dns_host_file_path
):
451 os
.unlink(dns_host_file_path
)
454 testenv_name
= os
.environ
.get("SELFTEST_TESTENV", testenv_default
)
456 env
= switch_env(testenv_name
, prefix
)
457 testenv_vars
= env
.get_vars()
459 os
.environ
["PIDDIR"] = testenv_vars
["PIDDIR"]
460 os
.environ
["ENVNAME"] = testenv_name
462 envvarstr
= exported_envvars_str(testenv_vars
, exported_envvars
)
464 term
= os
.environ
.get("TERMINAL", "xterm -e")
466 Welcome to the Samba4 Test environment '%(testenv_name)'
468 This matches the client environment used in make test
469 server is pid `cat \$PIDDIR/samba.pid`
471 Some useful environment variables:
472 TORTURE_OPTIONS=\$TORTURE_OPTIONS
473 SMB_CONF_PATH=\$SMB_CONF_PATH
476 \" && LD_LIBRARY_PATH=%(LD_LIBRARY_PATH)s $(SHELL)'""" % {
477 "testenv_name": testenv_name
,
478 "LD_LIBRARY_PATH": os
.environ
["LD_LIBRARY_PATH"]}
479 subprocess
.call(term
+ ' ' + cmd
, shell
=True)
480 env_manager
.teardown_env(testenv_name
)
482 for (name
, envname
, cmd
, supports_loadfile
, supports_idlist
, subtests
) in todo
:
483 cmd
= expand_command_list(cmd
)
485 warnings
.warn("Unable to list tests in %s" % name
)
488 exitcode
= subprocess
.call(cmd
, shell
=True)
491 sys
.stderr
.write("%s exited with exit code %s\n" % (cmd
, exitcode
))
494 for (name
, envname
, cmd
, supports_loadfile
, supports_idlist
, subtests
) in todo
:
496 env
= switch_env(envname
, prefix
)
497 except UnsupportedEnvironment
:
498 subunit_ops
.start_testsuite(name
)
499 subunit_ops
.end_testsuite(name
, "skip",
500 "environment %s is unknown in this test backend - skipping" % envname
)
503 subunit_ops
.start_testsuite(name
)
504 traceback
.print_exc()
505 subunit_ops
.end_testsuite(name
, "error",
506 "unable to set up environment %s: %s" % (envname
, e
))
509 cmd
, tmpf
= expand_command_run(cmd
, supports_loadfile
, supports_idlist
,
512 run_testsuite(name
, cmd
, subunit_ops
, env
=env
)
517 if opts
.resetup_environment
:
518 env_manager
.teardown_env(envname
)
519 env_manager
.teardown_all()
521 sys
.stdout
.write("\n")
523 # if there were any valgrind failures, show them
524 for fn
in os
.listdir(prefix
):
525 if fn
.startswith("valgrind.log"):
526 sys
.stdout
.write("VALGRIND FAILURE\n")
527 f
= open(os
.path
.join(prefix
, fn
), 'r')
529 sys
.stdout
.write(f
.read())