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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "torture/ui.h"
24 #include "torture/torture.h"
25 #include "lib/util/dlinklist.h"
27 void torture_comment(struct torture_context
*context
, const char *comment
, ...)
32 if (!context
->ui_ops
->comment
)
35 va_start(ap
, comment
);
36 tmp
= talloc_vasprintf(context
, comment
, ap
);
38 context
->ui_ops
->comment(context
, tmp
);
43 void torture_result(struct torture_context
*context
,
44 enum torture_result result
, const char *fmt
, ...)
50 context
->last_result
= result
;
51 context
->last_reason
= talloc_vasprintf(context
, fmt
, ap
);
55 struct torture_suite
*torture_suite_create(TALLOC_CTX
*ctx
, const char *name
)
57 struct torture_suite
*suite
= talloc_zero(ctx
, struct torture_suite
);
59 suite
->name
= talloc_strdup(suite
, name
);
60 suite
->testcases
= NULL
;
61 suite
->children
= NULL
;
66 void torture_tcase_set_fixture(struct torture_tcase
*tcase
,
67 BOOL (*setup
) (struct torture_context
*, void **),
68 BOOL (*teardown
) (struct torture_context
*, void *))
71 tcase
->teardown
= teardown
;
74 static bool wrap_test_with_testcase(struct torture_context
*torture_ctx
,
75 struct torture_tcase
*tcase
,
76 struct torture_test
*test
)
78 bool (*fn
) (struct torture_context
*,
79 const void *tcase_data
,
80 const void *test_data
);
84 return fn(torture_ctx
, tcase
->data
, test
->data
);
87 struct torture_test
*torture_tcase_add_test(struct torture_tcase
*tcase
,
89 bool (*run
) (struct torture_context
*,
90 const void *tcase_data
,
91 const void *test_data
),
94 struct torture_test
*test
= talloc(tcase
, struct torture_test
);
96 test
->name
= talloc_strdup(test
, name
);
97 test
->description
= NULL
;
98 test
->run
= wrap_test_with_testcase
;
100 test
->dangerous
= False
;
103 DLIST_ADD_END(tcase
->tests
, test
, struct torture_test
*);
108 struct torture_tcase
*torture_suite_add_tcase(struct torture_suite
*suite
,
111 struct torture_tcase
*tcase
= talloc(suite
, struct torture_tcase
);
113 tcase
->name
= talloc_strdup(tcase
, name
);
114 tcase
->description
= NULL
;
116 tcase
->teardown
= NULL
;
117 tcase
->fixture_persistent
= True
;
120 DLIST_ADD_END(suite
->testcases
, tcase
, struct torture_tcase
*);
125 BOOL
torture_run_suite(struct torture_context
*context
,
126 struct torture_suite
*suite
)
129 struct torture_tcase
*tcase
;
130 struct torture_suite
*tsuite
;
134 if (context
->ui_ops
->suite_start
)
135 context
->ui_ops
->suite_start(context
, suite
);
137 old_testname
= context
->active_testname
;
138 if (old_testname
!= NULL
)
139 context
->active_testname
= talloc_asprintf(context
, "%s-%s",
140 old_testname
, suite
->name
);
142 context
->active_testname
= talloc_strdup(context
, suite
->name
);
144 for (tcase
= suite
->testcases
; tcase
; tcase
= tcase
->next
) {
145 ret
&= torture_run_tcase(context
, tcase
);
148 for (tsuite
= suite
->children
; tsuite
; tsuite
= tsuite
->next
) {
149 ret
&= torture_run_suite(context
, tsuite
);
152 talloc_free(context
->active_testname
);
153 context
->active_testname
= old_testname
;
155 if (context
->ui_ops
->suite_finish
)
156 context
->ui_ops
->suite_finish(context
, suite
);
163 void torture_ui_test_start(struct torture_context
*context
,
164 struct torture_tcase
*tcase
,
165 struct torture_test
*test
)
167 if (context
->ui_ops
->test_start
)
168 context
->ui_ops
->test_start(context
, tcase
, test
);
171 int str_list_match(const char *name
, char **list
)
177 for (i
= 0; list
[i
]; i
++) {
178 if (gen_fnmatch(list
[i
], name
) == 0)
184 void torture_ui_test_result(struct torture_context
*context
,
185 enum torture_result result
,
188 if (context
->ui_ops
->test_result
)
189 context
->ui_ops
->test_result(context
, result
, comment
);
191 if (result
== TORTURE_SKIP
) {
192 context
->results
.skipped
++;
193 } else if (result
== TORTURE_OK
) {
194 if (str_list_match(context
->active_testname
,
195 context
->expected_failures
)) {
196 context
->results
.unexpected_successes
= str_list_add(
197 context
->results
.unexpected_successes
,
198 talloc_reference(context
, context
->active_testname
));
200 context
->results
.success
++;
201 } else if (result
== TORTURE_ERROR
) {
202 context
->results
.unexpected_errors
= str_list_add(
203 context
->results
.unexpected_errors
,
204 talloc_reference(context
, context
->active_testname
));
205 context
->results
.errors
++;
206 context
->results
.returncode
= false;
207 } else if (result
== TORTURE_FAIL
) {
208 if (0 == str_list_match(context
->active_testname
,
209 context
->expected_failures
)) {
210 context
->results
.unexpected_failures
= str_list_add(
211 context
->results
.unexpected_failures
,
212 talloc_reference(context
, context
->active_testname
));
213 context
->results
.returncode
= false;
215 context
->results
.failed
++;
219 static BOOL
internal_torture_run_test(struct torture_context
*context
,
220 struct torture_tcase
*tcase
,
221 struct torture_test
*test
,
227 if (test
->dangerous
&& !torture_setting_bool(context
, "dangerous", False
)) {
228 torture_result(context
, TORTURE_SKIP
,
229 "disabled %s - enable dangerous tests to use", test
->name
);
233 if (!already_setup
&& tcase
->setup
&&
234 !tcase
->setup(context
, &(tcase
->data
)))
237 if (tcase
== NULL
|| strcmp(test
->name
, tcase
->name
) != 0) {
238 old_testname
= context
->active_testname
;
239 context
->active_testname
= talloc_asprintf(context
, "%s-%s",
240 old_testname
, test
->name
);
242 context
->active_tcase
= tcase
;
243 context
->active_test
= test
;
245 torture_ui_test_start(context
, tcase
, test
);
248 context
->last_reason
= NULL
;
249 context
->last_result
= TORTURE_OK
;
251 ret
= test
->run(context
, tcase
, test
);
252 if (!ret
&& context
->last_result
== TORTURE_OK
) {
253 if (context
->last_reason
== NULL
)
254 context
->last_reason
= talloc_strdup(context
, "Unknown error/failure");
255 context
->last_result
= TORTURE_ERROR
;
258 torture_ui_test_result(context
, context
->last_result
, context
->last_reason
);
260 talloc_free(context
->last_reason
);
262 if (tcase
== NULL
|| strcmp(test
->name
, tcase
->name
) != 0) {
263 talloc_free(context
->active_testname
);
264 context
->active_testname
= old_testname
;
266 context
->active_test
= NULL
;
267 context
->active_tcase
= NULL
;
269 if (!already_setup
&& tcase
->teardown
&& !tcase
->teardown(context
, tcase
->data
))
275 BOOL
torture_run_tcase(struct torture_context
*context
,
276 struct torture_tcase
*tcase
)
280 struct torture_test
*test
;
284 context
->active_tcase
= tcase
;
285 if (context
->ui_ops
->tcase_start
)
286 context
->ui_ops
->tcase_start(context
, tcase
);
288 if (tcase
->fixture_persistent
&& tcase
->setup
289 && !tcase
->setup(context
, &tcase
->data
)) {
294 old_testname
= context
->active_testname
;
295 context
->active_testname
= talloc_asprintf(context
, "%s-%s",
296 old_testname
, tcase
->name
);
297 for (test
= tcase
->tests
; test
; test
= test
->next
) {
298 ret
&= internal_torture_run_test(context
, tcase
, test
,
299 tcase
->fixture_persistent
);
301 talloc_free(context
->active_testname
);
302 context
->active_testname
= old_testname
;
304 if (tcase
->fixture_persistent
&& tcase
->teardown
&&
305 !tcase
->teardown(context
, tcase
->data
))
309 context
->active_tcase
= NULL
;
311 if (context
->ui_ops
->tcase_finish
)
312 context
->ui_ops
->tcase_finish(context
, tcase
);
319 BOOL
torture_run_test(struct torture_context
*context
,
320 struct torture_tcase
*tcase
,
321 struct torture_test
*test
)
323 return internal_torture_run_test(context
, tcase
, test
, False
);
326 int torture_setting_int(struct torture_context
*test
, const char *name
,
329 return lp_parm_int(-1, "torture", name
, default_value
);
332 bool torture_setting_bool(struct torture_context
*test
, const char *name
,
335 return lp_parm_bool(-1, "torture", name
, default_value
);
338 const char *torture_setting_string(struct torture_context
*test
, const char *name
,
339 const char *default_value
)
341 const char *ret
= lp_parm_string(-1, "torture", name
);
344 return default_value
;
349 static bool wrap_test_with_simple_tcase(struct torture_context
*torture_ctx
,
350 struct torture_tcase
*tcase
,
351 struct torture_test
*test
)
353 bool (*fn
) (struct torture_context
*, const void *tcase_data
);
357 return fn(torture_ctx
, test
->data
);
360 struct torture_tcase
*torture_suite_add_simple_tcase(
361 struct torture_suite
*suite
,
363 bool (*run
) (struct torture_context
*test
, const void *),
366 struct torture_tcase
*tcase
;
367 struct torture_test
*test
;
369 tcase
= torture_suite_add_tcase(suite
, name
);
371 test
= talloc(tcase
, struct torture_test
);
373 test
->name
= talloc_strdup(test
, name
);
374 test
->description
= NULL
;
375 test
->run
= wrap_test_with_simple_tcase
;
378 test
->dangerous
= False
;
380 DLIST_ADD_END(tcase
->tests
, test
, struct torture_test
*);
385 static bool wrap_simple_test(struct torture_context
*torture_ctx
,
386 struct torture_tcase
*tcase
,
387 struct torture_test
*test
)
389 bool (*fn
) (struct torture_context
*);
393 return fn(torture_ctx
);
396 struct torture_tcase
*torture_suite_add_simple_test(
397 struct torture_suite
*suite
,
399 bool (*run
) (struct torture_context
*test
))
401 struct torture_test
*test
;
402 struct torture_tcase
*tcase
;
404 tcase
= torture_suite_add_tcase(suite
, name
);
406 test
= talloc(tcase
, struct torture_test
);
408 test
->name
= talloc_strdup(test
, name
);
409 test
->description
= NULL
;
410 test
->run
= wrap_simple_test
;
412 test
->dangerous
= false;
414 DLIST_ADD_END(tcase
->tests
, test
, struct torture_test
*);
419 bool torture_suite_add_suite(struct torture_suite
*suite
,
420 struct torture_suite
*child
)
425 DLIST_ADD_END(suite
->children
, child
, struct torture_suite
*);
427 /* FIXME: Check for duplicates and return false if the
428 * added suite already exists as a child */
434 struct torture_suite
*torture_find_suite(struct torture_suite
*parent
,
437 struct torture_suite
*child
;
439 for (child
= parent
->children
; child
; child
= child
->next
)
440 if (!strcmp(child
->name
, name
))