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
33 sys
.path
.insert(0, os
.path
.dirname(os
.path
.dirname(__file__
)))
35 from selftest
import (
40 from selftest
.client
import write_clientconf
41 from selftest
.run
import (
42 expand_environment_strings
,
47 from selftest
.target
import (
50 UnsupportedEnvironment
,
57 return datetime
.datetime
.utcnow().replace(tzinfo
=iso8601
.iso8601
.Utc())
59 def read_excludes(fn
):
60 excludes
.extend(testlist
.read_test_regexes(fn
))
62 def read_includes(fn
):
63 includes
.extend(testlist
.read_test_regexes(fn
))
65 parser
= optparse
.OptionParser("TEST-REGEXES")
66 parser
.add_option("--target", type="choice", choices
=["samba", "samba3", "none"], default
="samba", help="Samba version to target")
67 parser
.add_option("--quick", help="run quick overall test", action
="store_true", default
=False)
68 parser
.add_option("--list", help="list available tests", action
="store_true", default
=False)
69 parser
.add_option("--socket-wrapper", help="enable socket wrapper", action
="store_true", default
=False)
70 parser
.add_option("--socket-wrapper-pcap", help="save traffic to pcap directories", type="str")
71 parser
.add_option("--socket-wrapper-keep-pcap", help="keep all pcap files, not just those for tests that failed", action
="store_true", default
=False)
72 parser
.add_option("--one", help="abort when the first test fails", action
="store_true", default
=False)
73 parser
.add_option("--exclude", action
="callback", help="Add file to exclude files", callback
=read_excludes
)
74 parser
.add_option("--include", action
="callback", help="Add file to include files", callback
=read_includes
)
75 parser
.add_option("--testenv", help="run a shell in the requested test environment", action
="store_true", default
=False)
76 parser
.add_option("--resetup-environment", help="Re-setup environment", action
="store_true", default
=False)
77 parser
.add_option("--binary-mapping", help="Map binaries to use", type=str)
78 parser
.add_option("--load-list", help="Load list of tests to load from a file", type=str)
79 parser
.add_option("--prefix", help="prefix to run tests in", type=str, default
="./st")
80 parser
.add_option("--srcdir", type=str, default
=".", help="source directory")
81 parser
.add_option("--bindir", type=str, default
="./bin", help="binaries directory")
82 parser
.add_option("--testlist", type=str, action
="append", help="file to read available tests from")
83 parser
.add_option("--ldap", help="back samba onto specified ldap server", choices
=["openldap", "fedora-ds"], type="choice")
85 opts
, args
= parser
.parse_args()
87 subunit_ops
= subunithelper
.SubunitOps(sys
.stdout
)
89 def handle_signal(sig
, frame
):
90 sys
.stderr
.write("Exiting early because of signal %s.\n" % sig
)
93 for sig
in (signal
.SIGINT
, signal
.SIGQUIT
, signal
.SIGTERm
, signal
.SIGPIPE
):
94 signal
.signal(sig
, handle_signal
)
97 return testlist
.find_in_list(excludes
, name
)
100 if (not opts
.socket_wrapper_pcap
or
101 not os
.environ
.get("SOCKET_WRAPPER_PCAP_DIR")):
104 fname
= "".join([x
for x
in name
if x
.isalnum() or x
== '-'])
106 pcap_file
= os
.path
.join(
107 os
.environ
["SOCKET_WRAPPER_PCAP_DIR"], "%s.pcap" % fname
)
109 socket_wrapper
.setup_pcap(pcap_file
)
113 def cleanup_pcap(pcap_file
, exit_code
):
114 if not opts
.socket_wrapper_pcap
:
116 if opts
.socket_wrapper_keep_pcap
:
120 if pcap_file
is None:
126 def run_testsuite(envname
, name
, cmd
):
127 """Run a single testsuite.
129 :param envname: Name of the environment to ru nin
130 :param name: Name of the testsuite
131 :param cmd: Name of the (fully expanded) command to run
132 :return: exitcode of the command
134 pcap_file
= setup_pcap(name
)
136 subunit_ops
.start_testsuite(name
)
137 subunit_ops
.progress(None, subunit
.PROGRESS_PUSH
)
138 subunit_ops
.time(now())
140 exitcode
= subprocess
.call(cmd
, shell
=True)
142 subunit_ops
.time(now())
143 subunit_ops
.progress(None, subunit
.PROGRESS_POP
)
144 subunit_ops
.end_testsuite(name
, "error", "Unable to run %r: %s" % (cmd
, e
))
147 subunit_ops
.time(now())
148 subunit_ops
.progress(None, subunit
.PROGRESS_POP
)
150 envlog
= env_manager
.getlog_env(envname
)
152 sys
.stdout
.write("envlog: %s\n" % envlog
)
154 sys
.stdout
.write("command: %s\n" % cmd
)
155 sys
.stdout
.write("expanded command: %s\n" % expand_environment_strings(cmd
, os
.environ
))
158 subunit_ops
.end_testsuite(name
, "success")
160 subunit_ops
.end_testsuite(name
, "failure", "Exit code was %d" % exitcode
)
162 cleanup_pcap(pcap_file
, exitcode
)
164 if not opts
.socket_wrapper_keep_pcap
and pcap_file
is not None:
165 sys
.stdout
.write("PCAP FILE: %s\n" % pcap_file
)
167 if exitcode
!= 0 and opts
.one
:
172 if opts
.list and opts
.testenv
:
173 sys
.stderr
.write("--list and --testenv are mutually exclusive\n")
178 # quick hack to disable rpc validation when using valgrind - it is way too slow
179 if not os
.environ
.get("VALGRIND"):
180 os
.environ
["VALIDATE"] = "validate"
181 os
.environ
["MALLOC_CHECK_"] = "2"
183 # make all our python scripts unbuffered
184 os
.environ
["PYTHONUNBUFFERED"] = "1"
186 bindir_abs
= os
.path
.abspath(opts
.bindir
)
188 # Backwards compatibility:
189 if os
.environ
.get("TEST_LDAP") == "yes":
190 if os
.environ
.get("FEDORA_DS_ROOT"):
195 torture_maxtime
= int(os
.getenv("TORTURE_MAXTIME", "1200"))
200 prefix
= os
.path
.normpath(opts
.prefix
)
203 raise Exception("using an empty prefix isn't allowed")
205 # Ensure we have the test prefix around.
207 # We need restrictive permissions on this as some subdirectories in this tree
208 # will have wider permissions (ie 0777) and this would allow other users on the
209 # host to subvert the test process.
210 if not os
.path
.isdir(prefix
):
211 os
.mkdir(prefix
, 0700)
213 os
.chmod(prefix
, 0700)
215 prefix_abs
= os
.path
.abspath(prefix
)
216 tmpdir_abs
= os
.path
.abspath(os
.path
.join(prefix_abs
, "tmp"))
217 if not os
.path
.isdir(tmpdir_abs
):
218 os
.mkdir(tmpdir_abs
, 0777)
220 srcdir_abs
= os
.path
.abspath(opts
.srcdir
)
223 raise Exception("using an empty absolute prefix isn't allowed")
224 if prefix_abs
== "/":
225 raise Exception("using '/' as absolute prefix isn't allowed")
227 os
.environ
["PREFIX"] = prefix
228 os
.environ
["KRB5CCNAME"] = os
.path
.join(prefix
, "krb5ticket")
229 os
.environ
["PREFIX_ABS"] = prefix_abs
230 os
.environ
["SRCDIR"] = opts
.srcdir
231 os
.environ
["SRCDIR_ABS"] = srcdir_abs
232 os
.environ
["BINDIR"] = bindir_abs
234 tls_enabled
= not opts
.quick
236 os
.environ
["TLS_ENABLED"] = "yes"
238 os
.environ
["TLS_ENABLED"] = "no"
240 def prefix_pathvar(name
, newpath
):
241 if name
in os
.environ
:
242 os
.environ
[name
] = "%s:%s" % (newpath
, os
.environ
[name
])
244 os
.environ
[name
] = newpath
245 prefix_pathvar("PKG_CONFIG_PATH", os
.path
.join(bindir_abs
, "pkgconfig"))
246 prefix_pathvar("PYTHONPATH", os
.path
.join(bindir_abs
, "python"))
248 if opts
.socket_wrapper_keep_pcap
:
249 # Socket wrapper keep pcap implies socket wrapper pcap
250 opts
.socket_wrapper_pcap
= True
252 if opts
.socket_wrapper_pcap
:
253 # Socket wrapper pcap implies socket wrapper
254 opts
.socket_wrapper
= True
256 if opts
.socket_wrapper
:
257 socket_wrapper_dir
= socket_wrapper
.setup_dir(os
.path
.join(prefix_abs
, "w"), opts
.socket_wrapper_pcap
)
258 sys
.stdout
.write("SOCKET_WRAPPER_DIR=%s\n" % socket_wrapper_dir
)
261 warnings
.warn("not using socket wrapper, but also not running as root. Will not be able to listen on proper ports")
263 testenv_default
= "none"
265 if opts
.binary_mapping
:
266 binary_mapping
= dict([l
.split(":") for l
in opts
.binary_mapping
.split(",")])
267 os
.environ
["BINARY_MAPPING"] = opts
.binary_mapping
270 os
.environ
["BINARY_MAPPING"] = ""
272 # After this many seconds, the server will self-terminate. All tests
273 # must terminate in this time, and testenv will only stay alive this
276 server_maxtime
= 7500
277 if os
.environ
.get("SMBD_MAXTIME", ""):
278 server_maxtime
= int(os
.environ
["SMBD_MAXTIME"])
281 def has_socket_wrapper(bindir
):
282 """Check if Samba has been built with socket wrapper support.
285 subprocess
.check_call([os
.path
.join(bindir
, "smbd"), "-b"], stdout
=f
)
286 for l
in f
.readlines():
287 if "SOCKET_WRAPPER" in l
:
293 if opts
.target
== "samba":
294 if opts
.socket_wrapper
and not has_socket_wrapper(opts
.bindir
):
295 sys
.stderr
.write("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....\n")
297 testenv_default
= "dc"
298 from selftest
.target
.samba
import Samba
299 target
= Samba(opts
.bindir
, binary_mapping
, ldap
, opts
.srcdir
, server_maxtime
)
300 elif opts
.target
== "samba3":
301 if opts
.socket_wrapper
and not has_socket_wrapper(opts
.bindir
):
302 sys
.stderr
.write("You must include --enable-socket-wrapper when compiling Samba in order to execute 'make test'. Exiting....\n")
304 testenv_default
= "member"
305 from selftest
.target
.samba3
import Samba3
306 target
= Samba3(opts
.bindir
, binary_mapping
, srcdir_abs
, server_maxtime
)
307 elif opts
.target
== "none":
308 testenv_default
= "none"
309 target
= NoneTarget()
311 env_manager
= EnvironmentManager(target
)
312 atexit
.register(env_manager
.teardown_all
)
314 interfaces
= ",".join([
322 clientdir
= os
.path
.join(prefix_abs
, "client")
324 conffile
= os
.path
.join(clientdir
, "client.conf")
325 os
.environ
["SMB_CONF_PATH"] = conffile
329 if not opts
.testlist
:
330 sys
.stderr
.write("No testlists specified\n")
333 os
.environ
["SELFTEST_PREFIX"] = prefix_abs
334 os
.environ
["SELFTEST_TMPDIR"] = tmpdir_abs
335 os
.environ
["TEST_DATA_PREFIX"] = tmpdir_abs
336 if opts
.socket_wrapper
:
337 os
.environ
["SELFTEST_INTERFACES"] = interfaces
339 os
.environ
["SELFTEST_INTERFACES"] = ""
341 os
.environ
["SELFTEST_QUICK"] = "1"
343 os
.environ
["SELFTEST_QUICK"] = ""
344 os
.environ
["SELFTEST_MAXTIME"] = str(torture_maxtime
)
348 for fn
in opts
.testlist
:
349 for testsuite
in testlist
.read_testlist_file(fn
):
350 if not testlist
.should_run_test(tests
, testsuite
):
353 if (includes
is not None and
354 testlist
.find_in_list(includes
, name
) is not None):
356 available
.append(testsuite
)
359 restricted_mgr
= testlist
.RestrictedTestManager
.from_path(opts
.load_list
)
361 restricted_mgr
= None
363 for testsuite
in available
:
365 skipreason
= skip(name
)
366 if restricted_mgr
is not None:
367 match
= restricted_mgr
.should_run_testsuite(name
)
372 if skipreason
is not None:
374 subunit_ops
.skip_testsuite(name
, skipreason
)
376 todo
.append(testsuite
+ (match
,))
378 if restricted_mgr
is not None:
379 for name
in restricted_mgr
.iter_unused():
380 sys
.stdout
.write("No test or testsuite found matching %s\n" % name
)
382 sys
.stderr
.write("No tests to run\n")
385 suitestotal
= len(todo
)
388 subunit_ops
.progress(suitestotal
, subunit
.PROGRESS_SET
)
389 subunit_ops
.time(now())
396 # domain controller stuff
405 "MEMBER_NETBIOSNAME",
406 "MEMBER_NETBIOSALIAS",
408 # rpc proxy controller stuff
410 "RPC_PROXY_SERVER_IP",
411 "RPC_PROXY_NETBIOSNAME",
412 "RPC_PROXY_NETBIOSALIAS",
414 # domain controller stuff for Vampired DC
416 "VAMPIRE_DC_SERVER_IP",
417 "VAMPIRE_DC_NETBIOSNAME",
418 "VAMPIRE_DC_NETBIOSALIAS",
435 "WINBINDD_SOCKET_DIR",
436 "WINBINDD_PRIV_PIPE_DIR",
441 def switch_env(name
, prefix
):
443 (envname
, option
) = name
.split(":", 1)
448 env
= env_manager
.setup_env(envname
, prefix
)
450 testenv_vars
= env
.get_vars()
452 if option
== "local":
453 socket_wrapper
.set_default_iface(testenv_vars
["SOCKET_WRAPPER_DEFAULT_IFACE"])
454 os
.environ
["SMB_CONF_PATH"] = testenv_vars
["SERVERCONFFILE"]
455 elif option
== "client":
456 socket_wrapper
.set_default_iface(11)
457 write_clientconf(conffile
, clientdir
, testenv_vars
)
458 os
.environ
["SMB_CONF_PATH"] = conffile
460 raise Exception("Unknown option[%s] for envname[%s]" % (option
,
463 for name
in exported_envvars
:
464 if name
in testenv_vars
:
465 os
.environ
[name
] = testenv_vars
[name
]
466 elif name
in os
.environ
:
471 # This 'global' file needs to be empty when we start
472 dns_host_file_path
= os
.path
.join(prefix_abs
, "dns_host_file")
473 if os
.path
.exists(dns_host_file_path
):
474 os
.unlink(dns_host_file_path
)
477 testenv_name
= os
.environ
.get("SELFTEST_TESTENV", testenv_default
)
479 testenv_vars
= switch_env(testenv_name
, prefix
)
481 os
.environ
["PIDDIR"] = testenv_vars
["PIDDIR"]
482 os
.environ
["ENVNAME"] = testenv_name
484 envvarstr
= exported_envvars_str(testenv_vars
, exported_envvars
)
486 term
= os
.environ
.get("TERMINAL", "xterm -e")
488 Welcome to the Samba4 Test environment '%(testenv_name)'
490 This matches the client environment used in make test
491 server is pid `cat \$PIDDIR/samba.pid`
493 Some useful environment variables:
494 TORTURE_OPTIONS=\$TORTURE_OPTIONS
495 SMB_CONF_PATH=\$SMB_CONF_PATH
498 \" && LD_LIBRARY_PATH=%(LD_LIBRARY_PATH)s $(SHELL)'""" % {
499 "testenv_name": testenv_name
,
500 "LD_LIBRARY_PATH": os
.environ
["LD_LIBRARY_PATH"]}
501 subprocess
.call(term
+ ' ' + cmd
, shell
=True)
502 env_manager
.teardown_env(testenv_name
)
504 for (name
, envname
, cmd
, supports_loadfile
, supports_idlist
, subtests
) in todo
:
505 cmd
= expand_command_list(cmd
)
507 warnings
.warn("Unable to list tests in %s" % name
)
510 exitcode
= subprocess
.call(cmd
, shell
=True)
513 sys
.stderr
.write("%s exited with exit code %s\n" % (cmd
, exitcode
))
516 for (name
, envname
, cmd
, supports_loadfile
, supports_idlist
, subtests
) in todo
:
518 envvars
= switch_env(envname
, prefix
)
519 except UnsupportedEnvironment
:
520 subunit_ops
.start_testsuite(name
)
521 subunit_ops
.end_testsuite(name
, "skip",
522 "environment %s is unknown in this test backend - skipping" % envname
)
525 subunit_ops
.start_testsuite(name
)
526 traceback
.print_exc()
527 subunit_ops
.end_testsuite(name
, "error",
528 "unable to set up environment %s: %s" % (envname
, e
))
531 cmd
, tmpf
= expand_command_run(cmd
, supports_loadfile
, supports_idlist
,
534 run_testsuite(envname
, name
, cmd
)
539 if opts
.resetup_environment
:
540 env_manager
.teardown_env(envname
)
541 env_manager
.teardown_all()
543 sys
.stdout
.write("\n")
545 # if there were any valgrind failures, show them
546 for fn
in os
.listdir(prefix
):
547 if fn
.startswith("valgrind.log"):
548 sys
.stdout
.write("VALGRIND FAILURE\n")
549 f
= open(os
.path
.join(prefix
, fn
), 'r')
551 sys
.stdout
.write(f
.read())