2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "lib/cmdline/popt_common.h"
24 #include "system/time.h"
25 #include "system/wait.h"
26 #include "system/filesys.h"
27 #include "system/readline.h"
28 #include "lib/smbreadline/smbreadline.h"
29 #include "libcli/libcli.h"
30 #include "lib/ldb/include/ldb.h"
31 #include "lib/events/events.h"
32 #include "dynconfig.h"
34 #include "torture/torture.h"
36 #include "lib/util/dlinklist.h"
37 #include "librpc/rpc/dcerpc.h"
39 static bool run_matching(struct torture_context *torture,
42 struct torture_suite *suite,
48 struct torture_suite *o;
50 for (o = torture_root->children; o; o = o->next) {
51 if (gen_fnmatch(expr, o->name) == 0) {
54 ret &= torture_run_suite(torture, o);
58 ret &= run_matching(torture, o->name, expr, o, matched);
62 struct torture_suite *c;
63 struct torture_tcase *t;
65 for (c = suite->children; c; c = c->next) {
66 asprintf(&name, "%s-%s", prefix, c->name);
68 if (gen_fnmatch(expr, name) == 0) {
71 torture->active_testname = talloc_strdup(torture, prefix);
72 ret &= torture_run_suite(torture, c);
77 ret &= run_matching(torture, name, expr, c, matched);
82 for (t = suite->testcases; t; t = t->next) {
83 asprintf(&name, "%s-%s", prefix, t->name);
84 if (gen_fnmatch(expr, name) == 0) {
87 torture->active_testname = talloc_strdup(torture, prefix);
88 ret &= torture_run_tcase(torture, t);
89 talloc_free(torture->active_testname);
98 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
100 /****************************************************************************
101 run a specified test or "ALL"
102 ****************************************************************************/
103 static bool run_test(struct torture_context *torture, const char *name)
106 bool matched = false;
107 struct torture_suite *o;
109 if (strequal(name, "ALL")) {
110 for (o = torture_root->children; o; o = o->next) {
111 ret &= torture_run_suite(torture, o);
116 ret = run_matching(torture, NULL, name, NULL, &matched);
119 printf("Unknown torture operation '%s'\n", name);
126 static void parse_dns(const char *dns)
128 char *userdn, *basedn, *secret;
131 /* retrievieng the userdn */
132 p = strchr_m(dns, '#');
134 lp_set_cmdline("torture:ldap_userdn", "");
135 lp_set_cmdline("torture:ldap_basedn", "");
136 lp_set_cmdline("torture:ldap_secret", "");
139 userdn = strndup(dns, p - dns);
140 lp_set_cmdline("torture:ldap_userdn", userdn);
142 /* retrieve the basedn */
144 p = strchr_m(d, '#');
146 lp_set_cmdline("torture:ldap_basedn", "");
147 lp_set_cmdline("torture:ldap_secret", "");
150 basedn = strndup(d, p - d);
151 lp_set_cmdline("torture:ldap_basedn", basedn);
153 /* retrieve the secret */
156 lp_set_cmdline("torture:ldap_secret", "");
160 lp_set_cmdline("torture:ldap_secret", secret);
162 printf ("%s - %s - %s\n", userdn, basedn, secret);
166 static void usage(poptContext pc)
168 struct torture_suite *o;
169 struct torture_suite *s;
170 struct torture_tcase *t;
173 poptPrintUsage(pc, stdout, 0);
176 printf("The binding format is:\n\n");
178 printf(" TRANSPORT:host[flags]\n\n");
180 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
181 printf(" or ncalrpc for local connections.\n\n");
183 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
184 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
185 printf(" string.\n\n");
187 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
188 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
189 printf(" will be auto-determined.\n\n");
191 printf(" other recognised flags are:\n\n");
193 printf(" sign : enable ntlmssp signing\n");
194 printf(" seal : enable ntlmssp sealing\n");
195 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
196 printf(" validate: enable the NDR validator\n");
197 printf(" print: enable debugging of the packets\n");
198 printf(" bigendian: use bigendian RPC\n");
199 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
201 printf(" For example, these all connect to the samr pipe:\n\n");
203 printf(" ncacn_np:myserver\n");
204 printf(" ncacn_np:myserver[samr]\n");
205 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
206 printf(" ncacn_np:myserver[/pipe/samr]\n");
207 printf(" ncacn_np:myserver[samr,sign,print]\n");
208 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
209 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
210 printf(" ncacn_np:\n");
211 printf(" ncacn_np:[/pipe/samr]\n\n");
213 printf(" ncacn_ip_tcp:myserver\n");
214 printf(" ncacn_ip_tcp:myserver[1024]\n");
215 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
217 printf(" ncalrpc:\n\n");
219 printf("The UNC format is:\n\n");
221 printf(" //server/share\n\n");
223 printf("Tests are:");
225 for (o = torture_root->children; o; o = o->next) {
226 printf("\n%s (%s):\n ", o->description, o->name);
229 for (s = o->children; s; s = s->next) {
230 if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
234 i+=printf("%s-%s ", o->name, s->name);
237 for (t = o->testcases; t; t = t->next) {
238 if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
242 i+=printf("%s-%s ", o->name, t->name);
248 printf("\nThe default test is ALL.\n");
253 static void max_runtime_handler(int sig)
255 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
259 struct timeval last_suite_started;
261 static void simple_suite_start(struct torture_context *ctx,
262 struct torture_suite *suite)
264 last_suite_started = timeval_current();
265 printf("Running %s\n", suite->name);
268 static void simple_suite_finish(struct torture_context *ctx,
269 struct torture_suite *suite)
272 printf("%s took %g secs\n\n", suite->name,
273 timeval_elapsed(&last_suite_started));
276 static void simple_test_result (struct torture_context *context,
277 enum torture_result res, const char *reason)
282 printf("OK: %s\n", reason);
285 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
288 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason);
291 printf("SKIP: %s - %s\n", context->active_test->name, reason);
296 static void simple_comment (struct torture_context *test,
299 printf("%s", comment);
302 const static struct torture_ui_ops std_ui_ops = {
303 .comment = simple_comment,
304 .suite_start = simple_suite_start,
305 .suite_finish = simple_suite_finish,
306 .test_result = simple_test_result
310 static void subunit_test_start (struct torture_context *ctx,
311 struct torture_tcase *tcase,
312 struct torture_test *test)
314 printf("test: %s\n", test->name);
317 static void subunit_test_result (struct torture_context *context,
318 enum torture_result res, const char *reason)
322 printf("success: %s", context->active_test->name);
325 printf("failure: %s", context->active_test->name);
328 printf("error: %s", context->active_test->name);
331 printf("skip: %s", context->active_test->name);
335 printf(" [ %s ]", reason);
339 static void subunit_comment (struct torture_context *test,
342 fprintf(stderr, "%s", comment);
345 const static struct torture_ui_ops subunit_ui_ops = {
346 .comment = subunit_comment,
347 .test_start = subunit_test_start,
348 .test_result = subunit_test_result
351 static void harness_test_start (struct torture_context *ctx,
352 struct torture_tcase *tcase,
353 struct torture_test *test)
357 static void harness_test_result (struct torture_context *context,
358 enum torture_result res, const char *reason)
362 printf("ok %s - %s\n", context->active_test->name, reason);
366 printf("not ok %s - %s\n", context->active_test->name, reason);
369 printf("skip %s - %s\n", context->active_test->name, reason);
374 static void harness_comment (struct torture_context *test,
377 printf("# %s\n", comment);
380 const static struct torture_ui_ops harness_ui_ops = {
381 .comment = harness_comment,
382 .test_start = harness_test_start,
383 .test_result = harness_test_result
386 static void quiet_suite_start(struct torture_context *ctx,
387 struct torture_suite *suite)
391 for (i = 1; i < ctx->level; i++) putchar('\t');
392 printf("%s: ", suite->name);
396 static void quiet_suite_finish(struct torture_context *ctx,
397 struct torture_suite *suite)
402 static void quiet_test_result (struct torture_context *context,
403 enum torture_result res, const char *reason)
407 case TORTURE_OK: putchar('.'); break;
408 case TORTURE_FAIL: putchar('F'); break;
409 case TORTURE_ERROR: putchar('E'); break;
410 case TORTURE_SKIP: putchar('I'); break;
414 const static struct torture_ui_ops quiet_ui_ops = {
415 .suite_start = quiet_suite_start,
416 .suite_finish = quiet_suite_finish,
417 .test_result = quiet_test_result
420 void run_recipe(struct torture_context *tctx, const char *recipe)
422 int numlines, i, ret;
425 lines = file_lines_load(recipe, &numlines, NULL);
427 fprintf(stderr, "Unable to load file %s\n", recipe);
431 for (i = 0; i < numlines; i++) {
435 ret = poptParseArgvString(lines[i], &argc, &argv);
437 fprintf(stderr, "Error parsing line\n");
441 run_test(tctx, argv[0]);
447 void run_shell(struct torture_context *tctx)
455 cline = smb_readline("torture> ", NULL, NULL);
460 ret = poptParseArgvString(cline, &argc, &argv);
462 fprintf(stderr, "Error parsing line\n");
466 if (!strcmp(argv[0], "quit")) {
468 } else if (!strcmp(argv[0], "set")) {
470 fprintf(stderr, "Usage: set <variable> <value>\n");
472 char *name = talloc_asprintf(NULL, "torture:%s", argv[1]);
473 lp_set_cmdline(name, argv[2]);
476 } else if (!strcmp(argv[0], "help")) {
477 fprintf(stderr, "Available commands:\n"
478 " help - This help command\n"
480 " set - Change variables\n"
482 } else if (!strcmp(argv[0], "run")) {
484 fprintf(stderr, "Usage: run TEST-NAME [OPTIONS...]\n");
486 run_test(tctx, argv[1]);
492 /****************************************************************************
494 ****************************************************************************/
495 int main(int argc,char *argv[])
501 struct torture_context *torture;
502 const struct torture_ui_ops *ui_ops;
505 static const char *target = "other";
506 const char **subunit_dir;
507 struct dcerpc_binding *binding_struct;
510 static const char *ui_ops_name = "simple";
511 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,
512 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS, OPT_BASEDIR};
514 struct poptOption long_options[] = {
516 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit, harness)", NULL },
517 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
518 {"basedir", 0, POPT_ARG_STRING, NULL, OPT_BASEDIR, "base directory", "BSAEDIR" },
519 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
520 {"num-progs", 0, POPT_ARG_INT, NULL, OPT_NUMPROGS, "num progs", NULL},
521 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
522 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
523 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
524 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
525 {"timelimit", 't', POPT_ARG_INT, NULL, OPT_TIMELIMIT, "timelimit", NULL},
526 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
527 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
528 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
529 "run dangerous tests (eg. wiping out password database)", NULL},
530 {"shell", 0, POPT_ARG_NONE, &shell, True, "Run shell", NULL},
531 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
532 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
533 "run async tests", NULL},
534 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
535 "number of simultaneous async requests", NULL},
536 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
537 "set maximum time for smbtorture to live", "seconds"},
539 POPT_COMMON_CONNECTION
540 POPT_COMMON_CREDENTIALS
547 /* we are never interested in SIGPIPE */
548 BlockSignals(true, SIGPIPE);
550 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
551 POPT_CONTEXT_KEEP_FIRST);
553 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
555 while((opt = poptGetNextOpt(pc)) != -1) {
558 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
561 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
564 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
567 lp_set_cmdline("torture:nprocs", poptGetOptArg(pc));
570 lp_set_cmdline("torture:basedir", poptGetOptArg(pc));
573 parse_dns(poptGetOptArg(pc));
576 lp_set_cmdline("torture:dangerous", "Yes");
579 lp_set_cmdline("torture:async", "Yes");
582 lp_set_cmdline("smb ports", poptGetOptArg(pc));
587 if (strcmp(target, "samba3") == 0) {
588 lp_set_cmdline("torture:samba3", "true");
589 lp_set_cmdline("torture:knownfail", "samba3-knownfail");
590 } else if (strcmp(target, "samba4") == 0) {
591 lp_set_cmdline("torture:samba4", "true");
592 lp_set_cmdline("torture:knownfail", "samba4-knownfail");
596 /* this will only work if nobody else uses alarm(),
597 which means it won't work for some tests, but we
598 can't use the event context method we use for smbd
599 as so many tests create their own event
600 context. This will at least catch most cases. */
601 signal(SIGALRM, max_runtime_handler);
608 subunit_dir = lp_parm_string_list(-1, "torture", "subunitdir", ":");
609 if (subunit_dir == NULL)
610 torture_subunit_load_testsuites(dyn_TORTUREDIR, true, NULL);
612 for (i = 0; subunit_dir[i]; i++)
613 torture_subunit_load_testsuites(subunit_dir[i], true, NULL);
616 if (torture_seed == 0) {
617 torture_seed = time(NULL);
619 printf("Using seed %d\n", torture_seed);
620 srandom(torture_seed);
622 argv_new = discard_const_p(char *, poptGetArgs(pc));
625 for (i=0; i<argc; i++) {
626 if (argv_new[i] == NULL) {
632 if (!(argc_new >= 3 || (shell && argc_new >= 2))) {
637 /* see if its a RPC transport specifier */
638 status = dcerpc_parse_binding(talloc_autofree_context(), argv_new[1], &binding_struct);
639 if (NT_STATUS_IS_OK(status)) {
640 lp_set_cmdline("torture:host", binding_struct->host);
641 lp_set_cmdline("torture:share", "IPC$");
642 lp_set_cmdline("torture:binding", argv_new[1]);
644 char *binding = NULL;
645 char *host = NULL, *share = NULL;
647 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
648 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
652 lp_set_cmdline("torture:host", host);
653 lp_set_cmdline("torture:share", share);
654 asprintf(&binding, "ncacn_np:%s", host);
655 lp_set_cmdline("torture:binding", binding);
658 if (!strcmp(ui_ops_name, "simple")) {
659 ui_ops = &std_ui_ops;
660 } else if (!strcmp(ui_ops_name, "subunit")) {
661 ui_ops = &subunit_ui_ops;
662 } else if (!strcmp(ui_ops_name, "harness")) {
663 ui_ops = &harness_ui_ops;
664 } else if (!strcmp(ui_ops_name, "quiet")) {
665 ui_ops = &quiet_ui_ops;
667 printf("Unknown output format '%s'\n", ui_ops_name);
671 torture = torture_context_init(talloc_autofree_context(),
672 lp_parm_string(-1, "torture", "knownfail"), ui_ops);
675 printf("You must specify a test to run, or 'ALL'\n");
681 int unexpected_failures;
682 for (i=2;i<argc_new;i++) {
683 if (argv_new[i][0] == '@') {
684 run_recipe(torture, argv_new[i]+1);
685 } else if (!run_test(torture, argv_new[i])) {
690 unexpected_failures = str_list_length(torture->results.unexpected_failures);
692 total = torture->results.skipped+torture->results.success+torture->results.failed+torture->results.errors;
694 printf("No tests run.\n");
696 rate = ((total - unexpected_failures - torture->results.errors) * (100.0 / total));
698 printf("Tests: %d, Failures: %d", total, torture->results.failed);
699 if (torture->results.failed - unexpected_failures) {
700 printf(" (%d expected)", torture->results.failed - unexpected_failures);
702 printf(", Errors: %d, Skipped: %d. Success rate: %.2f%%\n",
703 torture->results.errors, torture->results.skipped, rate);
706 if (unexpected_failures) {
707 printf("The following tests failed:\n");
708 for (i = 0; torture->results.unexpected_failures[i]; i++) {
709 printf(" %s\n", torture->results.unexpected_failures[i]);
714 if (str_list_length(torture->results.unexpected_errors)) {
715 printf("Errors occurred while running the following tests:\n");
716 for (i = 0; torture->results.unexpected_errors[i]; i++) {
717 printf(" %s\n", torture->results.unexpected_errors[i]);
722 if (str_list_length(torture->results.unexpected_successes)) {
723 printf("The following tests were expected to fail but succeeded:\n");
724 for (i = 0; torture->results.unexpected_successes[i]; i++) {
725 printf(" %s\n", torture->results.unexpected_successes[i]);
731 if (torture->results.returncode) {