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 print_test_list(void)
168 struct torture_suite *o;
169 struct torture_suite *s;
170 struct torture_tcase *t;
172 for (o = torture_root->children; o; o = o->next) {
173 for (s = o->children; s; s = s->next) {
174 printf("%s-%s\n", o->name, s->name);
177 for (t = o->testcases; t; t = t->next) {
178 printf("%s-%s\n", o->name, t->name);
183 static void usage(poptContext pc)
185 struct torture_suite *o;
186 struct torture_suite *s;
187 struct torture_tcase *t;
190 poptPrintUsage(pc, stdout, 0);
193 printf("The binding format is:\n\n");
195 printf(" TRANSPORT:host[flags]\n\n");
197 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
198 printf(" or ncalrpc for local connections.\n\n");
200 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
201 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
202 printf(" string.\n\n");
204 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
205 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
206 printf(" will be auto-determined.\n\n");
208 printf(" other recognised flags are:\n\n");
210 printf(" sign : enable ntlmssp signing\n");
211 printf(" seal : enable ntlmssp sealing\n");
212 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
213 printf(" validate: enable the NDR validator\n");
214 printf(" print: enable debugging of the packets\n");
215 printf(" bigendian: use bigendian RPC\n");
216 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
218 printf(" For example, these all connect to the samr pipe:\n\n");
220 printf(" ncacn_np:myserver\n");
221 printf(" ncacn_np:myserver[samr]\n");
222 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
223 printf(" ncacn_np:myserver[/pipe/samr]\n");
224 printf(" ncacn_np:myserver[samr,sign,print]\n");
225 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
226 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
227 printf(" ncacn_np:\n");
228 printf(" ncacn_np:[/pipe/samr]\n\n");
230 printf(" ncacn_ip_tcp:myserver\n");
231 printf(" ncacn_ip_tcp:myserver[1024]\n");
232 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
234 printf(" ncalrpc:\n\n");
236 printf("The UNC format is:\n\n");
238 printf(" //server/share\n\n");
240 printf("Tests are:");
242 for (o = torture_root->children; o; o = o->next) {
243 printf("\n%s (%s):\n ", o->description, o->name);
246 for (s = o->children; s; s = s->next) {
247 if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
251 i+=printf("%s-%s ", o->name, s->name);
254 for (t = o->testcases; t; t = t->next) {
255 if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
259 i+=printf("%s-%s ", o->name, t->name);
265 printf("\nThe default test is ALL.\n");
270 static void max_runtime_handler(int sig)
272 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
276 struct timeval last_suite_started;
278 static void simple_suite_start(struct torture_context *ctx,
279 struct torture_suite *suite)
281 last_suite_started = timeval_current();
282 printf("Running %s\n", suite->name);
285 static void simple_suite_finish(struct torture_context *ctx,
286 struct torture_suite *suite)
289 printf("%s took %g secs\n\n", suite->name,
290 timeval_elapsed(&last_suite_started));
293 static void simple_test_result (struct torture_context *context,
294 enum torture_result res, const char *reason)
299 printf("OK: %s\n", reason);
302 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
305 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason);
308 printf("SKIP: %s - %s\n", context->active_test->name, reason);
313 static void simple_comment (struct torture_context *test,
316 printf("%s", comment);
319 const static struct torture_ui_ops std_ui_ops = {
320 .comment = simple_comment,
321 .suite_start = simple_suite_start,
322 .suite_finish = simple_suite_finish,
323 .test_result = simple_test_result
326 static void subunit_suite_start(struct torture_context *ctx,
327 struct torture_suite *suite)
329 printf("testsuite: %s\n", suite->name);
332 static void subunit_test_start (struct torture_context *ctx,
333 struct torture_tcase *tcase,
334 struct torture_test *test)
336 printf("test: %s\n", test->name);
339 static void subunit_test_result (struct torture_context *context,
340 enum torture_result res, const char *reason)
344 printf("success: %s", context->active_test->name);
347 printf("failure: %s", context->active_test->name);
350 printf("error: %s", context->active_test->name);
353 printf("skip: %s", context->active_test->name);
357 printf(" [ %s ]", reason);
361 static void subunit_comment (struct torture_context *test,
364 fprintf(stderr, "%s", comment);
367 const static struct torture_ui_ops subunit_ui_ops = {
368 .comment = subunit_comment,
369 .test_start = subunit_test_start,
370 .test_result = subunit_test_result,
371 .suite_start = subunit_suite_start
374 static void harness_test_start (struct torture_context *ctx,
375 struct torture_tcase *tcase,
376 struct torture_test *test)
380 static void harness_test_result (struct torture_context *context,
381 enum torture_result res, const char *reason)
385 printf("ok %s - %s\n", context->active_test->name, reason);
389 printf("not ok %s - %s\n", context->active_test->name, reason);
392 printf("skip %s - %s\n", context->active_test->name, reason);
397 static void harness_comment (struct torture_context *test,
400 printf("# %s\n", comment);
403 const static struct torture_ui_ops harness_ui_ops = {
404 .comment = harness_comment,
405 .test_start = harness_test_start,
406 .test_result = harness_test_result
409 static void quiet_suite_start(struct torture_context *ctx,
410 struct torture_suite *suite)
414 for (i = 1; i < ctx->level; i++) putchar('\t');
415 printf("%s: ", suite->name);
419 static void quiet_suite_finish(struct torture_context *ctx,
420 struct torture_suite *suite)
425 static void quiet_test_result (struct torture_context *context,
426 enum torture_result res, const char *reason)
430 case TORTURE_OK: putchar('.'); break;
431 case TORTURE_FAIL: putchar('F'); break;
432 case TORTURE_ERROR: putchar('E'); break;
433 case TORTURE_SKIP: putchar('I'); break;
437 const static struct torture_ui_ops quiet_ui_ops = {
438 .suite_start = quiet_suite_start,
439 .suite_finish = quiet_suite_finish,
440 .test_result = quiet_test_result
443 void run_shell(struct torture_context *tctx)
451 cline = smb_readline("torture> ", NULL, NULL);
456 ret = poptParseArgvString(cline, &argc, &argv);
458 fprintf(stderr, "Error parsing line\n");
462 if (!strcmp(argv[0], "quit")) {
464 } else if (!strcmp(argv[0], "set")) {
466 fprintf(stderr, "Usage: set <variable> <value>\n");
468 char *name = talloc_asprintf(NULL, "torture:%s", argv[1]);
469 lp_set_cmdline(name, argv[2]);
472 } else if (!strcmp(argv[0], "help")) {
473 fprintf(stderr, "Available commands:\n"
474 " help - This help command\n"
476 " set - Change variables\n"
478 } else if (!strcmp(argv[0], "run")) {
480 fprintf(stderr, "Usage: run TEST-NAME [OPTIONS...]\n");
482 run_test(tctx, argv[1]);
488 /****************************************************************************
490 ****************************************************************************/
491 int main(int argc,char *argv[])
497 struct torture_context *torture;
498 const struct torture_ui_ops *ui_ops;
501 static const char *target = "other";
502 struct dcerpc_binding *binding_struct;
505 static const char *ui_ops_name = "simple";
506 static int list_tests = 0;
507 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
508 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS, OPT_BASEDIR};
510 struct poptOption long_options[] = {
512 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit, harness)", NULL },
513 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
514 {"basedir", 0, POPT_ARG_STRING, NULL, OPT_BASEDIR, "base directory", "BSAEDIR" },
515 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
516 {"num-progs", 0, POPT_ARG_INT, NULL, OPT_NUMPROGS, "num progs", NULL},
517 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
518 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
519 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
520 {"list", 0, POPT_ARG_NONE, &list_tests, 0, NULL, NULL },
521 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
522 {"timelimit", 't', POPT_ARG_INT, NULL, OPT_TIMELIMIT, "timelimit", NULL},
523 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
524 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
525 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
526 "run dangerous tests (eg. wiping out password database)", NULL},
527 {"shell", 0, POPT_ARG_NONE, &shell, True, "Run shell", NULL},
528 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
529 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
530 "run async tests", NULL},
531 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
532 "number of simultaneous async requests", NULL},
533 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
534 "set maximum time for smbtorture to live", "seconds"},
536 POPT_COMMON_CONNECTION
537 POPT_COMMON_CREDENTIALS
544 /* we are never interested in SIGPIPE */
545 BlockSignals(true, SIGPIPE);
547 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
548 POPT_CONTEXT_KEEP_FIRST);
550 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
552 while((opt = poptGetNextOpt(pc)) != -1) {
555 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
558 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
561 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
564 lp_set_cmdline("torture:nprocs", poptGetOptArg(pc));
567 lp_set_cmdline("torture:basedir", poptGetOptArg(pc));
570 parse_dns(poptGetOptArg(pc));
573 lp_set_cmdline("torture:dangerous", "Yes");
576 lp_set_cmdline("torture:async", "Yes");
579 lp_set_cmdline("smb ports", poptGetOptArg(pc));
584 if (strcmp(target, "samba3") == 0) {
585 lp_set_cmdline("torture:samba3", "true");
586 lp_set_cmdline("torture:knownfail", "samba3-knownfail");
587 } else if (strcmp(target, "samba4") == 0) {
588 lp_set_cmdline("torture:samba4", "true");
589 lp_set_cmdline("torture:knownfail", "samba4-knownfail");
593 /* this will only work if nobody else uses alarm(),
594 which means it won't work for some tests, but we
595 can't use the event context method we use for smbd
596 as so many tests create their own event
597 context. This will at least catch most cases. */
598 signal(SIGALRM, max_runtime_handler);
610 if (torture_seed == 0) {
611 torture_seed = time(NULL);
613 printf("Using seed %d\n", torture_seed);
614 srandom(torture_seed);
616 argv_new = discard_const_p(char *, poptGetArgs(pc));
619 for (i=0; i<argc; i++) {
620 if (argv_new[i] == NULL) {
626 if (!(argc_new >= 3 || (shell && argc_new >= 2))) {
631 /* see if its a RPC transport specifier */
632 status = dcerpc_parse_binding(talloc_autofree_context(), argv_new[1], &binding_struct);
633 if (NT_STATUS_IS_OK(status)) {
634 lp_set_cmdline("torture:host", binding_struct->host);
635 lp_set_cmdline("torture:share", "IPC$");
636 lp_set_cmdline("torture:binding", argv_new[1]);
638 char *binding = NULL;
639 char *host = NULL, *share = NULL;
641 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
642 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
646 lp_set_cmdline("torture:host", host);
647 lp_set_cmdline("torture:share", share);
648 asprintf(&binding, "ncacn_np:%s", host);
649 lp_set_cmdline("torture:binding", binding);
652 if (!strcmp(ui_ops_name, "simple")) {
653 ui_ops = &std_ui_ops;
654 } else if (!strcmp(ui_ops_name, "subunit")) {
655 ui_ops = &subunit_ui_ops;
656 } else if (!strcmp(ui_ops_name, "harness")) {
657 ui_ops = &harness_ui_ops;
658 } else if (!strcmp(ui_ops_name, "quiet")) {
659 ui_ops = &quiet_ui_ops;
661 printf("Unknown output format '%s'\n", ui_ops_name);
665 torture = torture_context_init(talloc_autofree_context(),
666 lp_parm_string(-1, "torture", "knownfail"), ui_ops);
669 printf("You must specify a test to run, or 'ALL'\n");
675 int unexpected_failures;
676 for (i=2;i<argc_new;i++) {
677 if (!run_test(torture, argv_new[i])) {
682 unexpected_failures = str_list_length(torture->results.unexpected_failures);
684 total = torture->results.skipped+torture->results.success+torture->results.failed+torture->results.errors;
686 printf("No tests run.\n");
688 rate = ((total - unexpected_failures - torture->results.errors) * (100.0 / total));
690 printf("Tests: %d, Failures: %d", total, torture->results.failed);
691 if (torture->results.failed - unexpected_failures) {
692 printf(" (%d expected)", torture->results.failed - unexpected_failures);
694 printf(", Errors: %d, Skipped: %d. Success rate: %.2f%%\n",
695 torture->results.errors, torture->results.skipped, rate);
698 if (unexpected_failures) {
699 printf("The following tests failed:\n");
700 for (i = 0; torture->results.unexpected_failures[i]; i++) {
701 printf(" %s\n", torture->results.unexpected_failures[i]);
706 if (str_list_length(torture->results.unexpected_errors)) {
707 printf("Errors occurred while running the following tests:\n");
708 for (i = 0; torture->results.unexpected_errors[i]; i++) {
709 printf(" %s\n", torture->results.unexpected_errors[i]);
714 if (str_list_length(torture->results.unexpected_successes)) {
715 printf("The following tests were expected to fail but succeeded:\n");
716 for (i = 0; torture->results.unexpected_successes[i]; i++) {
717 printf(" %s\n", torture->results.unexpected_successes[i]);
723 if (torture->results.returncode) {