s4-drepl: We won't need a working schema for empty replicas sent.
[Samba.git] / source4 / torture / smbtorture.c
blobcfa8b0f87db2a2df8f9b6471371bd3cd57d4c96a
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006-2008
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 3 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, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "lib/cmdline/popt_common.h"
23 #include "system/time.h"
24 #include "system/wait.h"
25 #include "system/filesys.h"
26 #include "system/readline.h"
27 #include "../libcli/smbreadline/smbreadline.h"
28 #include "libcli/libcli.h"
29 #include "lib/events/events.h"
31 #include "torture/smbtorture.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "auth/gensec/gensec.h"
34 #include "param/param.h"
36 #if HAVE_READLINE_HISTORY_H
37 #include <readline/history.h>
38 #endif
40 static char *prefix_name(TALLOC_CTX *mem_ctx, const char *prefix, const char *name)
42 if (prefix == NULL)
43 return talloc_strdup(mem_ctx, name);
44 else
45 return talloc_asprintf(mem_ctx, "%s.%s", prefix, name);
48 static void print_test_list(const struct torture_suite *suite, const char *prefix, const char *expr)
50 struct torture_suite *o;
51 struct torture_tcase *t;
52 struct torture_test *p;
54 for (o = suite->children; o; o = o->next) {
55 char *name = prefix_name(NULL, prefix, o->name);
56 print_test_list(o, name, expr);
57 talloc_free(name);
60 for (t = suite->testcases; t; t = t->next) {
61 for (p = t->tests; p; p = p->next) {
62 char *name = talloc_asprintf(NULL, "%s.%s.%s", prefix, t->name, p->name);
63 if (strncmp(name, expr, strlen(expr)) == 0) {
64 printf("%s\n", name);
66 talloc_free(name);
71 static bool run_matching(struct torture_context *torture,
72 const char *prefix,
73 const char *expr,
74 const char **restricted,
75 struct torture_suite *suite,
76 bool *matched)
78 bool ret = true;
79 struct torture_suite *o;
80 struct torture_tcase *t;
81 struct torture_test *p;
83 for (o = suite->children; o; o = o->next) {
84 char *name = NULL;
85 name = prefix_name(torture, prefix, o->name);
86 if (gen_fnmatch(expr, name) == 0) {
87 *matched = true;
88 reload_charcnv(torture->lp_ctx);
89 if (restricted != NULL)
90 ret &= torture_run_suite_restricted(torture, o, restricted);
91 else
92 ret &= torture_run_suite(torture, o);
94 ret &= run_matching(torture, name, expr, restricted, o, matched);
97 for (t = suite->testcases; t; t = t->next) {
98 char *name = talloc_asprintf(torture, "%s.%s", prefix, t->name);
99 if (gen_fnmatch(expr, name) == 0) {
100 *matched = true;
101 reload_charcnv(torture->lp_ctx);
102 ret &= torture_run_tcase_restricted(torture, t, restricted);
104 for (p = t->tests; p; p = p->next) {
105 name = talloc_asprintf(torture, "%s.%s.%s", prefix, t->name, p->name);
106 if (gen_fnmatch(expr, name) == 0) {
107 *matched = true;
108 reload_charcnv(torture->lp_ctx);
109 ret &= torture_run_test_restricted(torture, t, p, restricted);
114 return ret;
117 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
119 /****************************************************************************
120 run a specified test or "ALL"
121 ****************************************************************************/
122 bool torture_run_named_tests(struct torture_context *torture, const char *name,
123 const char **restricted)
125 bool ret = true;
126 bool matched = false;
127 struct torture_suite *o;
129 torture_ui_report_time(torture);
131 if (strequal(name, "ALL")) {
132 if (restricted != NULL) {
133 printf("--load-list and ALL are incompatible\n");
134 return false;
136 for (o = torture_root->children; o; o = o->next) {
137 ret &= torture_run_suite(torture, o);
139 return ret;
142 ret = run_matching(torture, NULL, name, restricted, torture_root, &matched);
144 if (!matched) {
145 printf("Unknown torture operation '%s'\n", name);
146 return false;
149 return ret;
152 bool torture_parse_target(struct loadparm_context *lp_ctx, const char *target)
154 char *host = NULL, *share = NULL;
155 struct dcerpc_binding *binding_struct;
156 NTSTATUS status;
158 /* see if its a RPC transport specifier */
159 if (!smbcli_parse_unc(target, NULL, &host, &share)) {
160 status = dcerpc_parse_binding(talloc_autofree_context(), target, &binding_struct);
161 if (NT_STATUS_IS_ERR(status)) {
162 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
163 return false;
165 lpcfg_set_cmdline(lp_ctx, "torture:host", binding_struct->host);
166 if (lpcfg_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
167 lpcfg_set_cmdline(lp_ctx, "torture:share", "IPC$");
168 lpcfg_set_cmdline(lp_ctx, "torture:binding", target);
169 } else {
170 lpcfg_set_cmdline(lp_ctx, "torture:host", host);
171 lpcfg_set_cmdline(lp_ctx, "torture:share", share);
172 lpcfg_set_cmdline(lp_ctx, "torture:binding", host);
175 return true;
178 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
180 char *userdn, *basedn, *secret;
181 char *p, *d;
183 /* retrievieng the userdn */
184 p = strchr_m(dns, '#');
185 if (!p) {
186 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
187 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
188 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
189 return;
191 userdn = strndup(dns, p - dns);
192 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
194 /* retrieve the basedn */
195 d = p + 1;
196 p = strchr_m(d, '#');
197 if (!p) {
198 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
199 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
200 return;
202 basedn = strndup(d, p - d);
203 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
205 /* retrieve the secret */
206 p = p + 1;
207 if (!p) {
208 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
209 return;
211 secret = strdup(p);
212 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
214 printf ("%s - %s - %s\n", userdn, basedn, secret);
218 /* Print the full test list, formatted into separate labelled test
219 * groups.
221 static void print_structured_testsuite_list(void)
223 struct torture_suite *o;
224 struct torture_suite *s;
225 struct torture_tcase *t;
226 int i;
228 if (torture_root == NULL) {
229 printf("NO TESTS LOADED\n");
230 return;
233 for (o = torture_root->children; o; o = o->next) {
234 printf("\n%s (%s):\n ", o->description, o->name);
236 i = 0;
237 for (s = o->children; s; s = s->next) {
238 if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
239 printf("\n ");
240 i = 0;
242 i+=printf("%s.%s ", o->name, s->name);
245 for (t = o->testcases; t; t = t->next) {
246 if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
247 printf("\n ");
248 i = 0;
250 i+=printf("%s.%s ", o->name, t->name);
253 if (i) printf("\n");
256 printf("\nThe default test is ALL.\n");
259 static void print_testsuite_list(void)
261 struct torture_suite *o;
262 struct torture_suite *s;
263 struct torture_tcase *t;
265 if (torture_root == NULL)
266 return;
268 for (o = torture_root->children; o; o = o->next) {
269 for (s = o->children; s; s = s->next) {
270 printf("%s.%s\n", o->name, s->name);
273 for (t = o->testcases; t; t = t->next) {
274 printf("%s.%s\n", o->name, t->name);
279 void torture_print_testsuites(bool structured)
281 if (structured) {
282 print_structured_testsuite_list();
283 } else {
284 print_testsuite_list();
288 _NORETURN_ static void usage(poptContext pc)
290 poptPrintUsage(pc, stdout, 0);
291 printf("\n");
293 printf("The binding format is:\n\n");
295 printf(" TRANSPORT:host[flags]\n\n");
297 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
298 printf(" or ncalrpc for local connections.\n\n");
300 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
301 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
302 printf(" string.\n\n");
304 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
305 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
306 printf(" will be auto-determined.\n\n");
308 printf(" other recognised flags are:\n\n");
310 printf(" sign : enable ntlmssp signing\n");
311 printf(" seal : enable ntlmssp sealing\n");
312 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
313 printf(" validate: enable the NDR validator\n");
314 printf(" print: enable debugging of the packets\n");
315 printf(" bigendian: use bigendian RPC\n");
316 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
318 printf(" For example, these all connect to the samr pipe:\n\n");
320 printf(" ncacn_np:myserver\n");
321 printf(" ncacn_np:myserver[samr]\n");
322 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
323 printf(" ncacn_np:myserver[/pipe/samr]\n");
324 printf(" ncacn_np:myserver[samr,sign,print]\n");
325 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
326 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
327 printf(" ncacn_np:\n");
328 printf(" ncacn_np:[/pipe/samr]\n\n");
330 printf(" ncacn_ip_tcp:myserver\n");
331 printf(" ncacn_ip_tcp:myserver[1024]\n");
332 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
334 printf(" ncalrpc:\n\n");
336 printf("The UNC format is:\n\n");
338 printf(" //server/share\n\n");
340 printf("Tests are:");
342 print_structured_testsuite_list();
344 exit(1);
347 _NORETURN_ static void max_runtime_handler(int sig)
349 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
350 exit(1);
353 struct timeval last_suite_started;
355 static void simple_suite_start(struct torture_context *ctx,
356 struct torture_suite *suite)
358 last_suite_started = timeval_current();
359 printf("Running %s\n", suite->name);
362 static void simple_suite_finish(struct torture_context *ctx,
363 struct torture_suite *suite)
366 printf("%s took %g secs\n\n", suite->name,
367 timeval_elapsed(&last_suite_started));
370 static void simple_test_result(struct torture_context *context,
371 enum torture_result res, const char *reason)
373 switch (res) {
374 case TORTURE_OK:
375 if (reason)
376 printf("OK: %s\n", reason);
377 break;
378 case TORTURE_FAIL:
379 printf("TEST %s FAILED! - %s\n", context->active_test->name, reason);
380 break;
381 case TORTURE_ERROR:
382 printf("ERROR IN TEST %s! - %s\n", context->active_test->name, reason);
383 break;
384 case TORTURE_SKIP:
385 printf("SKIP: %s - %s\n", context->active_test->name, reason);
386 break;
390 static void simple_comment(struct torture_context *test,
391 const char *comment)
393 printf("%s", comment);
396 static void simple_warning(struct torture_context *test,
397 const char *comment)
399 fprintf(stderr, "WARNING: %s\n", comment);
402 static void simple_progress(struct torture_context *test,
403 int offset, enum torture_progress_whence whence)
407 const static struct torture_ui_ops std_ui_ops = {
408 .comment = simple_comment,
409 .warning = simple_warning,
410 .suite_start = simple_suite_start,
411 .suite_finish = simple_suite_finish,
412 .test_result = simple_test_result,
413 .progress = simple_progress,
416 /****************************************************************************
417 main program
418 ****************************************************************************/
419 int main(int argc,char *argv[])
421 int opt, i;
422 bool correct = true;
423 int max_runtime=0;
424 int argc_new;
425 struct torture_context *torture;
426 struct torture_results *results;
427 const struct torture_ui_ops *ui_ops;
428 char **argv_new;
429 poptContext pc;
430 static const char *target = "other";
431 NTSTATUS status;
432 int shell = false;
433 static const char *ui_ops_name = "subunit";
434 const char *basedir = NULL;
435 char *outputdir;
436 const char *extra_module = NULL;
437 static int list_tests = 0, list_testsuites = 0;
438 int num_extra_users = 0;
439 char **restricted = NULL;
440 int num_restricted = -1;
441 const char *load_list = NULL;
442 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
443 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
444 OPT_EXTRA_USER,};
446 struct poptOption long_options[] = {
447 POPT_AUTOHELP
448 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
449 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
450 {"basedir", 0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
451 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "Seed to use for randomizer", NULL},
452 {"num-progs", 0, POPT_ARG_INT, NULL, OPT_NUMPROGS, "num progs", NULL},
453 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
454 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
455 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "NBench load file to use", NULL},
456 {"list-suites", 0, POPT_ARG_NONE, &list_testsuites, 0, "List available testsuites and exit", NULL },
457 {"list", 0, POPT_ARG_NONE, &list_tests, 0, "List available tests in specified suites and exit", NULL },
458 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
459 {"timelimit", 't', POPT_ARG_INT, NULL, OPT_TIMELIMIT, "Set time limit (in seconds)", NULL},
460 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
461 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
462 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
463 "run dangerous tests (eg. wiping out password database)", NULL},
464 {"load-module", 0, POPT_ARG_STRING, &extra_module, 0, "load tests from DSO file", "SOFILE"},
465 {"shell", 0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
466 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
467 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
468 "run async tests", NULL},
469 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
470 "number of simultaneous async requests", NULL},
471 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
472 "set maximum time for smbtorture to live", "seconds"},
473 {"extra-user", 0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
474 "extra user credentials", NULL},
475 {"load-list", 0, POPT_ARG_STRING, &load_list, 0,
476 "load a test id list from a text file", NULL},
477 POPT_COMMON_SAMBA
478 POPT_COMMON_CONNECTION
479 POPT_COMMON_CREDENTIALS
480 POPT_COMMON_VERSION
481 { NULL }
484 setlinebuf(stdout);
486 /* we are never interested in SIGPIPE */
487 BlockSignals(true, SIGPIPE);
489 pc = poptGetContext("smbtorture", argc, (const char **) argv, long_options,
490 POPT_CONTEXT_KEEP_FIRST);
492 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
494 while((opt = poptGetNextOpt(pc)) != -1) {
495 switch (opt) {
496 case OPT_LOADFILE:
497 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:loadfile", poptGetOptArg(pc));
498 break;
499 case OPT_UNCLIST:
500 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:unclist", poptGetOptArg(pc));
501 break;
502 case OPT_TIMELIMIT:
503 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:timelimit", poptGetOptArg(pc));
504 break;
505 case OPT_NUMPROGS:
506 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:nprocs", poptGetOptArg(pc));
507 break;
508 case OPT_DNS:
509 parse_dns(cmdline_lp_ctx, poptGetOptArg(pc));
510 break;
511 case OPT_DANGEROUS:
512 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:dangerous", "Yes");
513 break;
514 case OPT_ASYNC:
515 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:async", "Yes");
516 break;
517 case OPT_SMB_PORTS:
518 lpcfg_set_cmdline(cmdline_lp_ctx, "smb ports", poptGetOptArg(pc));
519 break;
520 case OPT_EXTRA_USER:
522 char *option = talloc_asprintf(NULL, "torture:extra_user%u",
523 ++num_extra_users);
524 const char *value = poptGetOptArg(pc);
525 lpcfg_set_cmdline(cmdline_lp_ctx, option, value);
526 talloc_free(option);
528 break;
529 default:
530 if (opt < 0) {
531 printf("bad command line option %d\n", opt);
532 exit(1);
537 if (load_list != NULL) {
538 restricted = file_lines_load(load_list, &num_restricted, 0,
539 talloc_autofree_context());
540 if (restricted == NULL) {
541 printf("Unable to read load list file '%s'\n", load_list);
542 exit(1);
546 if (strcmp(target, "samba3") == 0) {
547 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba3", "true");
548 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
549 } else if (strcmp(target, "samba4") == 0) {
550 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:samba4", "true");
551 } else if (strcmp(target, "winxp") == 0) {
552 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:winxp", "true");
553 } else if (strcmp(target, "w2k3") == 0) {
554 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k3", "true");
555 } else if (strcmp(target, "w2k8") == 0) {
556 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:w2k8", "true");
557 lpcfg_set_cmdline(cmdline_lp_ctx,
558 "torture:invalid_lock_range_support", "false");
559 } else if (strcmp(target, "win7") == 0) {
560 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:win7", "true");
561 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:cn_max_buffer_size",
562 "0x00010000");
563 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
564 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
566 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
567 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_support", "false");
569 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:hide_on_access_denied",
570 "true");
571 } else if (strcmp(target, "onefs") == 0) {
572 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:onefs", "true");
573 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:openx_deny_dos_support",
574 "false");
575 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:range_not_locked_on_file_close", "false");
576 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:sacl_support", "false");
577 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:ea_support", "false");
578 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smbexit_pdu_support",
579 "false");
580 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:smblock_pdu_support",
581 "false");
582 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:2_step_break_to_none",
583 "true");
584 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_dos_support", "false");
585 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:deny_fcb_support", "false");
586 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:read_support", "false");
587 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:writeclose_support", "false");
588 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:resume_key_support", "false");
589 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:rewind_support", "false");
590 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:raw_search_search", "false");
591 lpcfg_set_cmdline(cmdline_lp_ctx, "torture:search_ea_size", "false");
594 if (max_runtime) {
595 /* this will only work if nobody else uses alarm(),
596 which means it won't work for some tests, but we
597 can't use the event context method we use for smbd
598 as so many tests create their own event
599 context. This will at least catch most cases. */
600 signal(SIGALRM, max_runtime_handler);
601 alarm(max_runtime);
604 if (extra_module != NULL) {
605 init_module_fn fn = load_module(talloc_autofree_context(), poptGetOptArg(pc));
607 if (fn == NULL)
608 d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
609 else {
610 status = fn();
611 if (NT_STATUS_IS_ERR(status)) {
612 d_printf("Error initializing module %s: %s\n",
613 poptGetOptArg(pc), nt_errstr(status));
616 } else {
617 torture_init();
620 if (list_testsuites) {
621 print_testsuite_list();
622 return 0;
625 argv_new = discard_const_p(char *, poptGetArgs(pc));
627 argc_new = argc;
628 for (i=0; i<argc; i++) {
629 if (argv_new[i] == NULL) {
630 argc_new = i;
631 break;
635 if (list_tests) {
636 if (argc_new == 1) {
637 print_test_list(torture_root, NULL, "");
638 } else {
639 for (i=1;i<argc_new;i++) {
640 print_test_list(torture_root, NULL, argv_new[i]);
643 return 0;
646 if (torture_seed == 0) {
647 torture_seed = time(NULL);
649 printf("Using seed %d\n", torture_seed);
650 srandom(torture_seed);
652 if (!strcmp(ui_ops_name, "simple")) {
653 ui_ops = &std_ui_ops;
654 } else if (!strcmp(ui_ops_name, "subunit")) {
655 ui_ops = &torture_subunit_ui_ops;
656 } else {
657 printf("Unknown output format '%s'\n", ui_ops_name);
658 exit(1);
661 results = torture_results_init(talloc_autofree_context(), ui_ops);
663 torture = torture_context_init(s4_event_context_init(talloc_autofree_context()),
664 results);
665 if (basedir != NULL) {
666 if (basedir[0] != '/') {
667 fprintf(stderr, "Please specify an absolute path to --basedir\n");
668 return 1;
670 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", basedir);
671 } else {
672 char *pwd = talloc_size(torture, PATH_MAX);
673 if (!getcwd(pwd, PATH_MAX)) {
674 fprintf(stderr, "Unable to determine current working directory\n");
675 return 1;
677 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", pwd);
679 if (!outputdir) {
680 fprintf(stderr, "Could not allocate per-run output dir\n");
681 return 1;
683 torture->outputdir = mkdtemp(outputdir);
684 if (!torture->outputdir) {
685 perror("Failed to make temp output dir");
688 torture->lp_ctx = cmdline_lp_ctx;
690 gensec_init(cmdline_lp_ctx);
692 if (shell) {
693 /* In shell mode, just ignore any remaining test names. */
694 torture_shell(torture);
695 } else {
697 /* At this point, we should just have a target string,
698 * followed by a series of test names. Unless we are in
699 * shell mode, in which case we don't need anythig more.
702 if (argc_new < 3) {
703 printf("You must specify a test to run, or 'ALL'\n");
704 usage(pc);
705 exit(1);
708 /* Take the target name or binding. */
709 if (!torture_parse_target(cmdline_lp_ctx, argv_new[1])) {
710 usage(pc);
711 exit(1);
714 for (i=2;i<argc_new;i++) {
715 if (!torture_run_named_tests(torture, argv_new[i],
716 (const char **)restricted)) {
717 correct = false;
722 /* Now delete the temp dir we created */
723 torture_deltree_outputdir(torture);
725 if (torture->results->returncode && correct) {
726 return(0);
727 } else {
728 return(1);