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