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("--load-list", help="Load list of tests to load from a file", type=str)
74 parser
.add_option("--prefix", help="prefix to run tests in", type=str, default
="./st")
75 parser
.add_option("--srcdir", type=str, default
=".", help="source directory")
76 parser
.add_option("--bindir", type=str, default
="./bin", help="binaries directory")
77 parser
.add_option("--testlist", type=str, action
="append", help="file to read available tests from")
78 parser
.add_option("--ldap", help="back samba onto specified ldap server", choices
=["openldap", "fedora-ds"], type="choice")
80 opts
, args
= parser
.parse_args()
82 subunit_ops
= subunithelper
.SubunitOps(sys
.stdout
)
84 def handle_signal(sig
, frame
):
85 sys
.stderr
.write("Exiting early because of signal %s.\n" % sig
)
88 for sig
in (signal
.SIGINT
, signal
.SIGQUIT
, signal
.SIGTERM
, signal
.SIGPIPE
):
89 signal
.signal(sig
, handle_signal
)
92 return testlist
.find_in_list(excludes
, name
)
95 if (not opts
.socket_wrapper_pcap
or
96 not os
.environ
.get("SOCKET_WRAPPER_PCAP_DIR")):
99 fname
= "".join([x
for x
in name
if x
.isalnum() or x
== '-'])
101 pcap_file
= os
.path
.join(
102 os
.environ
["SOCKET_WRAPPER_PCAP_DIR"], "%s.pcap" % fname
)
104 socket_wrapper
.setup_pcap(pcap_file
)
108 def cleanup_pcap(pcap_file
, exit_code
):
109 if not opts
.socket_wrapper_pcap
:
111 if opts
.socket_wrapper_keep_pcap
:
115 if pcap_file
is None:
121 def run_testsuite(name
, cmd
, subunit_ops
, env
=None):
122 """Run a single testsuite.
124 :param env: Environment to run in
125 :param name: Name of the testsuite
126 :param cmd: Name of the (fully expanded) command to run
127 :return: exitcode of the command
129 pcap_file
= setup_pcap(name
)
131 exitcode
= run_testsuite_command(name
, cmd
, subunit_ops
, env
)
135 cleanup_pcap(pcap_file
, exitcode
)
137 if not opts
.socket_wrapper_keep_pcap
and pcap_file
is not None:
138 sys
.stdout
.write("PCAP FILE: %s\n" % pcap_file
)
140 if exitcode
!= 0 and opts
.one
:
146 if opts
.list and opts
.testenv
:
147 sys
.stderr
.write("--list and --testenv are mutually exclusive\n")
152 # quick hack to disable rpc validation when using valgrind - it is way too slow
153 if not os
.environ
.get("VALGRIND"):
154 os
.environ
["VALIDATE"] = "validate"
155 os
.environ
["MALLOC_CHECK_"] = "3"
157 # make all our python scripts unbuffered
158 os
.environ
["PYTHONUNBUFFERED"] = "1"
160 bindir_abs
= os
.path
.abspath(opts
.bindir
)
162 # Backwards compatibility:
163 if os
.environ
.get("TEST_LDAP") == "yes":
164 if os
.environ
.get("FEDORA_DS_ROOT"):
169 torture_maxtime
= int(os
.getenv("TORTURE_MAXTIME", "1200"))
174 prefix
= os
.path
.normpath(opts
.prefix
)
176 # Ensure we have the test prefix around.
178 # We need restrictive permissions on this as some subdirectories in this tree
179 # will have wider permissions (ie 0777) and this would allow other users on the
180 # host to subvert the test process.
181 if not os
.path
.isdir(prefix
):
182 os
.mkdir(prefix
, 0700)
184 os
.chmod(prefix
, 0700)
186 prefix_abs
= os
.path
.abspath(prefix
)
187 tmpdir_abs
= os
.path
.abspath(os
.path
.join(prefix_abs
, "tmp"))
188 if not os
.path
.isdir(tmpdir_abs
):
189 os
.mkdir(tmpdir_abs
, 0777)
191 srcdir_abs
= os
.path
.abspath(opts
.srcdir
)
193 if prefix_abs
== "/":
194 raise Exception("using '/' as absolute prefix is a bad idea")
196 os
.environ
["PREFIX"] = prefix
197 os
.environ
["KRB5CCNAME"] = os
.path
.join(prefix
, "krb5ticket")
198 os
.environ
["PREFIX_ABS"] = prefix_abs
199 os
.environ
["SRCDIR"] = opts
.srcdir
200 os
.environ
["SRCDIR_ABS"] = srcdir_abs
201 os
.environ
["BINDIR"] = bindir_abs
203 tls_enabled
= not opts
.quick
205 os
.environ
["TLS_ENABLED"] = "yes"
207 os
.environ
["TLS_ENABLED"] = "no"
209 def prefix_pathvar(name
, newpath
):
210 if name
in os
.environ
:
211 os
.environ
[name
] = "%s:%s" % (newpath
, os
.environ
[name
])
213 os
.environ
[name
] = newpath
214 prefix_pathvar("PKG_CONFIG_PATH", os
.path
.join(bindir_abs
, "pkgconfig"))
215 prefix_pathvar("PYTHONPATH", os
.path
.join(bindir_abs
, "python"))
217 if opts
.socket_wrapper_keep_pcap
:
218 # Socket wrapper keep pcap implies socket wrapper pcap
219 opts
.socket_wrapper_pcap
= True
221 if opts
.socket_wrapper_pcap
:
222 # Socket wrapper pcap implies socket wrapper
223 opts
.socket_wrapper
= True
225 if opts
.socket_wrapper
:
226 socket_wrapper_dir
= socket_wrapper
.setup_dir(os
.path
.join(prefix_abs
, "w"), opts
.socket_wrapper_pcap
)
227 sys
.stdout
.write("SOCKET_WRAPPER_DIR=%s\n" % socket_wrapper_dir
)
230 warnings
.warn("not using socket wrapper, but also not running as root. Will not be able to listen on proper ports")
232 testenv_default
= "none"
234 # After this many seconds, the server will self-terminate. All tests
235 # must terminate in this time, and testenv will only stay alive this
238 if os
.environ
.get("SMBD_MAXTIME", ""):
239 server_maxtime
= int(os
.environ
["SMBD_MAXTIME"])
241 server_maxtime
= 7500
244 def has_socket_wrapper(bindir
):
245 """Check if Samba has been built with socket wrapper support.
248 subprocess
.check_call([os
.path
.join(bindir
, "smbd"), "-b"], stdout
=f
)
249 for l
in f
.readlines():
250 if "SOCKET_WRAPPER" in l
:
256 if opts
.target
== "samba":
257 if opts
.socket_wrapper
and not has_socket_wrapper(opts
.bindir
):
258 sys
.stderr
.write("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....\n")
260 testenv_default
= "ad_dc_ntvfs"
261 from selftest
.target
.samba
import Samba
262 target
= Samba(opts
.bindir
, ldap
, opts
.srcdir
, server_maxtime
)
263 elif opts
.target
== "samba3":
264 if opts
.socket_wrapper
and not has_socket_wrapper(opts
.bindir
):
265 sys
.stderr
.write("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....\n")
267 testenv_default
= "member"
268 from selftest
.target
.samba3
import Samba3
269 target
= Samba3(opts
.bindir
, srcdir_abs
, server_maxtime
)
270 elif opts
.target
== "none":
271 testenv_default
= "none"
272 target
= NoneTarget()
274 env_manager
= EnvironmentManager(target
)
275 atexit
.register(env_manager
.teardown_all
)
277 interfaces
= ",".join([
285 clientdir
= os
.path
.join(prefix_abs
, "client")
287 conffile
= os
.path
.join(clientdir
, "client.conf")
288 os
.environ
["SMB_CONF_PATH"] = conffile
292 if not opts
.testlist
:
293 sys
.stderr
.write("No testlists specified\n")
296 os
.environ
["SELFTEST_PREFIX"] = prefix_abs
297 os
.environ
["SELFTEST_TMPDIR"] = tmpdir_abs
298 os
.environ
["TEST_DATA_PREFIX"] = tmpdir_abs
299 if opts
.socket_wrapper
:
300 os
.environ
["SELFTEST_INTERFACES"] = interfaces
302 os
.environ
["SELFTEST_INTERFACES"] = ""
304 os
.environ
["SELFTEST_QUICK"] = "1"
306 os
.environ
["SELFTEST_QUICK"] = ""
307 os
.environ
["SELFTEST_MAXTIME"] = str(torture_maxtime
)
311 for fn
in opts
.testlist
:
312 for testsuite
in testlist
.read_testlist_file(fn
):
313 if not testlist
.should_run_test(tests
, testsuite
):
316 if (includes
is not None and
317 testlist
.find_in_list(includes
, name
) is not None):
319 available
.append(testsuite
)
322 restricted_mgr
= testlist
.RestrictedTestManager
.from_path(opts
.load_list
)
324 restricted_mgr
= None
326 for testsuite
in available
:
328 skipreason
= skip(name
)
329 if restricted_mgr
is not None:
330 match
= restricted_mgr
.should_run_testsuite(name
)
335 if skipreason
is not None:
337 subunit_ops
.skip_testsuite(name
, skipreason
)
339 todo
.append(testsuite
+ (match
,))
341 if restricted_mgr
is not None:
342 for name
in restricted_mgr
.iter_unused():
343 sys
.stdout
.write("No test or testsuite found matching %s\n" % name
)
345 sys
.stderr
.write("No tests to run\n")
348 suitestotal
= len(todo
)
351 subunit_ops
.progress(suitestotal
, subunit
.PROGRESS_SET
)
352 subunit_ops
.time(now())
359 # domain controller stuff
368 "MEMBER_NETBIOSNAME",
369 "MEMBER_NETBIOSALIAS",
371 # rpc proxy controller stuff
373 "RPC_PROXY_SERVER_IP",
374 "RPC_PROXY_NETBIOSNAME",
375 "RPC_PROXY_NETBIOSALIAS",
377 # domain controller stuff for Vampired DC
379 "VAMPIRE_DC_SERVER_IP",
380 "VAMPIRE_DC_NETBIOSNAME",
381 "VAMPIRE_DC_NETBIOSALIAS",
383 # domain controller stuff for Vampired DC
384 "PROMOTED_DC_SERVER",
385 "PROMOTED_DC_SERVER_IP",
386 "PROMOTED_DC_NETBIOSNAME",
387 "PROMOTED_DC_NETBIOSALIAS",
404 "WINBINDD_SOCKET_DIR",
405 "WINBINDD_PRIV_PIPE_DIR",
410 def switch_env(name
, prefix
):
412 (envname
, option
) = name
.split(":", 1)
417 env
= env_manager
.setup_env(envname
, prefix
)
419 testenv_vars
= env
.get_vars()
421 if option
== "local":
422 socket_wrapper
.set_default_iface(testenv_vars
["SOCKET_WRAPPER_DEFAULT_IFACE"])
423 os
.environ
["SMB_CONF_PATH"] = testenv_vars
["SERVERCONFFILE"]
424 elif option
== "client":
425 socket_wrapper
.set_default_iface(11)
426 write_clientconf(conffile
, clientdir
, testenv_vars
)
427 os
.environ
["SMB_CONF_PATH"] = conffile
429 raise Exception("Unknown option[%s] for envname[%s]" % (option
,
432 for name
in exported_envvars
:
433 if name
in testenv_vars
:
434 os
.environ
[name
] = testenv_vars
[name
]
435 elif name
in os
.environ
:
440 # This 'global' file needs to be empty when we start
441 dns_host_file_path
= os
.path
.join(prefix_abs
, "dns_host_file")
442 if os
.path
.exists(dns_host_file_path
):
443 os
.unlink(dns_host_file_path
)
446 testenv_name
= os
.environ
.get("SELFTEST_TESTENV", testenv_default
)
448 env
= switch_env(testenv_name
, prefix
)
449 testenv_vars
= env
.get_vars()
451 os
.environ
["PIDDIR"] = testenv_vars
["PIDDIR"]
452 os
.environ
["ENVNAME"] = testenv_name
454 envvarstr
= exported_envvars_str(testenv_vars
, exported_envvars
)
456 term
= os
.environ
.get("TERMINAL", "xterm -e")
458 Welcome to the Samba4 Test environment '%(testenv_name)'
460 This matches the client environment used in make test
461 server is pid `cat \$PIDDIR/samba.pid`
463 Some useful environment variables:
464 TORTURE_OPTIONS=\$TORTURE_OPTIONS
465 SMB_CONF_PATH=\$SMB_CONF_PATH
468 \" && LD_LIBRARY_PATH=%(LD_LIBRARY_PATH)s $(SHELL)'""" % {
469 "testenv_name": testenv_name
,
470 "LD_LIBRARY_PATH": os
.environ
["LD_LIBRARY_PATH"]}
471 subprocess
.call(term
+ ' ' + cmd
, shell
=True)
472 env_manager
.teardown_env(testenv_name
)
474 for (name
, envname
, cmd
, supports_loadfile
, supports_idlist
, subtests
) in todo
:
475 cmd
= expand_command_list(cmd
)
477 warnings
.warn("Unable to list tests in %s" % name
)
480 exitcode
= subprocess
.call(cmd
, shell
=True)
483 sys
.stderr
.write("%s exited with exit code %s\n" % (cmd
, exitcode
))
486 for (name
, envname
, cmd
, supports_loadfile
, supports_idlist
, subtests
) in todo
:
488 env
= switch_env(envname
, prefix
)
489 except UnsupportedEnvironment
:
490 subunit_ops
.start_testsuite(name
)
491 subunit_ops
.end_testsuite(name
, "skip",
492 "environment %s is unknown in this test backend - skipping" % envname
)
495 subunit_ops
.start_testsuite(name
)
496 traceback
.print_exc()
497 subunit_ops
.end_testsuite(name
, "error",
498 "unable to set up environment %s: %s" % (envname
, e
))
501 cmd
, tmpf
= expand_command_run(cmd
, supports_loadfile
, supports_idlist
,
504 run_testsuite(name
, cmd
, subunit_ops
, env
=env
)
509 if opts
.resetup_environment
:
510 env_manager
.teardown_env(envname
)
511 env_manager
.teardown_all()
513 sys
.stdout
.write("\n")
515 # if there were any valgrind failures, show them
516 for fn
in os
.listdir(prefix
):
517 if fn
.startswith("valgrind.log"):
518 sys
.stdout
.write("VALGRIND FAILURE\n")
519 f
= open(os
.path
.join(prefix
, fn
), 'r')
521 sys
.stdout
.write(f
.read())