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())