2 Unix SMB/CIFS implementation.
3 SMB torture UI functions
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 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/>.
22 #include "torture/ui.h"
23 #include "torture/torture.h"
24 #include "lib/util/dlinklist.h"
25 #include "param/param.h"
26 #include "system/filesys.h"
29 create a temporary directory.
31 _PUBLIC_ NTSTATUS torture_temp_dir(struct torture_context *tctx,
35 SMB_ASSERT(tctx->outputdir != NULL);
37 *tempdir = talloc_asprintf(tctx, "%s/%s.XXXXXX", tctx->outputdir,
39 NT_STATUS_HAVE_NO_MEMORY(*tempdir);
41 if (mkdtemp(*tempdir) == NULL) {
42 return map_nt_error_from_unix(errno);
48 void torture_comment(struct torture_context *context, const char *comment, ...)
53 if (!context->ui_ops->comment)
56 va_start(ap, comment);
57 tmp = talloc_vasprintf(context, comment, ap);
59 context->ui_ops->comment(context, tmp);
64 void torture_warning(struct torture_context *context, const char *comment, ...)
69 if (!context->ui_ops->warning)
72 va_start(ap, comment);
73 tmp = talloc_vasprintf(context, comment, ap);
75 context->ui_ops->warning(context, tmp);
80 void torture_result(struct torture_context *context,
81 enum torture_result result, const char *fmt, ...)
87 if (context->last_reason) {
88 torture_warning(context, "%s", context->last_reason);
89 talloc_free(context->last_reason);
92 context->last_result = result;
93 context->last_reason = talloc_vasprintf(context, fmt, ap);
97 struct torture_suite *torture_suite_create(TALLOC_CTX *ctx, const char *name)
99 struct torture_suite *suite = talloc_zero(ctx, struct torture_suite);
101 suite->name = talloc_strdup(suite, name);
102 suite->testcases = NULL;
103 suite->children = NULL;
108 void torture_tcase_set_fixture(struct torture_tcase *tcase,
109 bool (*setup) (struct torture_context *, void **),
110 bool (*teardown) (struct torture_context *, void *))
112 tcase->setup = setup;
113 tcase->teardown = teardown;
116 static bool wrap_test_with_testcase_const(struct torture_context *torture_ctx,
117 struct torture_tcase *tcase,
118 struct torture_test *test)
120 bool (*fn) (struct torture_context *,
121 const void *tcase_data,
122 const void *test_data);
126 return fn(torture_ctx, tcase->data, test->data);
129 struct torture_test *torture_tcase_add_test_const(struct torture_tcase *tcase,
131 bool (*run) (struct torture_context *, const void *tcase_data,
132 const void *test_data),
135 struct torture_test *test = talloc(tcase, struct torture_test);
137 test->name = talloc_strdup(test, name);
138 test->description = NULL;
139 test->run = wrap_test_with_testcase_const;
141 test->dangerous = false;
144 DLIST_ADD_END(tcase->tests, test, struct torture_test *);
150 bool torture_suite_init_tcase(struct torture_suite *suite,
151 struct torture_tcase *tcase,
154 tcase->name = talloc_strdup(tcase, name);
155 tcase->description = NULL;
157 tcase->teardown = NULL;
158 tcase->fixture_persistent = true;
161 DLIST_ADD_END(suite->testcases, tcase, struct torture_tcase *);
167 struct torture_tcase *torture_suite_add_tcase(struct torture_suite *suite,
170 struct torture_tcase *tcase = talloc(suite, struct torture_tcase);
172 if (!torture_suite_init_tcase(suite, tcase, name))
178 bool torture_run_suite(struct torture_context *context,
179 struct torture_suite *suite)
182 struct torture_tcase *tcase;
183 struct torture_suite *tsuite;
187 if (context->ui_ops->suite_start)
188 context->ui_ops->suite_start(context, suite);
190 old_testname = context->active_testname;
191 if (old_testname != NULL)
192 context->active_testname = talloc_asprintf(context, "%s-%s",
193 old_testname, suite->name);
195 context->active_testname = talloc_strdup(context, suite->name);
197 for (tcase = suite->testcases; tcase; tcase = tcase->next) {
198 ret &= torture_run_tcase(context, tcase);
201 for (tsuite = suite->children; tsuite; tsuite = tsuite->next) {
202 ret &= torture_run_suite(context, tsuite);
205 talloc_free(context->active_testname);
206 context->active_testname = old_testname;
208 if (context->ui_ops->suite_finish)
209 context->ui_ops->suite_finish(context, suite);
216 void torture_ui_test_start(struct torture_context *context,
217 struct torture_tcase *tcase,
218 struct torture_test *test)
220 if (context->ui_ops->test_start)
221 context->ui_ops->test_start(context, tcase, test);
224 int str_list_match(const char *name, char **list)
230 for (i = 0; list[i]; i++) {
231 if (gen_fnmatch(list[i], name) == 0)
237 void torture_ui_test_result(struct torture_context *context,
238 enum torture_result result,
241 if (context->ui_ops->test_result)
242 context->ui_ops->test_result(context, result, comment);
244 if (result == TORTURE_ERROR || result == TORTURE_FAIL)
245 context->returncode = false;
248 static bool internal_torture_run_test(struct torture_context *context,
249 struct torture_tcase *tcase,
250 struct torture_test *test,
256 if (tcase == NULL || strcmp(test->name, tcase->name) != 0) {
257 old_testname = context->active_testname;
258 context->active_testname = talloc_asprintf(context, "%s-%s", old_testname, test->name);
261 context->active_tcase = tcase;
262 context->active_test = test;
264 torture_ui_test_start(context, tcase, test);
266 context->last_reason = NULL;
267 context->last_result = TORTURE_OK;
269 if (!already_setup && tcase->setup &&
270 !tcase->setup(context, &(tcase->data))) {
271 if (context->last_reason == NULL)
272 context->last_reason = talloc_strdup(context, "Setup failure");
273 context->last_result = TORTURE_ERROR;
275 } else if (test->dangerous &&
276 !torture_setting_bool(context, "dangerous", false)) {
277 context->last_result = TORTURE_SKIP;
278 context->last_reason = talloc_asprintf(context,
279 "disabled %s - enable dangerous tests to use", test->name);
282 success = test->run(context, tcase, test);
284 if (!success && context->last_result == TORTURE_OK) {
285 if (context->last_reason == NULL)
286 context->last_reason = talloc_strdup(context, "Unknown error/failure");
287 context->last_result = TORTURE_ERROR;
291 if (!already_setup && tcase->teardown && !tcase->teardown(context, tcase->data)) {
292 if (context->last_reason == NULL)
293 context->last_reason = talloc_strdup(context, "Setup failure");
294 context->last_result = TORTURE_ERROR;
298 torture_ui_test_result(context, context->last_result,
299 context->last_reason);
301 talloc_free(context->last_reason);
303 if (tcase == NULL || strcmp(test->name, tcase->name) != 0) {
304 talloc_free(context->active_testname);
305 context->active_testname = old_testname;
307 context->active_test = NULL;
308 context->active_tcase = NULL;
313 bool torture_run_tcase(struct torture_context *context,
314 struct torture_tcase *tcase)
318 struct torture_test *test;
322 context->active_tcase = tcase;
323 if (context->ui_ops->tcase_start)
324 context->ui_ops->tcase_start(context, tcase);
326 if (tcase->fixture_persistent && tcase->setup
327 && !tcase->setup(context, &tcase->data)) {
328 /* FIXME: Use torture ui ops for reporting this error */
329 fprintf(stderr, "Setup failed: ");
330 if (context->last_reason != NULL)
331 fprintf(stderr, "%s", context->last_reason);
332 fprintf(stderr, "\n");
337 old_testname = context->active_testname;
338 context->active_testname = talloc_asprintf(context, "%s-%s",
339 old_testname, tcase->name);
340 for (test = tcase->tests; test; test = test->next) {
341 ret &= internal_torture_run_test(context, tcase, test,
342 tcase->fixture_persistent);
344 talloc_free(context->active_testname);
345 context->active_testname = old_testname;
347 if (tcase->fixture_persistent && tcase->teardown &&
348 !tcase->teardown(context, tcase->data))
352 context->active_tcase = NULL;
354 if (context->ui_ops->tcase_finish)
355 context->ui_ops->tcase_finish(context, tcase);
362 bool torture_run_test(struct torture_context *context,
363 struct torture_tcase *tcase,
364 struct torture_test *test)
366 return internal_torture_run_test(context, tcase, test, false);
369 int torture_setting_int(struct torture_context *test, const char *name,
372 return lp_parm_int(test->lp_ctx, NULL, "torture", name, default_value);
375 double torture_setting_double(struct torture_context *test, const char *name,
376 double default_value)
378 return lp_parm_double(test->lp_ctx, NULL, "torture", name, default_value);
381 bool torture_setting_bool(struct torture_context *test, const char *name,
384 return lp_parm_bool(test->lp_ctx, NULL, "torture", name, default_value);
387 const char *torture_setting_string(struct torture_context *test,
389 const char *default_value)
393 SMB_ASSERT(test != NULL);
394 SMB_ASSERT(test->lp_ctx != NULL);
396 ret = lp_parm_string(test->lp_ctx, NULL, "torture", name);
399 return default_value;
404 static bool wrap_test_with_simple_tcase_const (
405 struct torture_context *torture_ctx,
406 struct torture_tcase *tcase,
407 struct torture_test *test)
409 bool (*fn) (struct torture_context *, const void *tcase_data);
413 return fn(torture_ctx, test->data);
416 struct torture_tcase *torture_suite_add_simple_tcase_const(
417 struct torture_suite *suite, const char *name,
418 bool (*run) (struct torture_context *test, const void *),
421 struct torture_tcase *tcase;
422 struct torture_test *test;
424 tcase = torture_suite_add_tcase(suite, name);
426 test = talloc(tcase, struct torture_test);
428 test->name = talloc_strdup(test, name);
429 test->description = NULL;
430 test->run = wrap_test_with_simple_tcase_const;
433 test->dangerous = false;
435 DLIST_ADD_END(tcase->tests, test, struct torture_test *);
440 static bool wrap_simple_test(struct torture_context *torture_ctx,
441 struct torture_tcase *tcase,
442 struct torture_test *test)
444 bool (*fn) (struct torture_context *);
448 return fn(torture_ctx);
451 struct torture_tcase *torture_suite_add_simple_test(
452 struct torture_suite *suite,
454 bool (*run) (struct torture_context *test))
456 struct torture_test *test;
457 struct torture_tcase *tcase;
459 tcase = torture_suite_add_tcase(suite, name);
461 test = talloc(tcase, struct torture_test);
463 test->name = talloc_strdup(test, name);
464 test->description = NULL;
465 test->run = wrap_simple_test;
467 test->dangerous = false;
469 DLIST_ADD_END(tcase->tests, test, struct torture_test *);
474 bool torture_suite_add_suite(struct torture_suite *suite,
475 struct torture_suite *child)
480 DLIST_ADD_END(suite->children, child, struct torture_suite *);
482 /* FIXME: Check for duplicates and return false if the
483 * added suite already exists as a child */
489 struct torture_suite *torture_find_suite(struct torture_suite *parent,
492 struct torture_suite *child;
494 for (child = parent->children; child; child = child->next)
495 if (!strcmp(child->name, name))
501 static bool wrap_test_with_simple_test_const(struct torture_context *torture_ctx,
502 struct torture_tcase *tcase,
503 struct torture_test *test)
505 bool (*fn) (struct torture_context *, const void *tcase_data);
509 return fn(torture_ctx, tcase->data);
512 struct torture_test *torture_tcase_add_simple_test_const(
513 struct torture_tcase *tcase,
515 bool (*run) (struct torture_context *test,
516 const void *tcase_data))
518 struct torture_test *test;
520 test = talloc(tcase, struct torture_test);
522 test->name = talloc_strdup(test, name);
523 test->description = NULL;
524 test->run = wrap_test_with_simple_test_const;
527 test->dangerous = false;
529 DLIST_ADD_END(tcase->tests, test, struct torture_test *);
534 static bool wrap_test_with_simple_test(struct torture_context *torture_ctx,
535 struct torture_tcase *tcase,
536 struct torture_test *test)
538 bool (*fn) (struct torture_context *, void *tcase_data);
542 return fn(torture_ctx, tcase->data);
545 struct torture_test *torture_tcase_add_simple_test(struct torture_tcase *tcase,
547 bool (*run) (struct torture_context *test, void *tcase_data))
549 struct torture_test *test;
551 test = talloc(tcase, struct torture_test);
553 test->name = talloc_strdup(test, name);
554 test->description = NULL;
555 test->run = wrap_test_with_simple_test;
558 test->dangerous = false;
560 DLIST_ADD_END(tcase->tests, test, struct torture_test *);