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 "libcli/libcli.h"
28 #include "lib/ldb/include/ldb.h"
29 #include "lib/events/events.h"
30 #include "dynconfig.h"
32 #include "torture/torture.h"
34 #include "lib/util/dlinklist.h"
35 #include "librpc/rpc/dcerpc.h"
37 static bool run_matching(struct torture_context *torture,
40 struct torture_suite *suite,
46 struct torture_suite *o;
48 for (o = torture_root->children; o; o = o->next) {
49 if (gen_fnmatch(expr, o->name) == 0) {
52 ret &= torture_run_suite(torture, o);
56 ret &= run_matching(torture,
57 o->name, expr, o, matched);
61 struct torture_suite *c;
62 struct torture_tcase *t;
64 for (c = suite->children; c; c = c->next) {
65 asprintf(&name, "%s-%s", prefix, c->name);
66 if (gen_fnmatch(expr, name) == 0) {
69 ret &= torture_run_suite(torture, c);
74 ret &= run_matching(torture, name, expr, c, matched);
79 for (t = suite->testcases; t; t = t->next) {
80 asprintf(&name, "%s-%s", prefix, t->name);
81 if (gen_fnmatch(expr, name) == 0) {
84 ret &= torture_run_tcase(torture, t);
93 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
95 /****************************************************************************
96 run a specified test or "ALL"
97 ****************************************************************************/
98 static bool run_test(struct torture_context *torture, const char *name)
101 bool matched = false;
102 struct torture_suite *o;
104 if (strequal(name, "ALL")) {
105 for (o = torture_root->children; o; o = o->next) {
106 ret &= torture_run_suite(torture, o);
111 ret = run_matching(torture, NULL, name, NULL, &matched);
114 printf("Unknown torture operation '%s'\n", name);
121 static void parse_dns(const char *dns)
123 char *userdn, *basedn, *secret;
126 /* retrievieng the userdn */
127 p = strchr_m(dns, '#');
129 lp_set_cmdline("torture:ldap_userdn", "");
130 lp_set_cmdline("torture:ldap_basedn", "");
131 lp_set_cmdline("torture:ldap_secret", "");
134 userdn = strndup(dns, p - dns);
135 lp_set_cmdline("torture:ldap_userdn", userdn);
137 /* retrieve the basedn */
139 p = strchr_m(d, '#');
141 lp_set_cmdline("torture:ldap_basedn", "");
142 lp_set_cmdline("torture:ldap_secret", "");
145 basedn = strndup(d, p - d);
146 lp_set_cmdline("torture:ldap_basedn", basedn);
148 /* retrieve the secret */
151 lp_set_cmdline("torture:ldap_secret", "");
155 lp_set_cmdline("torture:ldap_secret", secret);
157 printf ("%s - %s - %s\n", userdn, basedn, secret);
161 static void usage(poptContext pc)
163 struct torture_suite *o;
164 struct torture_suite *s;
165 struct torture_tcase *t;
168 poptPrintUsage(pc, stdout, 0);
171 printf("The binding format is:\n\n");
173 printf(" TRANSPORT:host[flags]\n\n");
175 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
176 printf(" or ncalrpc for local connections.\n\n");
178 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
179 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
180 printf(" string.\n\n");
182 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
183 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
184 printf(" will be auto-determined.\n\n");
186 printf(" other recognised flags are:\n\n");
188 printf(" sign : enable ntlmssp signing\n");
189 printf(" seal : enable ntlmssp sealing\n");
190 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
191 printf(" validate: enable the NDR validator\n");
192 printf(" print: enable debugging of the packets\n");
193 printf(" bigendian: use bigendian RPC\n");
194 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
196 printf(" For example, these all connect to the samr pipe:\n\n");
198 printf(" ncacn_np:myserver\n");
199 printf(" ncacn_np:myserver[samr]\n");
200 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
201 printf(" ncacn_np:myserver[/pipe/samr]\n");
202 printf(" ncacn_np:myserver[samr,sign,print]\n");
203 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
204 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
205 printf(" ncacn_np:\n");
206 printf(" ncacn_np:[/pipe/samr]\n\n");
208 printf(" ncacn_ip_tcp:myserver\n");
209 printf(" ncacn_ip_tcp:myserver[1024]\n");
210 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
212 printf(" ncalrpc:\n\n");
214 printf("The UNC format is:\n\n");
216 printf(" //server/share\n\n");
218 printf("Tests are:");
220 for (o = torture_root->children; o; o = o->next) {
221 printf("\n%s (%s):\n ", o->description, o->name);
224 for (s = o->children; s; s = s->next) {
225 if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
229 i+=printf("%s-%s ", o->name, s->name);
232 for (t = o->testcases; t; t = t->next) {
233 if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
237 i+=printf("%s-%s ", o->name, t->name);
243 printf("\nThe default test is ALL.\n");
248 static bool is_binding_string(const char *binding_string)
250 TALLOC_CTX *mem_ctx = talloc_named_const(NULL, 0, "is_binding_string");
251 struct dcerpc_binding *binding_struct;
254 status = dcerpc_parse_binding(mem_ctx, binding_string, &binding_struct);
256 talloc_free(mem_ctx);
257 return NT_STATUS_IS_OK(status);
260 static void max_runtime_handler(int sig)
262 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
266 struct timeval last_suite_started;
268 static void simple_suite_start(struct torture_context *ctx,
269 struct torture_suite *suite)
271 last_suite_started = timeval_current();
272 printf("Running %s\n", suite->name);
275 static void simple_suite_finish(struct torture_context *ctx,
276 struct torture_suite *suite)
279 printf("%s took %g secs\n\n", suite->name,
280 timeval_elapsed(&last_suite_started));
283 static void simple_test_result (struct torture_context *context,
284 enum torture_result res, const char *reason)
289 printf("OK: %s\n", reason);
292 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
295 printf("TODO: %s - %s\n", context->active_test->name, reason);
298 printf("SKIP: %s - %s\n", context->active_test->name, reason);
304 static void simple_comment (struct torture_context *test,
307 printf("%s", comment);
310 const static struct torture_ui_ops std_ui_ops = {
311 .comment = simple_comment,
312 .suite_start = simple_suite_start,
313 .suite_finish = simple_suite_finish,
314 .test_result = simple_test_result
318 static void subunit_test_start (struct torture_context *ctx,
319 struct torture_tcase *tcase,
320 struct torture_test *test)
322 printf("test: %s\n", test->name);
325 static void subunit_test_result (struct torture_context *context,
326 enum torture_result res, const char *reason)
330 printf("success: %s", context->active_test->name);
333 printf("failure: %s", context->active_test->name);
336 printf("todo: %s", context->active_test->name);
339 printf("skip: %s", context->active_test->name);
343 printf(" [ %s ]", reason);
347 static void subunit_comment (struct torture_context *test,
350 fprintf(stderr, "%s", comment);
353 const static struct torture_ui_ops subunit_ui_ops = {
354 .comment = subunit_comment,
355 .test_start = subunit_test_start,
356 .test_result = subunit_test_result
359 static void harness_test_start (struct torture_context *ctx,
360 struct torture_tcase *tcase,
361 struct torture_test *test)
365 static void harness_test_result (struct torture_context *context,
366 enum torture_result res, const char *reason)
370 printf("ok %s - %s\n", context->active_test->name, reason);
373 printf("not ok %s - %s\n", context->active_test->name, reason);
376 printf("todo %s - %s\n", context->active_test->name, reason);
379 printf("skip %s - %s\n", context->active_test->name, reason);
384 static void harness_comment (struct torture_context *test,
387 printf("# %s\n", comment);
390 const static struct torture_ui_ops harness_ui_ops = {
391 .comment = harness_comment,
392 .test_start = harness_test_start,
393 .test_result = harness_test_result
396 static void quiet_suite_start(struct torture_context *ctx,
397 struct torture_suite *suite)
401 for (i = 1; i < ctx->level; i++) putchar('\t');
402 printf("%s: ", suite->name);
406 static void quiet_suite_finish(struct torture_context *ctx,
407 struct torture_suite *suite)
412 static void quiet_test_result (struct torture_context *context,
413 enum torture_result res, const char *reason)
417 case TORTURE_OK: putchar('.'); break;
418 case TORTURE_FAIL: putchar('E'); break;
419 case TORTURE_TODO: putchar('T'); break;
420 case TORTURE_SKIP: putchar('S'); break;
424 const static struct torture_ui_ops quiet_ui_ops = {
425 .suite_start = quiet_suite_start,
426 .suite_finish = quiet_suite_finish,
427 .test_result = quiet_test_result
431 /****************************************************************************
433 ****************************************************************************/
434 int main(int argc,char *argv[])
440 struct torture_context *torture;
443 static const char *target = "other";
444 const char **subunit_dir;
445 static const char *ui_ops_name = "simple";
446 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,
447 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC};
449 struct poptOption long_options[] = {
451 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit, harness)", NULL },
452 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
453 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
454 {"num-progs", 0, POPT_ARG_INT, &torture_nprocs, 0, "num progs", NULL},
455 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
456 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
457 {"show-all", 0, POPT_ARG_NONE, &torture_showall, 0, "show all", NULL},
458 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
459 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
460 {"timelimit", 't', POPT_ARG_STRING, NULL, OPT_TIMELIMIT, "timelimit", NULL},
461 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
462 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
463 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
464 "run dangerous tests (eg. wiping out password database)", NULL},
465 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
466 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
467 "run async tests", NULL},
468 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
469 "number of simultaneous async requests", NULL},
470 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
471 "set maximum time for smbtorture to live", "seconds"},
473 POPT_COMMON_CONNECTION
474 POPT_COMMON_CREDENTIALS
481 /* we are never interested in SIGPIPE */
482 BlockSignals(true,SIGPIPE);
484 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
485 POPT_CONTEXT_KEEP_FIRST);
487 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
489 while((opt = poptGetNextOpt(pc)) != -1) {
492 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
495 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
498 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
501 parse_dns(poptGetOptArg(pc));
504 lp_set_cmdline("torture:dangerous", "Yes");
507 lp_set_cmdline("torture:async", "Yes");
510 lp_set_cmdline("smb ports", poptGetOptArg(pc));
513 d_printf("Invalid option %s: %s\n",
514 poptBadOption(pc, 0), poptStrerror(opt));
521 if (strcmp(target, "samba3") == 0) {
522 lp_set_cmdline("target:samba3", "true");
523 } else if (strcmp(target, "samba4") == 0) {
524 lp_set_cmdline("target:samba4", "true");
528 /* this will only work if nobody else uses alarm(),
529 which means it won't work for some tests, but we
530 can't use the event context method we use for smbd
531 as so many tests create their own event
532 context. This will at least catch most cases. */
533 signal(SIGALRM, max_runtime_handler);
540 subunit_dir = lp_parm_string_list(-1, "torture", "subunitdir", ":");
541 if (subunit_dir == NULL)
542 torture_subunit_load_testsuites(dyn_TORTUREDIR, true, NULL);
544 for (i = 0; subunit_dir[i]; i++)
545 torture_subunit_load_testsuites(subunit_dir[i], true, NULL);
548 if (torture_seed == 0) {
549 torture_seed = time(NULL);
551 printf("Using seed %d\n", torture_seed);
552 srandom(torture_seed);
554 argv_new = discard_const_p(char *, poptGetArgs(pc));
557 for (i=0; i<argc; i++) {
558 if (argv_new[i] == NULL) {
569 /* see if its a RPC transport specifier */
570 if (is_binding_string(argv_new[1])) {
571 lp_set_cmdline("torture:binding", argv_new[1]);
573 char *binding = NULL;
574 char *host = NULL, *share = NULL;
576 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
577 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
581 lp_set_cmdline("torture:host", host);
582 lp_set_cmdline("torture:share", share);
583 asprintf(&binding, "ncacn_np:%s", host);
584 lp_set_cmdline("torture:binding", binding);
587 torture = talloc_zero(talloc_autofree_context(), struct torture_context);
588 if (!strcmp(ui_ops_name, "simple")) {
589 torture->ui_ops = &std_ui_ops;
590 } else if (!strcmp(ui_ops_name, "subunit")) {
591 torture->ui_ops = &subunit_ui_ops;
592 } else if (!strcmp(ui_ops_name, "harness")) {
593 torture->ui_ops = &harness_ui_ops;
594 } else if (!strcmp(ui_ops_name, "quiet")) {
595 torture->ui_ops = &quiet_ui_ops;
597 printf("Unknown output format '%s'\n", ui_ops_name);
602 printf("You must specify a test to run, or 'ALL'\n");
606 for (i=2;i<argc_new;i++) {
607 if (!run_test(torture, argv_new[i])) {
612 total = torture->skipped+torture->success+torture->failed;
614 printf("No tests run.\n");
616 rate = ((total - torture->failed) * (100.0 / total));
617 printf("Tests: %d, Errors: %d, Skipped: %d. Success rate: %.2f%%\n",
618 total, torture->failed, torture->skipped,
623 talloc_free(torture);