Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB torture UI functions
4 :
5 : Copyright (C) Jelmer Vernooij 2006-2008
6 :
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.
11 :
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.
16 :
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/>.
19 : */
20 :
21 : #include "source4/include/includes.h"
22 : #include "../torture/torture.h"
23 : #include "../lib/util/dlinklist.h"
24 : #include "param/param.h"
25 : #include "system/filesys.h"
26 : #include "system/dir.h"
27 :
28 :
29 908 : struct torture_results *torture_results_init(TALLOC_CTX *mem_ctx, const struct torture_ui_ops *ui_ops)
30 : {
31 908 : struct torture_results *results = talloc_zero(mem_ctx, struct torture_results);
32 :
33 908 : results->ui_ops = ui_ops;
34 908 : results->returncode = true;
35 :
36 908 : if (ui_ops->init)
37 0 : ui_ops->init(results);
38 :
39 908 : return results;
40 : }
41 :
42 : /**
43 : * Initialize a torture context
44 : */
45 908 : struct torture_context *torture_context_init(struct tevent_context *event_ctx,
46 : struct torture_results *results)
47 : {
48 908 : struct torture_context *torture = talloc_zero(event_ctx,
49 : struct torture_context);
50 :
51 908 : if (torture == NULL)
52 0 : return NULL;
53 :
54 908 : torture->ev = event_ctx;
55 908 : torture->results = talloc_reference(torture, results);
56 :
57 : /*
58 : * We start with an empty subunit prefix
59 : */
60 908 : torture_subunit_prefix_reset(torture, NULL);
61 :
62 908 : return torture;
63 : }
64 :
65 : /**
66 : * Create a sub torture context
67 : */
68 0 : struct torture_context *torture_context_child(struct torture_context *parent)
69 : {
70 0 : struct torture_context *subtorture = talloc_zero(parent, struct torture_context);
71 :
72 0 : if (subtorture == NULL)
73 0 : return NULL;
74 :
75 0 : subtorture->ev = talloc_reference(subtorture, parent->ev);
76 0 : subtorture->lp_ctx = talloc_reference(subtorture, parent->lp_ctx);
77 0 : subtorture->outputdir = talloc_reference(subtorture, parent->outputdir);
78 0 : subtorture->results = talloc_reference(subtorture, parent->results);
79 :
80 0 : return subtorture;
81 : }
82 :
83 : /**
84 : create a temporary directory under the output dir
85 : */
86 4 : _PUBLIC_ NTSTATUS torture_temp_dir(struct torture_context *tctx,
87 : const char *prefix, char **tempdir)
88 : {
89 4 : SMB_ASSERT(tctx->outputdir != NULL);
90 :
91 4 : *tempdir = talloc_asprintf(tctx, "%s/%s.XXXXXX", tctx->outputdir,
92 : prefix);
93 4 : NT_STATUS_HAVE_NO_MEMORY(*tempdir);
94 :
95 4 : if (mkdtemp(*tempdir) == NULL) {
96 0 : return map_nt_error_from_unix_common(errno);
97 : }
98 :
99 4 : return NT_STATUS_OK;
100 : }
101 :
102 920 : static int local_deltree(const char *path)
103 : {
104 920 : int ret = 0;
105 : struct dirent *dirent;
106 920 : DIR *dir = opendir(path);
107 920 : if (!dir) {
108 0 : char *error = talloc_asprintf(NULL, "Could not open directory %s", path);
109 0 : perror(error);
110 0 : talloc_free(error);
111 0 : return -1;
112 : }
113 3470 : while ((dirent = readdir(dir))) {
114 : char *name;
115 1862 : if ((strcmp(dirent->d_name, ".") == 0) || (strcmp(dirent->d_name, "..") == 0)) {
116 1818 : continue;
117 : }
118 44 : name = talloc_asprintf(NULL, "%s/%s", path,
119 44 : dirent->d_name);
120 44 : if (name == NULL) {
121 0 : closedir(dir);
122 0 : return -1;
123 : }
124 44 : DEBUG(0, ("About to remove %s\n", name));
125 44 : ret = remove(name);
126 44 : if (ret == 0) {
127 32 : talloc_free(name);
128 32 : continue;
129 : }
130 :
131 12 : if (errno == ENOTEMPTY) {
132 12 : ret = local_deltree(name);
133 12 : if (ret == 0) {
134 4 : ret = remove(name);
135 : }
136 : }
137 12 : talloc_free(name);
138 12 : if (ret != 0) {
139 12 : char *error = talloc_asprintf(NULL, "Could not remove %s", path);
140 12 : perror(error);
141 12 : talloc_free(error);
142 12 : break;
143 : }
144 : }
145 920 : closedir(dir);
146 920 : rmdir(path);
147 920 : return ret;
148 : }
149 :
150 908 : _PUBLIC_ NTSTATUS torture_deltree_outputdir(struct torture_context *tctx)
151 : {
152 908 : if (tctx->outputdir == NULL) {
153 0 : return NT_STATUS_OK;
154 : }
155 908 : if ((strcmp(tctx->outputdir, "/") == 0)
156 908 : || (strcmp(tctx->outputdir, "") == 0)) {
157 0 : return NT_STATUS_INVALID_PARAMETER;
158 : }
159 :
160 908 : if (local_deltree(tctx->outputdir) == -1) {
161 4 : if (errno != 0) {
162 4 : return map_nt_error_from_unix_common(errno);
163 : }
164 0 : return NT_STATUS_UNSUCCESSFUL;
165 : }
166 904 : return NT_STATUS_OK;
167 : }
168 :
169 : /**
170 : * Comment on the status/progress of a test
171 : */
172 67235 : void torture_comment(struct torture_context *context, const char *comment, ...)
173 : {
174 : va_list ap;
175 : char *tmp;
176 :
177 67235 : if (!context->results->ui_ops->comment)
178 0 : return;
179 :
180 67235 : va_start(ap, comment);
181 67235 : tmp = talloc_vasprintf(context, comment, ap);
182 67235 : va_end(ap);
183 :
184 67235 : context->results->ui_ops->comment(context, tmp);
185 :
186 67235 : talloc_free(tmp);
187 : }
188 :
189 : /**
190 : * Print a warning about the current test
191 : */
192 1590 : void torture_warning(struct torture_context *context, const char *comment, ...)
193 : {
194 : va_list ap;
195 : char *tmp;
196 :
197 1590 : if (!context->results->ui_ops->warning)
198 0 : return;
199 :
200 1590 : va_start(ap, comment);
201 1590 : tmp = talloc_vasprintf(context, comment, ap);
202 1590 : va_end(ap);
203 :
204 1590 : context->results->ui_ops->warning(context, tmp);
205 :
206 1590 : talloc_free(tmp);
207 : }
208 :
209 : /**
210 : * Store the result of a torture test.
211 : */
212 4998 : void torture_result(struct torture_context *context,
213 : enum torture_result result, const char *fmt, ...)
214 : {
215 : va_list ap;
216 :
217 4998 : va_start(ap, fmt);
218 :
219 4998 : if (context->last_reason) {
220 942 : torture_warning(context, "%s", context->last_reason);
221 942 : talloc_free(context->last_reason);
222 : }
223 :
224 4998 : context->last_result = result;
225 4998 : context->last_reason = talloc_vasprintf(context, fmt, ap);
226 4998 : va_end(ap);
227 4998 : }
228 :
229 : /**
230 : * Create a new torture suite
231 : */
232 1012136 : struct torture_suite *torture_suite_create(TALLOC_CTX *ctx, const char *name)
233 : {
234 1012136 : struct torture_suite *suite = talloc_zero(ctx, struct torture_suite);
235 :
236 1012136 : suite->name = talloc_strdup(suite, name);
237 1012136 : suite->testcases = NULL;
238 1012136 : suite->children = NULL;
239 :
240 1012136 : return suite;
241 : }
242 :
243 : /**
244 : * Set the setup() and teardown() functions for a testcase.
245 : */
246 40488 : void torture_tcase_set_fixture(struct torture_tcase *tcase,
247 : bool (*setup) (struct torture_context *, void **),
248 : bool (*teardown) (struct torture_context *, void *))
249 : {
250 40488 : tcase->setup = setup;
251 40488 : tcase->teardown = teardown;
252 40488 : }
253 :
254 0 : static bool wrap_test_with_testcase_const(struct torture_context *torture_ctx,
255 : struct torture_tcase *tcase,
256 : struct torture_test *test)
257 : {
258 : bool (*fn) (struct torture_context *,
259 : const void *tcase_data,
260 : const void *test_data);
261 :
262 0 : fn = test->fn;
263 :
264 0 : return fn(torture_ctx, tcase->data, test->data);
265 : }
266 :
267 : /**
268 : * Add a test that uses const data to a testcase
269 : */
270 12532 : struct torture_test *torture_tcase_add_test_const(struct torture_tcase *tcase,
271 : const char *name,
272 : bool (*run) (struct torture_context *, const void *tcase_data,
273 : const void *test_data),
274 : const void *data)
275 : {
276 12532 : struct torture_test *test = talloc(tcase, struct torture_test);
277 :
278 12532 : test->name = talloc_strdup(test, name);
279 12532 : test->description = NULL;
280 12532 : test->run = wrap_test_with_testcase_const;
281 12532 : test->fn = run;
282 12532 : test->dangerous = false;
283 12532 : test->data = data;
284 :
285 12532 : DLIST_ADD_END(tcase->tests, test);
286 :
287 12532 : return test;
288 : }
289 :
290 : /**
291 : * Add a new testcase
292 : */
293 2197556 : bool torture_suite_init_tcase(struct torture_suite *suite,
294 : struct torture_tcase *tcase,
295 : const char *name)
296 : {
297 2197556 : tcase->name = talloc_strdup(tcase, name);
298 2197556 : tcase->description = NULL;
299 2197556 : tcase->setup = NULL;
300 2197556 : tcase->teardown = NULL;
301 2197556 : tcase->fixture_persistent = true;
302 2197556 : tcase->tests = NULL;
303 :
304 2197556 : DLIST_ADD_END(suite->testcases, tcase);
305 2197556 : tcase->suite = suite;
306 :
307 2197556 : return true;
308 : }
309 :
310 :
311 2143000 : struct torture_tcase *torture_suite_add_tcase(struct torture_suite *suite,
312 : const char *name)
313 : {
314 2143000 : struct torture_tcase *tcase = talloc(suite, struct torture_tcase);
315 :
316 2143000 : if (!torture_suite_init_tcase(suite, tcase, name))
317 0 : return NULL;
318 :
319 2143000 : return tcase;
320 : }
321 :
322 33463 : char *torture_subunit_test_name(struct torture_context *ctx,
323 : struct torture_tcase *tcase,
324 : struct torture_test *test)
325 : {
326 33463 : if (!strcmp(tcase->name, test->name)) {
327 39174 : return talloc_asprintf(ctx, "%s%s",
328 20817 : ctx->active_prefix->subunit_prefix,
329 : test->name);
330 : } else {
331 21380 : return talloc_asprintf(ctx, "%s%s.%s",
332 12646 : ctx->active_prefix->subunit_prefix,
333 : tcase->name, test->name);
334 : }
335 : }
336 :
337 908 : void torture_subunit_prefix_reset(struct torture_context *ctx,
338 : const char *name)
339 : {
340 908 : struct torture_subunit_prefix *prefix = &ctx->_initial_prefix;
341 :
342 908 : ZERO_STRUCTP(prefix);
343 :
344 908 : if (name != NULL) {
345 : int ret;
346 :
347 0 : ret = snprintf(prefix->subunit_prefix,
348 : sizeof(prefix->subunit_prefix),
349 : "%s.", name);
350 0 : if (ret < 0) {
351 0 : abort();
352 : }
353 : }
354 :
355 908 : ctx->active_prefix = prefix;
356 908 : }
357 :
358 4706 : static void torture_subunit_prefix_push(struct torture_context *ctx,
359 : struct torture_subunit_prefix *prefix,
360 : const char *name)
361 : {
362 4706 : *prefix = (struct torture_subunit_prefix) {
363 4706 : .parent = ctx->active_prefix,
364 : };
365 :
366 5119 : if (ctx->active_prefix->parent != NULL ||
367 601 : ctx->active_prefix->subunit_prefix[0] != '\0') {
368 : /*
369 : * We need a new component for the prefix.
370 : */
371 : int ret;
372 :
373 4105 : ret = snprintf(prefix->subunit_prefix,
374 : sizeof(prefix->subunit_prefix),
375 : "%s%s.",
376 4105 : ctx->active_prefix->subunit_prefix,
377 : name);
378 4105 : if (ret < 0) {
379 0 : abort();
380 : }
381 : }
382 :
383 4706 : ctx->active_prefix = prefix;
384 4706 : }
385 :
386 4706 : static void torture_subunit_prefix_pop(struct torture_context *ctx)
387 : {
388 4706 : ctx->active_prefix = ctx->active_prefix->parent;
389 4706 : }
390 :
391 4706 : int torture_suite_children_count(const struct torture_suite *suite)
392 : {
393 4706 : int ret = 0;
394 : struct torture_tcase *tcase;
395 : struct torture_test *test;
396 : struct torture_suite *tsuite;
397 11719 : for (tcase = suite->testcases; tcase; tcase = tcase->next) {
398 17670 : for (test = tcase->tests; test; test = test->next) {
399 10657 : ret++;
400 : }
401 : }
402 8811 : for (tsuite = suite->children; tsuite; tsuite = tsuite->next) {
403 4105 : ret ++;
404 : }
405 4706 : return ret;
406 : }
407 :
408 : /**
409 : * Run a torture test suite.
410 : */
411 0 : bool torture_run_suite(struct torture_context *context,
412 : struct torture_suite *suite)
413 : {
414 0 : return torture_run_suite_restricted(context, suite, NULL);
415 : }
416 :
417 4706 : bool torture_run_suite_restricted(struct torture_context *context,
418 : struct torture_suite *suite, const char **restricted)
419 : {
420 : struct torture_subunit_prefix _prefix_stack;
421 4706 : bool ret = true;
422 : struct torture_tcase *tcase;
423 : struct torture_suite *tsuite;
424 :
425 4706 : torture_subunit_prefix_push(context, &_prefix_stack, suite->name);
426 :
427 4706 : if (context->results->ui_ops->suite_start)
428 4706 : context->results->ui_ops->suite_start(context, suite);
429 :
430 : /* FIXME: Adjust torture_suite_children_count if restricted != NULL */
431 4706 : context->results->ui_ops->progress(context,
432 : torture_suite_children_count(suite), TORTURE_PROGRESS_SET);
433 :
434 11719 : for (tcase = suite->testcases; tcase; tcase = tcase->next) {
435 7013 : ret &= torture_run_tcase_restricted(context, tcase, restricted);
436 : }
437 :
438 8811 : for (tsuite = suite->children; tsuite; tsuite = tsuite->next) {
439 4105 : context->results->ui_ops->progress(context, 0, TORTURE_PROGRESS_PUSH);
440 4105 : ret &= torture_run_suite_restricted(context, tsuite, restricted);
441 4105 : context->results->ui_ops->progress(context, 0, TORTURE_PROGRESS_POP);
442 : }
443 :
444 4706 : if (context->results->ui_ops->suite_finish)
445 0 : context->results->ui_ops->suite_finish(context, suite);
446 :
447 4706 : torture_subunit_prefix_pop(context);
448 :
449 4706 : return ret;
450 : }
451 :
452 11179 : void torture_ui_test_start(struct torture_context *context,
453 : struct torture_tcase *tcase,
454 : struct torture_test *test)
455 : {
456 11179 : if (context->results->ui_ops->test_start)
457 11179 : context->results->ui_ops->test_start(context, tcase, test);
458 11179 : }
459 :
460 11179 : void torture_ui_test_result(struct torture_context *context,
461 : enum torture_result result,
462 : const char *comment)
463 : {
464 11179 : if (context->results->ui_ops->test_result)
465 11179 : context->results->ui_ops->test_result(context, result, comment);
466 :
467 11179 : if (result == TORTURE_ERROR || result == TORTURE_FAIL)
468 970 : context->results->returncode = false;
469 11179 : }
470 :
471 11105 : static bool test_needs_running(const char *name, const char **restricted)
472 : {
473 : int i;
474 11105 : if (restricted == NULL)
475 11105 : return true;
476 0 : for (i = 0; restricted[i]; i++) {
477 0 : if (!strcmp(name, restricted[i]))
478 0 : return true;
479 : }
480 0 : return false;
481 : }
482 :
483 11105 : static bool internal_torture_run_test(struct torture_context *context,
484 : struct torture_tcase *tcase,
485 : struct torture_test *test,
486 : bool already_setup,
487 : const char **restricted)
488 : {
489 : bool success;
490 11105 : char *subunit_testname = torture_subunit_test_name(context, tcase, test);
491 :
492 11105 : if (!test_needs_running(subunit_testname, restricted))
493 0 : return true;
494 :
495 11105 : context->active_tcase = tcase;
496 11105 : context->active_test = test;
497 :
498 11105 : torture_ui_test_start(context, tcase, test);
499 :
500 11105 : context->last_reason = NULL;
501 11105 : context->last_result = TORTURE_OK;
502 :
503 11105 : if (!already_setup && tcase->setup &&
504 0 : !tcase->setup(context, &(tcase->data))) {
505 0 : if (context->last_reason == NULL)
506 0 : context->last_reason = talloc_strdup(context, "Setup failure");
507 0 : context->last_result = TORTURE_ERROR;
508 0 : success = false;
509 11225 : } else if (test->dangerous &&
510 206 : !torture_setting_bool(context, "dangerous", false)) {
511 206 : context->last_result = TORTURE_SKIP;
512 206 : context->last_reason = talloc_asprintf(context,
513 : "disabled %s - enable dangerous tests to use", test->name);
514 206 : success = true;
515 : } else {
516 10899 : success = test->run(context, tcase, test);
517 :
518 10899 : if (!success && context->last_result == TORTURE_OK) {
519 0 : if (context->last_reason == NULL)
520 0 : context->last_reason = talloc_strdup(context,
521 : "Unknown error/failure. Missing torture_fail() or torture_assert_*() call?");
522 0 : context->last_result = TORTURE_ERROR;
523 : }
524 : }
525 :
526 11105 : if (!already_setup && tcase->teardown && !tcase->teardown(context, tcase->data)) {
527 0 : if (context->last_reason == NULL)
528 0 : context->last_reason = talloc_strdup(context, "Setup failure");
529 0 : context->last_result = TORTURE_ERROR;
530 0 : success = false;
531 : }
532 :
533 11105 : torture_ui_test_result(context, context->last_result,
534 11105 : context->last_reason);
535 :
536 11105 : talloc_free(context->last_reason);
537 11105 : context->last_reason = NULL;
538 :
539 11105 : context->active_test = NULL;
540 11105 : context->active_tcase = NULL;
541 :
542 11105 : return success;
543 : }
544 :
545 0 : bool torture_run_tcase(struct torture_context *context,
546 : struct torture_tcase *tcase)
547 : {
548 0 : return torture_run_tcase_restricted(context, tcase, NULL);
549 : }
550 :
551 7496 : bool torture_run_tcase_restricted(struct torture_context *context,
552 : struct torture_tcase *tcase, const char **restricted)
553 : {
554 7496 : bool ret = true;
555 : struct torture_test *test;
556 7496 : bool setup_succeeded = true;
557 7496 : const char * setup_reason = "Setup failed";
558 :
559 7496 : context->active_tcase = tcase;
560 7496 : if (context->results->ui_ops->tcase_start)
561 0 : context->results->ui_ops->tcase_start(context, tcase);
562 :
563 7496 : if (tcase->fixture_persistent && tcase->setup) {
564 557 : setup_succeeded = tcase->setup(context, &tcase->data);
565 : }
566 :
567 7496 : if (!setup_succeeded) {
568 : /* Uh-oh. The setup failed, so we can't run any of the tests
569 : * in this testcase. The subunit format doesn't specify what
570 : * to do here, so we keep the failure reason, and manually
571 : * use it to fail every test.
572 : */
573 9 : if (context->last_reason != NULL) {
574 9 : setup_reason = talloc_asprintf(context,
575 : "Setup failed: %s", context->last_reason);
576 : }
577 : }
578 :
579 18675 : for (test = tcase->tests; test; test = test->next) {
580 11179 : if (setup_succeeded) {
581 11105 : ret &= internal_torture_run_test(context, tcase, test,
582 11105 : tcase->fixture_persistent, restricted);
583 : } else {
584 74 : context->active_tcase = tcase;
585 74 : context->active_test = test;
586 74 : torture_ui_test_start(context, tcase, test);
587 74 : torture_ui_test_result(context, TORTURE_FAIL, setup_reason);
588 : }
589 : }
590 :
591 7875 : if (setup_succeeded && tcase->fixture_persistent && tcase->teardown &&
592 548 : !tcase->teardown(context, tcase->data)) {
593 0 : ret = false;
594 : }
595 :
596 7496 : context->active_tcase = NULL;
597 7496 : context->active_test = NULL;
598 :
599 7496 : if (context->results->ui_ops->tcase_finish)
600 0 : context->results->ui_ops->tcase_finish(context, tcase);
601 :
602 7496 : return (!setup_succeeded) ? false : ret;
603 : }
604 :
605 0 : bool torture_run_test(struct torture_context *context,
606 : struct torture_tcase *tcase,
607 : struct torture_test *test)
608 : {
609 0 : return internal_torture_run_test(context, tcase, test, false, NULL);
610 : }
611 :
612 0 : bool torture_run_test_restricted(struct torture_context *context,
613 : struct torture_tcase *tcase,
614 : struct torture_test *test,
615 : const char **restricted)
616 : {
617 0 : return internal_torture_run_test(context, tcase, test, false, restricted);
618 : }
619 :
620 25 : int torture_setting_int(struct torture_context *test, const char *name,
621 : int default_value)
622 : {
623 25 : return lpcfg_parm_int(test->lp_ctx, NULL, "torture", name, default_value);
624 : }
625 :
626 0 : unsigned long torture_setting_ulong(struct torture_context *test,
627 : const char *name,
628 : unsigned long default_value)
629 : {
630 0 : return lpcfg_parm_ulong(test->lp_ctx, NULL, "torture", name,
631 : default_value);
632 : }
633 :
634 0 : double torture_setting_double(struct torture_context *test, const char *name,
635 : double default_value)
636 : {
637 0 : return lpcfg_parm_double(test->lp_ctx, NULL, "torture", name, default_value);
638 : }
639 :
640 54601 : bool torture_setting_bool(struct torture_context *test, const char *name,
641 : bool default_value)
642 : {
643 54601 : return lpcfg_parm_bool(test->lp_ctx, NULL, "torture", name, default_value);
644 : }
645 :
646 22574 : const char *torture_setting_string(struct torture_context *test,
647 : const char *name,
648 : const char *default_value)
649 : {
650 : const char *ret;
651 :
652 22574 : SMB_ASSERT(test != NULL);
653 22574 : SMB_ASSERT(test->lp_ctx != NULL);
654 :
655 22574 : ret = lpcfg_parm_string(test->lp_ctx, NULL, "torture", name);
656 :
657 22574 : if (ret == NULL)
658 8557 : return default_value;
659 :
660 14017 : return ret;
661 : }
662 :
663 5755 : static bool wrap_test_with_simple_tcase_const (
664 : struct torture_context *torture_ctx,
665 : struct torture_tcase *tcase,
666 : struct torture_test *test)
667 : {
668 : bool (*fn) (struct torture_context *, const void *tcase_data);
669 :
670 5755 : fn = test->fn;
671 :
672 5755 : return fn(torture_ctx, test->data);
673 : }
674 :
675 511852 : struct torture_tcase *torture_suite_add_simple_tcase_const(
676 : struct torture_suite *suite, const char *name,
677 : bool (*run) (struct torture_context *test, const void *),
678 : const void *data)
679 : {
680 : struct torture_tcase *tcase;
681 : struct torture_test *test;
682 :
683 511852 : tcase = torture_suite_add_tcase(suite, name);
684 :
685 511852 : test = talloc(tcase, struct torture_test);
686 :
687 511852 : test->name = talloc_strdup(test, name);
688 511852 : test->description = NULL;
689 511852 : test->run = wrap_test_with_simple_tcase_const;
690 511852 : test->fn = run;
691 511852 : test->data = data;
692 511852 : test->dangerous = false;
693 :
694 511852 : DLIST_ADD_END(tcase->tests, test);
695 511852 : test->tcase = tcase;
696 :
697 511852 : return tcase;
698 : }
699 :
700 425 : static bool wrap_simple_test(struct torture_context *torture_ctx,
701 : struct torture_tcase *tcase,
702 : struct torture_test *test)
703 : {
704 : bool (*fn) (struct torture_context *);
705 :
706 425 : fn = test->fn;
707 :
708 425 : return fn(torture_ctx);
709 : }
710 :
711 472420 : struct torture_tcase *torture_suite_add_simple_test(
712 : struct torture_suite *suite,
713 : const char *name,
714 : bool (*run) (struct torture_context *test))
715 : {
716 : struct torture_test *test;
717 : struct torture_tcase *tcase;
718 :
719 472420 : tcase = torture_suite_add_tcase(suite, name);
720 :
721 472420 : test = talloc(tcase, struct torture_test);
722 :
723 472420 : test->name = talloc_strdup(test, name);
724 472420 : test->description = NULL;
725 472420 : test->run = wrap_simple_test;
726 472420 : test->fn = run;
727 472420 : test->dangerous = false;
728 :
729 472420 : DLIST_ADD_END(tcase->tests, test);
730 :
731 472420 : return tcase;
732 : }
733 :
734 : /**
735 : * Add a child testsuite to a testsuite.
736 : */
737 635018 : bool torture_suite_add_suite(struct torture_suite *suite,
738 : struct torture_suite *child)
739 : {
740 635018 : if (child == NULL)
741 0 : return false;
742 :
743 635018 : DLIST_ADD_END(suite->children, child);
744 635018 : child->parent = suite;
745 :
746 : /* FIXME: Check for duplicates and return false if the
747 : * added suite already exists as a child */
748 :
749 635018 : return true;
750 : }
751 :
752 : /**
753 : * Find the child testsuite with the specified name.
754 : */
755 0 : struct torture_suite *torture_find_suite(struct torture_suite *parent,
756 : const char *name)
757 : {
758 : struct torture_suite *child;
759 :
760 0 : for (child = parent->children; child; child = child->next)
761 0 : if (!strcmp(child->name, name))
762 0 : return child;
763 :
764 0 : return NULL;
765 : }
766 :
767 0 : static bool wrap_test_with_simple_test_const(struct torture_context *torture_ctx,
768 : struct torture_tcase *tcase,
769 : struct torture_test *test)
770 : {
771 : bool (*fn) (struct torture_context *, const void *tcase_data);
772 :
773 0 : fn = test->fn;
774 :
775 0 : return fn(torture_ctx, tcase->data);
776 : }
777 :
778 19280 : struct torture_test *torture_tcase_add_simple_test_const(
779 : struct torture_tcase *tcase,
780 : const char *name,
781 : bool (*run) (struct torture_context *test,
782 : const void *tcase_data))
783 : {
784 : struct torture_test *test;
785 :
786 19280 : test = talloc(tcase, struct torture_test);
787 :
788 19280 : test->name = talloc_strdup(test, name);
789 19280 : test->description = NULL;
790 19280 : test->run = wrap_test_with_simple_test_const;
791 19280 : test->fn = run;
792 19280 : test->data = NULL;
793 19280 : test->dangerous = false;
794 :
795 19280 : DLIST_ADD_END(tcase->tests, test);
796 :
797 19280 : return test;
798 : }
799 :
800 31 : static bool wrap_test_with_simple_test(struct torture_context *torture_ctx,
801 : struct torture_tcase *tcase,
802 : struct torture_test *test)
803 : {
804 : bool (*fn) (struct torture_context *, void *tcase_data);
805 :
806 31 : fn = test->fn;
807 :
808 31 : return fn(torture_ctx, tcase->data);
809 : }
810 :
811 248712 : struct torture_test *torture_tcase_add_simple_test(struct torture_tcase *tcase,
812 : const char *name,
813 : bool (*run) (struct torture_context *test, void *tcase_data))
814 : {
815 : struct torture_test *test;
816 :
817 248712 : test = talloc(tcase, struct torture_test);
818 :
819 248712 : test->name = talloc_strdup(test, name);
820 248712 : test->description = NULL;
821 248712 : test->run = wrap_test_with_simple_test;
822 248712 : test->fn = run;
823 248712 : test->data = NULL;
824 248712 : test->dangerous = false;
825 :
826 248712 : DLIST_ADD_END(tcase->tests, test);
827 :
828 248712 : return test;
829 : }
830 :
831 916 : void torture_ui_report_time(struct torture_context *context)
832 : {
833 916 : if (context->results->ui_ops->report_time)
834 916 : context->results->ui_ops->report_time(context);
835 916 : }
|