source: vendor/current/selftest/selftest.py@ 1075

Last change on this file since 1075 was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 16.0 KB
Line 
1#!/usr/bin/python -u
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>
5
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.
10
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.
15
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/>.
18
19import atexit
20from cStringIO import StringIO
21import os
22import sys
23import signal
24import subprocess
25from samba import subunit
26import traceback
27import warnings
28
29import optparse
30
31sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
32
33from selftest import (
34 socket_wrapper,
35 subunithelper,
36 testlist,
37 )
38from selftest.client import write_clientconf
39from selftest.run import (
40 expand_command_list,
41 expand_command_run,
42 exported_envvars_str,
43 now,
44 run_testsuite_command,
45 )
46from selftest.target import (
47 EnvironmentManager,
48 NoneTarget,
49 UnsupportedEnvironment,
50 )
51
52includes = ()
53excludes = ()
54
55def read_excludes(fn):
56 excludes.extend(testlist.read_test_regexes(fn))
57
58def read_includes(fn):
59 includes.extend(testlist.read_test_regexes(fn))
60
61parser = optparse.OptionParser("TEST-REGEXES")
62parser.add_option("--target", type="choice", choices=["samba", "samba3", "none"], default="samba", help="Samba version to target")
63parser.add_option("--quick", help="run quick overall test", action="store_true", default=False)
64parser.add_option("--list", help="list available tests", action="store_true", default=False)
65parser.add_option("--socket-wrapper", help="enable socket wrapper", action="store_true", default=False)
66parser.add_option("--socket-wrapper-pcap", help="save traffic to pcap directories", type="str")
67parser.add_option("--socket-wrapper-keep-pcap", help="keep all pcap files, not just those for tests that failed", action="store_true", default=False)
68parser.add_option("--one", help="abort when the first test fails", action="store_true", default=False)
69parser.add_option("--exclude", action="callback", help="Add file to exclude files", callback=read_excludes)
70parser.add_option("--include", action="callback", help="Add file to include files", callback=read_includes)
71parser.add_option("--testenv", help="run a shell in the requested test environment", action="store_true", default=False)
72parser.add_option("--resetup-environment", help="Re-setup environment", action="store_true", default=False)
73parser.add_option("--load-list", help="Load list of tests to load from a file", type=str)
74parser.add_option("--prefix", help="prefix to run tests in", type=str, default="./st")
75parser.add_option("--srcdir", type=str, default=".", help="source directory")
76parser.add_option("--bindir", type=str, default="./bin", help="binaries directory")
77parser.add_option("--testlist", type=str, action="append", help="file to read available tests from")
78parser.add_option("--ldap", help="back samba onto specified ldap server", choices=["openldap", "fedora-ds"], type="choice")
79
80opts, args = parser.parse_args()
81
82subunit_ops = subunithelper.SubunitOps(sys.stdout)
83
84def handle_signal(sig, frame):
85 sys.stderr.write("Exiting early because of signal %s.\n" % sig)
86 sys.exit(1)
87
88for sig in (signal.SIGINT, signal.SIGQUIT, signal.SIGTERM, signal.SIGPIPE):
89 signal.signal(sig, handle_signal)
90
91def skip(name):
92 return testlist.find_in_list(excludes, name)
93
94def setup_pcap(name):
95 if (not opts.socket_wrapper_pcap or
96 not os.environ.get("SOCKET_WRAPPER_PCAP_DIR")):
97 return
98
99 fname = "".join([x for x in name if x.isalnum() or x == '-'])
100
101 pcap_file = os.path.join(
102 os.environ["SOCKET_WRAPPER_PCAP_DIR"], "%s.pcap" % fname)
103
104 socket_wrapper.setup_pcap(pcap_file)
105 return pcap_file
106
107
108def cleanup_pcap(pcap_file, exit_code):
109 if not opts.socket_wrapper_pcap:
110 return
111 if opts.socket_wrapper_keep_pcap:
112 return
113 if exitcode == 0:
114 return
115 if pcap_file is None:
116 return
117
118 os.unlink(pcap_file)
119
120
121def run_testsuite(name, cmd, subunit_ops, env=None):
122 """Run a single testsuite.
123
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
128 """
129 pcap_file = setup_pcap(name)
130
131 exitcode = run_testsuite_command(name, cmd, subunit_ops, env)
132 if exitcode is None:
133 sys.exit(1)
134
135 cleanup_pcap(pcap_file, exitcode)
136
137 if not opts.socket_wrapper_keep_pcap and pcap_file is not None:
138 sys.stdout.write("PCAP FILE: %s\n" % pcap_file)
139
140 if exitcode != 0 and opts.one:
141 sys.exit(1)
142
143 return exitcode
144
145
146if opts.list and opts.testenv:
147 sys.stderr.write("--list and --testenv are mutually exclusive\n")
148 sys.exit(1)
149
150tests = args
151
152# quick hack to disable rpc validation when using valgrind - it is way too slow
153if not os.environ.get("VALGRIND"):
154 os.environ["VALIDATE"] = "validate"
155 os.environ["MALLOC_CHECK_"] = "3"
156
157# make all our python scripts unbuffered
158os.environ["PYTHONUNBUFFERED"] = "1"
159
160bindir_abs = os.path.abspath(opts.bindir)
161
162# Backwards compatibility:
163if os.environ.get("TEST_LDAP") == "yes":
164 if os.environ.get("FEDORA_DS_ROOT"):
165 ldap = "fedora-ds"
166 else:
167 ldap = "openldap"
168
169torture_maxtime = int(os.getenv("TORTURE_MAXTIME", "1200"))
170if opts.ldap:
171 # LDAP is slow
172 torture_maxtime *= 2
173
174prefix = os.path.normpath(opts.prefix)
175
176# Ensure we have the test prefix around.
177#
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.
181if not os.path.isdir(prefix):
182 os.mkdir(prefix, 0700)
183else:
184 os.chmod(prefix, 0700)
185
186prefix_abs = os.path.abspath(prefix)
187tmpdir_abs = os.path.abspath(os.path.join(prefix_abs, "tmp"))
188if not os.path.isdir(tmpdir_abs):
189 os.mkdir(tmpdir_abs, 0777)
190
191srcdir_abs = os.path.abspath(opts.srcdir)
192
193if prefix_abs == "/":
194 raise Exception("using '/' as absolute prefix is a bad idea")
195
196os.environ["PREFIX"] = prefix
197os.environ["KRB5CCNAME"] = os.path.join(prefix, "krb5ticket")
198os.environ["PREFIX_ABS"] = prefix_abs
199os.environ["SRCDIR"] = opts.srcdir
200os.environ["SRCDIR_ABS"] = srcdir_abs
201os.environ["BINDIR"] = bindir_abs
202
203tls_enabled = not opts.quick
204if tls_enabled:
205 os.environ["TLS_ENABLED"] = "yes"
206else:
207 os.environ["TLS_ENABLED"] = "no"
208
209def prefix_pathvar(name, newpath):
210 if name in os.environ:
211 os.environ[name] = "%s:%s" % (newpath, os.environ[name])
212 else:
213 os.environ[name] = newpath
214prefix_pathvar("PKG_CONFIG_PATH", os.path.join(bindir_abs, "pkgconfig"))
215prefix_pathvar("PYTHONPATH", os.path.join(bindir_abs, "python"))
216
217if opts.socket_wrapper_keep_pcap:
218 # Socket wrapper keep pcap implies socket wrapper pcap
219 opts.socket_wrapper_pcap = True
220
221if opts.socket_wrapper_pcap:
222 # Socket wrapper pcap implies socket wrapper
223 opts.socket_wrapper = True
224
225if 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)
228elif not opts.list:
229 if os.getuid() != 0:
230 warnings.warn("not using socket wrapper, but also not running as root. Will not be able to listen on proper ports")
231
232testenv_default = "none"
233
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
236# long
237
238if os.environ.get("SMBD_MAXTIME", ""):
239 server_maxtime = int(os.environ["SMBD_MAXTIME"])
240else:
241 server_maxtime = 7500
242
243
244def has_socket_wrapper(bindir):
245 """Check if Samba has been built with socket wrapper support.
246 """
247 f = StringIO()
248 subprocess.check_call([os.path.join(bindir, "smbd"), "-b"], stdout=f)
249 for l in f.readlines():
250 if "SOCKET_WRAPPER" in l:
251 return True
252 return False
253
254
255if not opts.list:
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")
259 sys.exit(1)
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")
266 sys.exit(1)
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()
273
274 env_manager = EnvironmentManager(target)
275 atexit.register(env_manager.teardown_all)
276
277interfaces = ",".join([
278 "127.0.0.11/8",
279 "127.0.0.12/8",
280 "127.0.0.13/8",
281 "127.0.0.14/8",
282 "127.0.0.15/8",
283 "127.0.0.16/8"])
284
285clientdir = os.path.join(prefix_abs, "client")
286
287conffile = os.path.join(clientdir, "client.conf")
288os.environ["SMB_CONF_PATH"] = conffile
289
290todo = []
291
292if not opts.testlist:
293 sys.stderr.write("No testlists specified\n")
294 sys.exit(1)
295
296os.environ["SELFTEST_PREFIX"] = prefix_abs
297os.environ["SELFTEST_TMPDIR"] = tmpdir_abs
298os.environ["TEST_DATA_PREFIX"] = tmpdir_abs
299if opts.socket_wrapper:
300 os.environ["SELFTEST_INTERFACES"] = interfaces
301else:
302 os.environ["SELFTEST_INTERFACES"] = ""
303if opts.quick:
304 os.environ["SELFTEST_QUICK"] = "1"
305else:
306 os.environ["SELFTEST_QUICK"] = ""
307os.environ["SELFTEST_MAXTIME"] = str(torture_maxtime)
308
309
310available = []
311for fn in opts.testlist:
312 for testsuite in testlist.read_testlist_file(fn):
313 if not testlist.should_run_test(tests, testsuite):
314 continue
315 name = testsuite[0]
316 if (includes is not None and
317 testlist.find_in_list(includes, name) is not None):
318 continue
319 available.append(testsuite)
320
321if opts.load_list:
322 restricted_mgr = testlist.RestrictedTestManager.from_path(opts.load_list)
323else:
324 restricted_mgr = None
325
326for testsuite in available:
327 name = testsuite[0]
328 skipreason = skip(name)
329 if restricted_mgr is not None:
330 match = restricted_mgr.should_run_testsuite(name)
331 if match == []:
332 continue
333 else:
334 match = None
335 if skipreason is not None:
336 if not opts.list:
337 subunit_ops.skip_testsuite(name, skipreason)
338 else:
339 todo.append(testsuite + (match,))
340
341if 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)
344if todo == []:
345 sys.stderr.write("No tests to run\n")
346 sys.exit(1)
347
348suitestotal = len(todo)
349
350if not opts.list:
351 subunit_ops.progress(suitestotal, subunit.PROGRESS_SET)
352 subunit_ops.time(now())
353
354exported_envvars = [
355 # domain stuff
356 "DOMAIN",
357 "REALM",
358
359 # domain controller stuff
360 "DC_SERVER",
361 "DC_SERVER_IP",
362 "DC_NETBIOSNAME",
363 "DC_NETBIOSALIAS",
364
365 # domain member
366 "MEMBER_SERVER",
367 "MEMBER_SERVER_IP",
368 "MEMBER_NETBIOSNAME",
369 "MEMBER_NETBIOSALIAS",
370
371 # rpc proxy controller stuff
372 "RPC_PROXY_SERVER",
373 "RPC_PROXY_SERVER_IP",
374 "RPC_PROXY_NETBIOSNAME",
375 "RPC_PROXY_NETBIOSALIAS",
376
377 # domain controller stuff for Vampired DC
378 "VAMPIRE_DC_SERVER",
379 "VAMPIRE_DC_SERVER_IP",
380 "VAMPIRE_DC_NETBIOSNAME",
381 "VAMPIRE_DC_NETBIOSALIAS",
382
383 # domain controller stuff for Vampired DC
384 "PROMOTED_DC_SERVER",
385 "PROMOTED_DC_SERVER_IP",
386 "PROMOTED_DC_NETBIOSNAME",
387 "PROMOTED_DC_NETBIOSALIAS",
388
389 # server stuff
390 "SERVER",
391 "SERVER_IP",
392 "NETBIOSNAME",
393 "NETBIOSALIAS",
394
395 # user stuff
396 "USERNAME",
397 "USERID",
398 "PASSWORD",
399 "DC_USERNAME",
400 "DC_PASSWORD",
401
402 # misc stuff
403 "KRB5_CONFIG",
404 "WINBINDD_SOCKET_DIR",
405 "WINBINDD_PRIV_PIPE_DIR",
406 "NMBD_SOCKET_DIR",
407 "LOCAL_PATH"
408]
409
410def switch_env(name, prefix):
411 if ":" in name:
412 (envname, option) = name.split(":", 1)
413 else:
414 envname = name
415 option = "client"
416
417 env = env_manager.setup_env(envname, prefix)
418
419 testenv_vars = env.get_vars()
420
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
428 else:
429 raise Exception("Unknown option[%s] for envname[%s]" % (option,
430 envname))
431
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:
436 del os.environ[name]
437
438 return env
439
440# This 'global' file needs to be empty when we start
441dns_host_file_path = os.path.join(prefix_abs, "dns_host_file")
442if os.path.exists(dns_host_file_path):
443 os.unlink(dns_host_file_path)
444
445if opts.testenv:
446 testenv_name = os.environ.get("SELFTEST_TESTENV", testenv_default)
447
448 env = switch_env(testenv_name, prefix)
449 testenv_vars = env.get_vars()
450
451 os.environ["PIDDIR"] = testenv_vars["PIDDIR"]
452 os.environ["ENVNAME"] = testenv_name
453
454 envvarstr = exported_envvars_str(testenv_vars, exported_envvars)
455
456 term = os.environ.get("TERMINAL", "xterm -e")
457 cmd = """'echo -e "
458Welcome to the Samba4 Test environment '%(testenv_name)'
459
460This matches the client environment used in make test
461server is pid `cat \$PIDDIR/samba.pid`
462
463Some useful environment variables:
464TORTURE_OPTIONS=\$TORTURE_OPTIONS
465SMB_CONF_PATH=\$SMB_CONF_PATH
466
467$envvarstr
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)
473elif opts.list:
474 for (name, envname, cmd, supports_loadfile, supports_idlist, subtests) in todo:
475 cmd = expand_command_list(cmd)
476 if cmd is None:
477 warnings.warn("Unable to list tests in %s" % name)
478 continue
479
480 exitcode = subprocess.call(cmd, shell=True)
481
482 if exitcode != 0:
483 sys.stderr.write("%s exited with exit code %s\n" % (cmd, exitcode))
484 sys.exit(1)
485else:
486 for (name, envname, cmd, supports_loadfile, supports_idlist, subtests) in todo:
487 try:
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)
493 continue
494 except Exception, e:
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))
499 continue
500
501 cmd, tmpf = expand_command_run(cmd, supports_loadfile, supports_idlist,
502 subtests)
503
504 run_testsuite(name, cmd, subunit_ops, env=env)
505
506 if tmpf is not None:
507 os.remove(tmpf)
508
509 if opts.resetup_environment:
510 env_manager.teardown_env(envname)
511 env_manager.teardown_all()
512
513sys.stdout.write("\n")
514
515# if there were any valgrind failures, show them
516for 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')
520 try:
521 sys.stdout.write(f.read())
522 finally:
523 f.close()
524
525sys.exit(0)
Note: See TracBrowser for help on using the repository browser.