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("ERROR IN TEST %s! - %s\n", context->active_test->name, reason);
298 printf("SKIP: %s - %s\n", context->active_test->name, reason);
303 static void simple_comment (struct torture_context *test,
306 printf("%s", comment);
309 const static struct torture_ui_ops std_ui_ops = {
310 .comment = simple_comment,
311 .suite_start = simple_suite_start,
312 .suite_finish = simple_suite_finish,
313 .test_result = simple_test_result
317 static void subunit_test_start (struct torture_context *ctx,
318 struct torture_tcase *tcase,
319 struct torture_test *test)
321 printf("test: %s\n", test->name);
324 static void subunit_test_result (struct torture_context *context,
325 enum torture_result res, const char *reason)
329 printf("success: %s", context->active_test->name);
332 printf("failure: %s", context->active_test->name);
335 printf("error: %s", context->active_test->name);
338 printf("skip: %s", context->active_test->name);
342 printf(" [ %s ]", reason);
346 static void subunit_comment (struct torture_context *test,
349 fprintf(stderr, "%s", comment);
352 const static struct torture_ui_ops subunit_ui_ops = {
353 .comment = subunit_comment,
354 .test_start = subunit_test_start,
355 .test_result = subunit_test_result
358 static void harness_test_start (struct torture_context *ctx,
359 struct torture_tcase *tcase,
360 struct torture_test *test)
364 static void harness_test_result (struct torture_context *context,
365 enum torture_result res, const char *reason)
369 printf("ok %s - %s\n", context->active_test->name, reason);
373 printf("not ok %s - %s\n", context->active_test->name, reason);
376 printf("skip %s - %s\n", context->active_test->name, reason);
381 static void harness_comment (struct torture_context *test,
384 printf("# %s\n", comment);
387 const static struct torture_ui_ops harness_ui_ops = {
388 .comment = harness_comment,
389 .test_start = harness_test_start,
390 .test_result = harness_test_result
393 static void quiet_suite_start(struct torture_context *ctx,
394 struct torture_suite *suite)
398 for (i = 1; i < ctx->level; i++) putchar('\t');
399 printf("%s: ", suite->name);
403 static void quiet_suite_finish(struct torture_context *ctx,
404 struct torture_suite *suite)
409 static void quiet_test_result (struct torture_context *context,
410 enum torture_result res, const char *reason)
414 case TORTURE_OK: putchar('.'); break;
415 case TORTURE_FAIL: putchar('F'); break;
416 case TORTURE_ERROR: putchar('E'); break;
417 case TORTURE_SKIP: putchar('I'); break;
421 const static struct torture_ui_ops quiet_ui_ops = {
422 .suite_start = quiet_suite_start,
423 .suite_finish = quiet_suite_finish,
424 .test_result = quiet_test_result
428 /****************************************************************************
430 ****************************************************************************/
431 int main(int argc,char *argv[])
437 struct torture_context *torture;
440 static const char *target = "other";
441 const char **subunit_dir;
442 static const char *ui_ops_name = "simple";
443 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS,
444 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC};
446 struct poptOption long_options[] = {
448 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit, harness)", NULL },
449 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
450 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "seed", NULL},
451 {"num-progs", 0, POPT_ARG_INT, &torture_nprocs, 0, "num progs", NULL},
452 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
453 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
454 {"show-all", 0, POPT_ARG_NONE, &torture_showall, 0, "show all", NULL},
455 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "loadfile", NULL},
456 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
457 {"timelimit", 't', POPT_ARG_STRING, NULL, OPT_TIMELIMIT, "timelimit", NULL},
458 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
459 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
460 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
461 "run dangerous tests (eg. wiping out password database)", NULL},
462 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
463 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
464 "run async tests", NULL},
465 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
466 "number of simultaneous async requests", NULL},
467 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
468 "set maximum time for smbtorture to live", "seconds"},
470 POPT_COMMON_CONNECTION
471 POPT_COMMON_CREDENTIALS
478 /* we are never interested in SIGPIPE */
479 BlockSignals(true,SIGPIPE);
481 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
482 POPT_CONTEXT_KEEP_FIRST);
484 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
486 while((opt = poptGetNextOpt(pc)) != -1) {
489 lp_set_cmdline("torture:loadfile", poptGetOptArg(pc));
492 lp_set_cmdline("torture:unclist", poptGetOptArg(pc));
495 lp_set_cmdline("torture:timelimit", poptGetOptArg(pc));
498 parse_dns(poptGetOptArg(pc));
501 lp_set_cmdline("torture:dangerous", "Yes");
504 lp_set_cmdline("torture:async", "Yes");
507 lp_set_cmdline("smb ports", poptGetOptArg(pc));
510 d_printf("Invalid option %s: %s\n",
511 poptBadOption(pc, 0), poptStrerror(opt));
518 if (strcmp(target, "samba3") == 0) {
519 lp_set_cmdline("target:samba3", "true");
520 } else if (strcmp(target, "samba4") == 0) {
521 lp_set_cmdline("target:samba4", "true");
525 /* this will only work if nobody else uses alarm(),
526 which means it won't work for some tests, but we
527 can't use the event context method we use for smbd
528 as so many tests create their own event
529 context. This will at least catch most cases. */
530 signal(SIGALRM, max_runtime_handler);
537 subunit_dir = lp_parm_string_list(-1, "torture", "subunitdir", ":");
538 if (subunit_dir == NULL)
539 torture_subunit_load_testsuites(dyn_TORTUREDIR, true, NULL);
541 for (i = 0; subunit_dir[i]; i++)
542 torture_subunit_load_testsuites(subunit_dir[i], true, NULL);
545 if (torture_seed == 0) {
546 torture_seed = time(NULL);
548 printf("Using seed %d\n", torture_seed);
549 srandom(torture_seed);
551 argv_new = discard_const_p(char *, poptGetArgs(pc));
554 for (i=0; i<argc; i++) {
555 if (argv_new[i] == NULL) {
566 /* see if its a RPC transport specifier */
567 if (is_binding_string(argv_new[1])) {
568 lp_set_cmdline("torture:binding", argv_new[1]);
570 char *binding = NULL;
571 char *host = NULL, *share = NULL;
573 if (!smbcli_parse_unc(argv_new[1], NULL, &host, &share)) {
574 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", argv_new[1]);
578 lp_set_cmdline("torture:host", host);
579 lp_set_cmdline("torture:share", share);
580 asprintf(&binding, "ncacn_np:%s", host);
581 lp_set_cmdline("torture:binding", binding);
584 torture = talloc_zero(talloc_autofree_context(), struct torture_context);
585 if (!strcmp(ui_ops_name, "simple")) {
586 torture->ui_ops = &std_ui_ops;
587 } else if (!strcmp(ui_ops_name, "subunit")) {
588 torture->ui_ops = &subunit_ui_ops;
589 } else if (!strcmp(ui_ops_name, "harness")) {
590 torture->ui_ops = &harness_ui_ops;
591 } else if (!strcmp(ui_ops_name, "quiet")) {
592 torture->ui_ops = &quiet_ui_ops;
594 printf("Unknown output format '%s'\n", ui_ops_name);
599 printf("You must specify a test to run, or 'ALL'\n");
603 for (i=2;i<argc_new;i++) {
604 if (!run_test(torture, argv_new[i])) {
609 total = torture->skipped+torture->success+torture->failed;
611 printf("No tests run.\n");
613 rate = ((total - torture->failed) * (100.0 / total));
614 printf("Tests: %d, Errors: %d, Skipped: %d. Success rate: %.2f%%\n",
615 total, torture->failed, torture->skipped,
620 talloc_free(torture);