s4: torture: Add an async SMB2_OP_FLUSH + SMB2_OP_CLOSE test to smb2.compound_async.
[Samba.git] / source4 / torture / smbtorture.c
blobb2e7b873620651123314afac74078142377cb262
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/cmdline.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"
35 #include "lib/util/samba_modules.h"
37 #ifdef HAVE_READLINE_HISTORY_H
38 #include <readline/history.h>
39 #endif
41 static int use_fullname;
43 static char *prefix_name(TALLOC_CTX *mem_ctx, const char *prefix, const char *name)
45 if (prefix == NULL)
46 return talloc_strdup(mem_ctx, name);
47 else
48 return talloc_asprintf(mem_ctx, "%s.%s", prefix, name);
51 static void print_test_list(const struct torture_suite *suite, const char *prefix, const char *expr)
53 struct torture_suite *o;
54 struct torture_tcase *t;
55 struct torture_test *p;
57 for (o = suite->children; o; o = o->next) {
58 char *name = prefix_name(NULL, prefix, o->name);
59 print_test_list(o, name, expr);
60 talloc_free(name);
63 for (t = suite->testcases; t; t = t->next) {
64 for (p = t->tests; p; p = p->next) {
65 char *name = talloc_asprintf(NULL, "%s.%s.%s", prefix, t->name, p->name);
66 if (strncmp(name, expr, strlen(expr)) == 0) {
67 printf("%s\n", name);
69 talloc_free(name);
74 static bool run_matching(struct torture_context *torture,
75 const char *prefix,
76 const char *expr,
77 const char **restricted,
78 struct torture_suite *suite,
79 bool *matched)
81 bool ret = true;
82 struct torture_suite *o;
83 struct torture_tcase *t;
84 struct torture_test *p;
86 for (o = suite->children; o; o = o->next) {
87 char *name = NULL;
88 name = prefix_name(torture, prefix, o->name);
89 if (gen_fnmatch(expr, name) == 0) {
90 *matched = true;
91 reload_charcnv(torture->lp_ctx);
92 if (use_fullname == 1) {
93 torture_subunit_prefix_reset(torture, prefix);
95 ret &= torture_run_suite_restricted(torture, o, restricted);
96 if (use_fullname == 1) {
97 torture_subunit_prefix_reset(torture, NULL);
100 * torture_run_suite_restricted() already implements
101 * recursion, so we're done with this child suite.
103 continue;
105 ret &= run_matching(torture, name, expr, restricted, o, matched);
108 for (t = suite->testcases; t; t = t->next) {
109 char *tname = prefix_name(torture, prefix, t->name);
110 if (gen_fnmatch(expr, tname) == 0) {
111 *matched = true;
112 reload_charcnv(torture->lp_ctx);
113 if (use_fullname == 1) {
114 torture_subunit_prefix_reset(torture, prefix);
116 ret &= torture_run_tcase_restricted(torture, t, restricted);
117 if (use_fullname == 1) {
118 torture_subunit_prefix_reset(torture, NULL);
121 * torture_run_tcase_restricted() already implements
122 * recursion, so we're done for this tcase.
124 continue;
126 for (p = t->tests; p; p = p->next) {
127 char *pname = prefix_name(torture, tname, p->name);
128 if (gen_fnmatch(expr, pname) == 0) {
129 *matched = true;
130 reload_charcnv(torture->lp_ctx);
131 if (use_fullname == 1) {
132 torture_subunit_prefix_reset(torture,
133 tname);
135 ret &= torture_run_test_restricted(torture, t, p, restricted);
136 if (use_fullname == 1) {
137 torture_subunit_prefix_reset(torture,
138 NULL);
144 return ret;
147 #define MAX_COLS 80 /* FIXME: Determine this at run-time */
149 /****************************************************************************
150 run a specified test or "ALL"
151 ****************************************************************************/
152 bool torture_run_named_tests(struct torture_context *torture, const char *name,
153 const char **restricted)
155 bool ret = true;
156 bool matched = false;
157 struct torture_suite *o;
159 torture_ui_report_time(torture);
161 if (strequal(name, "ALL")) {
162 if (restricted != NULL) {
163 printf("--load-list and ALL are incompatible\n");
164 return false;
166 for (o = torture_root->children; o; o = o->next) {
167 ret &= torture_run_suite(torture, o);
169 return ret;
172 ret = run_matching(torture, NULL, name, restricted, torture_root, &matched);
174 if (!matched) {
175 printf("Unknown torture operation '%s'\n", name);
176 return false;
179 return ret;
182 bool torture_parse_target(TALLOC_CTX *ctx,
183 struct loadparm_context *lp_ctx,
184 const char *target)
186 char *host = NULL, *share = NULL;
187 struct dcerpc_binding *binding_struct;
188 NTSTATUS status;
190 /* see if its a RPC transport specifier */
191 if (!smbcli_parse_unc(target, NULL, &host, &share)) {
192 const char *h;
194 status = dcerpc_parse_binding(ctx, target, &binding_struct);
195 if (NT_STATUS_IS_ERR(status)) {
196 d_printf("Invalid option: %s is not a valid torture target (share or binding string)\n\n", target);
197 return false;
200 h = dcerpc_binding_get_string_option(binding_struct, "host");
201 host = discard_const_p(char, h);
202 if (host != NULL) {
203 lpcfg_set_cmdline(lp_ctx, "torture:host", host);
206 if (lpcfg_parm_string(lp_ctx, NULL, "torture", "share") == NULL)
207 lpcfg_set_cmdline(lp_ctx, "torture:share", "IPC$");
208 lpcfg_set_cmdline(lp_ctx, "torture:binding", target);
209 } else {
210 lpcfg_set_cmdline(lp_ctx, "torture:host", host);
211 lpcfg_set_cmdline(lp_ctx, "torture:share", share);
212 lpcfg_set_cmdline(lp_ctx, "torture:binding", host);
215 return true;
218 static void parse_dns(struct loadparm_context *lp_ctx, const char *dns)
220 char *userdn, *basedn, *secret;
221 char *p, *d;
223 /* retrieve the userdn */
224 p = strchr_m(dns, '#');
225 if (!p) {
226 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", "");
227 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
228 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
229 return;
231 userdn = strndup(dns, p - dns);
232 lpcfg_set_cmdline(lp_ctx, "torture:ldap_userdn", userdn);
234 /* retrieve the basedn */
235 d = p + 1;
236 p = strchr_m(d, '#');
237 if (!p) {
238 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", "");
239 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
240 return;
242 basedn = strndup(d, p - d);
243 lpcfg_set_cmdline(lp_ctx, "torture:ldap_basedn", basedn);
245 /* retrieve the secret */
246 p = p + 1;
247 if (!p) {
248 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", "");
249 return;
251 secret = strdup(p);
252 lpcfg_set_cmdline(lp_ctx, "torture:ldap_secret", secret);
254 printf ("%s - %s - %s\n", userdn, basedn, secret);
258 /* Print the full test list, formatted into separate labelled test
259 * groups.
261 static void print_structured_testsuite_list(void)
263 struct torture_suite *o;
264 struct torture_suite *s;
265 struct torture_tcase *t;
266 int i;
268 if (torture_root == NULL) {
269 printf("NO TESTS LOADED\n");
270 return;
273 for (o = torture_root->children; o; o = o->next) {
274 printf("\n%s (%s):\n ", o->description, o->name);
276 i = 0;
277 for (s = o->children; s; s = s->next) {
278 if (i + strlen(o->name) + strlen(s->name) >= (MAX_COLS - 3)) {
279 printf("\n ");
280 i = 0;
282 i+=printf("%s.%s ", o->name, s->name);
285 for (t = o->testcases; t; t = t->next) {
286 if (i + strlen(o->name) + strlen(t->name) >= (MAX_COLS - 3)) {
287 printf("\n ");
288 i = 0;
290 i+=printf("%s.%s ", o->name, t->name);
293 if (i) printf("\n");
296 printf("\nThe default test is ALL.\n");
299 static void print_testsuite_list(void)
301 struct torture_suite *o;
302 struct torture_suite *s;
303 struct torture_tcase *t;
305 if (torture_root == NULL)
306 return;
308 for (o = torture_root->children; o; o = o->next) {
309 for (s = o->children; s; s = s->next) {
310 printf("%s.%s\n", o->name, s->name);
313 for (t = o->testcases; t; t = t->next) {
314 printf("%s.%s\n", o->name, t->name);
319 void torture_print_testsuites(bool structured)
321 if (structured) {
322 print_structured_testsuite_list();
323 } else {
324 print_testsuite_list();
328 static void usage(poptContext pc)
330 poptPrintUsage(pc, stdout, 0);
331 printf("\n");
333 printf("The binding format is:\n\n");
335 printf(" TRANSPORT:host[flags]\n\n");
337 printf(" where TRANSPORT is either ncacn_np for SMB, ncacn_ip_tcp for RPC/TCP\n");
338 printf(" or ncalrpc for local connections.\n\n");
340 printf(" 'host' is an IP or hostname or netbios name. If the binding string\n");
341 printf(" identifies the server side of an endpoint, 'host' may be an empty\n");
342 printf(" string.\n\n");
344 printf(" 'flags' can include a SMB pipe name if using the ncacn_np transport or\n");
345 printf(" a TCP port number if using the ncacn_ip_tcp transport, otherwise they\n");
346 printf(" will be auto-determined.\n\n");
348 printf(" other recognised flags are:\n\n");
350 printf(" sign : enable ntlmssp signing\n");
351 printf(" seal : enable ntlmssp sealing\n");
352 printf(" connect : enable rpc connect level auth (auth, but no sign or seal)\n");
353 printf(" validate: enable the NDR validator\n");
354 printf(" print: enable debugging of the packets\n");
355 printf(" bigendian: use bigendian RPC\n");
356 printf(" padcheck: check reply data for non-zero pad bytes\n\n");
358 printf(" For example, these all connect to the samr pipe:\n\n");
360 printf(" ncacn_np:myserver\n");
361 printf(" ncacn_np:myserver[samr]\n");
362 printf(" ncacn_np:myserver[\\pipe\\samr]\n");
363 printf(" ncacn_np:myserver[/pipe/samr]\n");
364 printf(" ncacn_np:myserver[samr,sign,print]\n");
365 printf(" ncacn_np:myserver[\\pipe\\samr,sign,seal,bigendian]\n");
366 printf(" ncacn_np:myserver[/pipe/samr,seal,validate]\n");
367 printf(" ncacn_np:\n");
368 printf(" ncacn_np:[/pipe/samr]\n\n");
370 printf(" ncacn_ip_tcp:myserver\n");
371 printf(" ncacn_ip_tcp:myserver[1024]\n");
372 printf(" ncacn_ip_tcp:myserver[1024,sign,seal]\n\n");
374 printf(" ncalrpc:\n\n");
376 printf("The UNC format is:\n\n");
378 printf(" //server/share\n\n");
380 printf("Tests are:");
382 print_structured_testsuite_list();
386 _NORETURN_ static void max_runtime_handler(int sig)
388 DEBUG(0,("maximum runtime exceeded for smbtorture - terminating\n"));
389 exit(1);
392 /****************************************************************************
393 main program
394 ****************************************************************************/
395 int main(int argc, const char *argv[])
397 int opt, i;
398 bool correct = true;
399 int max_runtime=0;
400 int argc_new;
401 struct torture_context *torture;
402 struct torture_results *results;
403 const struct torture_ui_ops *ui_ops;
404 char **argv_new;
405 poptContext pc;
406 static const char *target = "other";
407 NTSTATUS status;
408 int shell = false;
409 static const char *ui_ops_name = "subunit";
410 const char *basedir = NULL;
411 char *outputdir;
412 const char *extra_module = NULL;
413 static int list_tests = 0, list_testsuites = 0;
414 int num_extra_users = 0;
415 const char **restricted = NULL;
416 int num_restricted = -1;
417 const char *load_list = NULL;
418 enum {OPT_LOADFILE=1000,OPT_UNCLIST,OPT_TIMELIMIT,OPT_DNS, OPT_LIST,
419 OPT_DANGEROUS,OPT_SMB_PORTS,OPT_ASYNC,OPT_NUMPROGS,
420 OPT_EXTRA_USER,};
421 TALLOC_CTX *mem_ctx = NULL;
422 struct loadparm_context *lp_ctx = NULL;
423 bool ok;
425 struct poptOption long_options[] = {
426 POPT_AUTOHELP
427 {"fullname", 0, POPT_ARG_NONE, &use_fullname, 0,
428 "use full name for the test", NULL },
429 {"format", 0, POPT_ARG_STRING, &ui_ops_name, 0, "Output format (one of: simple, subunit)", NULL },
430 {"smb-ports", 'p', POPT_ARG_STRING, NULL, OPT_SMB_PORTS, "SMB ports", NULL},
431 {"basedir", 0, POPT_ARG_STRING, &basedir, 0, "base directory", "BASEDIR" },
432 {"seed", 0, POPT_ARG_INT, &torture_seed, 0, "Seed to use for randomizer", NULL},
433 {"num-progs", 0, POPT_ARG_INT, NULL, OPT_NUMPROGS, "num progs", NULL},
434 {"num-ops", 0, POPT_ARG_INT, &torture_numops, 0, "num ops", NULL},
435 {"entries", 0, POPT_ARG_INT, &torture_entries, 0, "entries", NULL},
436 {"loadfile", 0, POPT_ARG_STRING, NULL, OPT_LOADFILE, "NBench load file to use", NULL},
437 {"list-suites", 0, POPT_ARG_NONE, &list_testsuites, 0, "List available testsuites and exit", NULL },
438 {"list", 0, POPT_ARG_NONE, &list_tests, 0, "List available tests in specified suites and exit", NULL },
439 {"unclist", 0, POPT_ARG_STRING, NULL, OPT_UNCLIST, "unclist", NULL},
440 {"timelimit", 't', POPT_ARG_INT, NULL, OPT_TIMELIMIT, "Set time limit (in seconds)", NULL},
441 {"failures", 'f', POPT_ARG_INT, &torture_failures, 0, "failures", NULL},
442 {"parse-dns", 'D', POPT_ARG_STRING, NULL, OPT_DNS, "parse-dns", NULL},
443 {"dangerous", 'X', POPT_ARG_NONE, NULL, OPT_DANGEROUS,
444 "run dangerous tests (eg. wiping out password database)", NULL},
445 {"load-module", 0, POPT_ARG_STRING, &extra_module, 0, "load tests from DSO file", "SOFILE"},
446 {"shell", 0, POPT_ARG_NONE, &shell, true, "Run shell", NULL},
447 {"target", 'T', POPT_ARG_STRING, &target, 0, "samba3|samba4|other", NULL},
448 {"async", 'a', POPT_ARG_NONE, NULL, OPT_ASYNC,
449 "run async tests", NULL},
450 {"num-async", 0, POPT_ARG_INT, &torture_numasync, 0,
451 "number of simultaneous async requests", NULL},
452 {"maximum-runtime", 0, POPT_ARG_INT, &max_runtime, 0,
453 "set maximum time for smbtorture to live", "seconds"},
454 {"extra-user", 0, POPT_ARG_STRING, NULL, OPT_EXTRA_USER,
455 "extra user credentials", NULL},
456 {"load-list", 0, POPT_ARG_STRING, &load_list, 0,
457 "load a test id list from a text file", NULL},
458 POPT_COMMON_SAMBA
459 POPT_COMMON_CONNECTION
460 POPT_COMMON_CREDENTIALS
461 POPT_COMMON_VERSION
462 POPT_LEGACY_S4
463 POPT_TABLEEND
466 setlinebuf(stdout);
468 mem_ctx = talloc_named_const(NULL, 0, "torture_ctx");
469 if (mem_ctx == NULL) {
470 printf("Unable to allocate torture_ctx\n");
471 exit(1);
474 printf("smbtorture %s\n", samba_version_string());
476 /* we are never interested in SIGPIPE */
477 BlockSignals(true, SIGPIPE);
479 ok = samba_cmdline_init(mem_ctx,
480 SAMBA_CMDLINE_CONFIG_CLIENT,
481 false /* require_smbconf */);
482 if (!ok) {
483 DBG_ERR("Unable to init cmdline parser\n");
484 TALLOC_FREE(mem_ctx);
485 exit(1);
488 pc = samba_popt_get_context(getprogname(),
489 argc,
490 argv,
491 long_options,
492 POPT_CONTEXT_KEEP_FIRST);
493 if (pc == NULL) {
494 DBG_ERR("Failed cmdline parser\n");
495 TALLOC_FREE(mem_ctx);
496 exit(1);
499 poptSetOtherOptionHelp(pc, "<binding>|<unc> TEST1 TEST2 ...");
501 lp_ctx = samba_cmdline_get_lp_ctx();
503 while((opt = poptGetNextOpt(pc)) != -1) {
504 switch (opt) {
505 case OPT_LOADFILE:
506 lpcfg_set_cmdline(lp_ctx, "torture:loadfile", poptGetOptArg(pc));
507 break;
508 case OPT_UNCLIST:
509 lpcfg_set_cmdline(lp_ctx, "torture:unclist", poptGetOptArg(pc));
510 break;
511 case OPT_TIMELIMIT:
512 lpcfg_set_cmdline(lp_ctx, "torture:timelimit", poptGetOptArg(pc));
513 break;
514 case OPT_NUMPROGS:
515 lpcfg_set_cmdline(lp_ctx, "torture:nprocs", poptGetOptArg(pc));
516 break;
517 case OPT_DNS:
518 parse_dns(lp_ctx, poptGetOptArg(pc));
519 break;
520 case OPT_DANGEROUS:
521 lpcfg_set_cmdline(lp_ctx, "torture:dangerous", "Yes");
522 break;
523 case OPT_ASYNC:
524 lpcfg_set_cmdline(lp_ctx, "torture:async", "Yes");
525 break;
526 case OPT_SMB_PORTS:
527 lpcfg_set_cmdline(lp_ctx, "smb ports", poptGetOptArg(pc));
528 break;
529 case OPT_EXTRA_USER:
531 char *option = talloc_asprintf(mem_ctx,
532 "torture:extra_user%u",
533 ++num_extra_users);
534 const char *value = poptGetOptArg(pc);
535 if (option == NULL) {
536 printf("talloc fail\n");
537 talloc_free(mem_ctx);
538 exit(1);
540 lpcfg_set_cmdline(lp_ctx, option, value);
541 talloc_free(option);
543 break;
544 default:
545 if (opt < 0) {
546 printf("Invalid command line option %s (%d)\n",
547 poptBadOption(pc, 0),
548 opt);
549 talloc_free(mem_ctx);
550 exit(1);
555 if (load_list != NULL) {
556 char **r;
557 r = file_lines_load(load_list, &num_restricted, 0, mem_ctx);
558 restricted = discard_const_p(const char *, r);
559 if (restricted == NULL) {
560 printf("Unable to read load list file '%s'\n", load_list);
561 talloc_free(mem_ctx);
562 exit(1);
566 if (strcmp(target, "samba3") == 0) {
567 lpcfg_set_cmdline(lp_ctx, "torture:samba3", "true");
568 lpcfg_set_cmdline(lp_ctx, "torture:resume_key_support", "false");
569 } else if (strcmp(target, "samba4") == 0) {
570 lpcfg_set_cmdline(lp_ctx, "torture:samba4", "true");
571 } else if (strcmp(target, "samba4-ntvfs") == 0) {
572 lpcfg_set_cmdline(lp_ctx, "torture:samba4", "true");
573 lpcfg_set_cmdline(lp_ctx, "torture:samba4-ntvfs", "true");
574 } else if (strcmp(target, "winxp") == 0) {
575 lpcfg_set_cmdline(lp_ctx, "torture:winxp", "true");
576 } else if (strcmp(target, "w2k3") == 0) {
577 lpcfg_set_cmdline(lp_ctx, "torture:w2k3", "true");
578 } else if (strcmp(target, "w2k8") == 0) {
579 lpcfg_set_cmdline(lp_ctx, "torture:w2k8", "true");
580 lpcfg_set_cmdline(lp_ctx,
581 "torture:invalid_lock_range_support", "false");
582 } else if (strcmp(target, "w2k12") == 0) {
583 lpcfg_set_cmdline(lp_ctx, "torture:w2k12", "true");
584 } else if (strcmp(target, "win7") == 0) {
585 lpcfg_set_cmdline(lp_ctx, "torture:win7", "true");
586 lpcfg_set_cmdline(lp_ctx, "torture:resume_key_support", "false");
587 lpcfg_set_cmdline(lp_ctx, "torture:rewind_support", "false");
589 /* RAW-SEARCH for fails for inexplicable reasons against win7 */
590 lpcfg_set_cmdline(lp_ctx, "torture:search_ea_support", "false");
592 lpcfg_set_cmdline(lp_ctx, "torture:hide_on_access_denied",
593 "true");
594 } else if (strcmp(target, "onefs") == 0) {
595 lpcfg_set_cmdline(lp_ctx, "torture:onefs", "true");
596 lpcfg_set_cmdline(lp_ctx, "torture:openx_deny_dos_support",
597 "false");
598 lpcfg_set_cmdline(lp_ctx, "torture:range_not_locked_on_file_close", "false");
599 lpcfg_set_cmdline(lp_ctx, "torture:sacl_support", "false");
600 lpcfg_set_cmdline(lp_ctx, "torture:ea_support", "false");
601 lpcfg_set_cmdline(lp_ctx, "torture:smbexit_pdu_support",
602 "false");
603 lpcfg_set_cmdline(lp_ctx, "torture:smblock_pdu_support",
604 "false");
605 lpcfg_set_cmdline(lp_ctx, "torture:2_step_break_to_none",
606 "true");
607 lpcfg_set_cmdline(lp_ctx, "torture:deny_dos_support", "false");
608 lpcfg_set_cmdline(lp_ctx, "torture:deny_fcb_support", "false");
609 lpcfg_set_cmdline(lp_ctx, "torture:read_support", "false");
610 lpcfg_set_cmdline(lp_ctx, "torture:writeclose_support", "false");
611 lpcfg_set_cmdline(lp_ctx, "torture:resume_key_support", "false");
612 lpcfg_set_cmdline(lp_ctx, "torture:rewind_support", "false");
613 lpcfg_set_cmdline(lp_ctx, "torture:raw_search_search", "false");
614 lpcfg_set_cmdline(lp_ctx, "torture:search_ea_size", "false");
617 if (max_runtime) {
618 /* this will only work if nobody else uses alarm(),
619 which means it won't work for some tests, but we
620 can't use the event context method we use for smbd
621 as so many tests create their own event
622 context. This will at least catch most cases. */
623 signal(SIGALRM, max_runtime_handler);
624 alarm(max_runtime);
627 if (extra_module != NULL) {
628 init_module_fn fn = load_module(poptGetOptArg(pc), false, NULL);
630 if (fn == NULL)
631 d_printf("Unable to load module from %s\n", poptGetOptArg(pc));
632 else {
633 status = fn(mem_ctx);
634 if (NT_STATUS_IS_ERR(status)) {
635 d_printf("Error initializing module %s: %s\n",
636 poptGetOptArg(pc), nt_errstr(status));
639 } else {
640 torture_init(mem_ctx);
643 if (list_testsuites) {
644 print_testsuite_list();
645 poptFreeContext(pc);
646 talloc_free(mem_ctx);
647 return 0;
650 argv_new = discard_const_p(char *, poptGetArgs(pc));
652 argc_new = argc;
653 for (i=0; i<argc; i++) {
654 if (argv_new[i] == NULL) {
655 argc_new = i;
656 break;
660 if (list_tests) {
661 if (argc_new == 1) {
662 print_test_list(torture_root, NULL, "");
663 } else {
664 for (i=1;i<argc_new;i++) {
665 print_test_list(torture_root, NULL, argv_new[i]);
668 poptFreeContext(pc);
669 talloc_free(mem_ctx);
670 return 0;
673 if (torture_seed == 0) {
674 torture_seed = time(NULL);
676 printf("Using seed %d\n", torture_seed);
677 srandom(torture_seed);
679 if (!strcmp(ui_ops_name, "simple")) {
680 ui_ops = &torture_simple_ui_ops;
681 } else if (!strcmp(ui_ops_name, "subunit")) {
682 ui_ops = &torture_subunit_ui_ops;
683 } else {
684 printf("Unknown output format '%s'\n", ui_ops_name);
685 talloc_free(mem_ctx);
686 exit(1);
689 results = torture_results_init(mem_ctx, ui_ops);
691 torture = torture_context_init(s4_event_context_init(mem_ctx),
692 results);
693 if (basedir != NULL) {
694 if (basedir[0] != '/') {
695 fprintf(stderr, "Please specify an absolute path to --basedir\n");
696 poptFreeContext(pc);
697 talloc_free(mem_ctx);
698 return 1;
700 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", basedir);
701 } else {
702 char *pwd = talloc_size(torture, PATH_MAX);
703 if (!getcwd(pwd, PATH_MAX)) {
704 fprintf(stderr, "Unable to determine current working directory\n");
705 poptFreeContext(pc);
706 talloc_free(mem_ctx);
707 return 1;
709 outputdir = talloc_asprintf(torture, "%s/smbtortureXXXXXX", pwd);
711 if (!outputdir) {
712 fprintf(stderr, "Could not allocate per-run output dir\n");
713 poptFreeContext(pc);
714 talloc_free(mem_ctx);
715 return 1;
717 torture->outputdir = mkdtemp(outputdir);
718 if (!torture->outputdir) {
719 perror("Failed to make temp output dir");
720 poptFreeContext(pc);
721 talloc_free(mem_ctx);
722 return 1;
725 torture->lp_ctx = lp_ctx;
727 gensec_init();
729 if (shell) {
730 /* In shell mode, just ignore any remaining test names. */
731 torture_shell(torture);
732 } else {
734 /* At this point, we should just have a target string,
735 * followed by a series of test names. Unless we are in
736 * shell mode, in which case we don't need anythig more.
739 if (argc_new < 3) {
740 printf("You must specify a test to run, or 'ALL'\n");
741 usage(pc);
742 torture->results->returncode = 1;
743 } else if (!torture_parse_target(torture,
744 lp_ctx, argv_new[1])) {
745 /* Take the target name or binding. */
746 usage(pc);
747 torture->results->returncode = 1;
748 } else {
749 for (i=2;i<argc_new;i++) {
750 if (!torture_run_named_tests(torture, argv_new[i],
751 (const char **)restricted)) {
752 correct = false;
758 /* Now delete the temp dir we created */
759 torture_deltree_outputdir(torture);
761 if (torture->results->returncode && correct) {
762 poptFreeContext(pc);
763 talloc_free(mem_ctx);
764 return(0);
765 } else {
766 poptFreeContext(pc);
767 talloc_free(mem_ctx);
768 return(1);