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
);
145 ret
&= torture_subunit_run_suite(context
, suite
);
147 for (tcase
= suite
->testcases
; tcase
; tcase
= tcase
->next
) {
148 ret
&= torture_run_tcase(context
, tcase
);
151 for (tsuite
= suite
->children
; tsuite
; tsuite
= tsuite
->next
) {
152 ret
&= torture_run_suite(context
, tsuite
);
155 talloc_free(context
->active_testname
);
156 context
->active_testname
= old_testname
;
158 if (context
->ui_ops
->suite_finish
)
159 context
->ui_ops
->suite_finish(context
, suite
);
166 void torture_ui_test_start(struct torture_context
*context
,
167 struct torture_tcase
*tcase
,
168 struct torture_test
*test
)
170 if (context
->ui_ops
->test_start
)
171 context
->ui_ops
->test_start(context
, tcase
, test
);
174 int str_list_match(const char *name
, char **list
)
180 for (i
= 0; list
[i
]; i
++) {
181 if (gen_fnmatch(list
[i
], name
) == 0)
187 void torture_ui_test_result(struct torture_context
*context
,
188 enum torture_result result
,
191 if (context
->ui_ops
->test_result
)
192 context
->ui_ops
->test_result(context
, result
, comment
);
194 if (result
== TORTURE_SKIP
) {
195 context
->results
.skipped
++;
196 } else if (result
== TORTURE_OK
) {
197 if (str_list_match(context
->active_testname
,
198 context
->expected_failures
)) {
199 context
->results
.unexpected_successes
= str_list_add(
200 context
->results
.unexpected_successes
,
201 talloc_reference(context
, context
->active_testname
));
203 context
->results
.success
++;
204 } else if (result
== TORTURE_ERROR
) {
205 context
->results
.unexpected_errors
= str_list_add(
206 context
->results
.unexpected_errors
,
207 talloc_reference(context
, context
->active_testname
));
208 context
->results
.errors
++;
209 context
->results
.returncode
= false;
210 } else if (result
== TORTURE_FAIL
) {
211 if (0 == str_list_match(context
->active_testname
,
212 context
->expected_failures
)) {
213 context
->results
.unexpected_failures
= str_list_add(
214 context
->results
.unexpected_failures
,
215 talloc_reference(context
, context
->active_testname
));
216 context
->results
.returncode
= false;
218 context
->results
.failed
++;
222 static BOOL
internal_torture_run_test(struct torture_context
*context
,
223 struct torture_tcase
*tcase
,
224 struct torture_test
*test
,
230 if (test
->dangerous
&& !torture_setting_bool(context
, "dangerous", False
)) {
231 torture_result(context
, TORTURE_SKIP
,
232 "disabled %s - enable dangerous tests to use", test
->name
);
236 if (!already_setup
&& tcase
->setup
&&
237 !tcase
->setup(context
, &(tcase
->data
)))
240 if (tcase
== NULL
|| strcmp(test
->name
, tcase
->name
) != 0) {
241 old_testname
= context
->active_testname
;
242 context
->active_testname
= talloc_asprintf(context
, "%s-%s",
243 old_testname
, test
->name
);
245 context
->active_tcase
= tcase
;
246 context
->active_test
= test
;
248 torture_ui_test_start(context
, tcase
, test
);
251 context
->last_reason
= NULL
;
252 context
->last_result
= TORTURE_OK
;
254 ret
= test
->run(context
, tcase
, test
);
255 if (!ret
&& context
->last_result
== TORTURE_OK
) {
256 if (context
->last_reason
== NULL
)
257 context
->last_reason
= talloc_strdup(context
, "Unknown error/failure");
258 context
->last_result
= TORTURE_ERROR
;
261 torture_ui_test_result(context
, context
->last_result
, context
->last_reason
);
263 talloc_free(context
->last_reason
);
265 if (tcase
== NULL
|| strcmp(test
->name
, tcase
->name
) != 0) {
266 talloc_free(context
->active_testname
);
267 context
->active_testname
= old_testname
;
269 context
->active_test
= NULL
;
270 context
->active_tcase
= NULL
;
272 if (!already_setup
&& tcase
->teardown
&& !tcase
->teardown(context
, tcase
->data
))
278 BOOL
torture_run_tcase(struct torture_context
*context
,
279 struct torture_tcase
*tcase
)
283 struct torture_test
*test
;
287 context
->active_tcase
= tcase
;
288 if (context
->ui_ops
->tcase_start
)
289 context
->ui_ops
->tcase_start(context
, tcase
);
291 if (tcase
->fixture_persistent
&& tcase
->setup
292 && !tcase
->setup(context
, &tcase
->data
)) {
297 old_testname
= context
->active_testname
;
298 context
->active_testname
= talloc_asprintf(context
, "%s-%s",
299 old_testname
, tcase
->name
);
300 for (test
= tcase
->tests
; test
; test
= test
->next
) {
301 ret
&= internal_torture_run_test(context
, tcase
, test
,
302 tcase
->fixture_persistent
);
304 talloc_free(context
->active_testname
);
305 context
->active_testname
= old_testname
;
307 if (tcase
->fixture_persistent
&& tcase
->teardown
&&
308 !tcase
->teardown(context
, tcase
->data
))
312 context
->active_tcase
= NULL
;
314 if (context
->ui_ops
->tcase_finish
)
315 context
->ui_ops
->tcase_finish(context
, tcase
);
322 BOOL
torture_run_test(struct torture_context
*context
,
323 struct torture_tcase
*tcase
,
324 struct torture_test
*test
)
326 return internal_torture_run_test(context
, tcase
, test
, False
);
329 int torture_setting_int(struct torture_context
*test
, const char *name
,
332 return lp_parm_int(-1, "torture", name
, default_value
);
335 bool torture_setting_bool(struct torture_context
*test
, const char *name
,
338 return lp_parm_bool(-1, "torture", name
, default_value
);
341 const char *torture_setting_string(struct torture_context
*test
, const char *name
,
342 const char *default_value
)
344 const char *ret
= lp_parm_string(-1, "torture", name
);
347 return default_value
;
352 static bool wrap_test_with_simple_tcase(struct torture_context
*torture_ctx
,
353 struct torture_tcase
*tcase
,
354 struct torture_test
*test
)
356 bool (*fn
) (struct torture_context
*, const void *tcase_data
);
360 return fn(torture_ctx
, test
->data
);
363 struct torture_tcase
*torture_suite_add_simple_tcase(
364 struct torture_suite
*suite
,
366 bool (*run
) (struct torture_context
*test
, const void *),
369 struct torture_tcase
*tcase
;
370 struct torture_test
*test
;
372 tcase
= torture_suite_add_tcase(suite
, name
);
374 test
= talloc(tcase
, struct torture_test
);
376 test
->name
= talloc_strdup(test
, name
);
377 test
->description
= NULL
;
378 test
->run
= wrap_test_with_simple_tcase
;
381 test
->dangerous
= False
;
383 DLIST_ADD_END(tcase
->tests
, test
, struct torture_test
*);
388 static bool wrap_simple_test(struct torture_context
*torture_ctx
,
389 struct torture_tcase
*tcase
,
390 struct torture_test
*test
)
392 bool (*fn
) (struct torture_context
*);
396 return fn(torture_ctx
);
399 struct torture_tcase
*torture_suite_add_simple_test(
400 struct torture_suite
*suite
,
402 bool (*run
) (struct torture_context
*test
))
404 struct torture_test
*test
;
405 struct torture_tcase
*tcase
;
407 tcase
= torture_suite_add_tcase(suite
, name
);
409 test
= talloc(tcase
, struct torture_test
);
411 test
->name
= talloc_strdup(test
, name
);
412 test
->description
= NULL
;
413 test
->run
= wrap_simple_test
;
415 test
->dangerous
= false;
417 DLIST_ADD_END(tcase
->tests
, test
, struct torture_test
*);
422 bool torture_suite_add_suite(struct torture_suite
*suite
,
423 struct torture_suite
*child
)
428 DLIST_ADD_END(suite
->children
, child
, struct torture_suite
*);
430 /* FIXME: Check for duplicates and return false if the
431 * added suite already exists as a child */
437 struct torture_suite
*torture_find_suite(struct torture_suite
*parent
,
440 struct torture_suite
*child
;
442 for (child
= parent
->children
; child
; child
= child
->next
)
443 if (!strcmp(child
->name
, name
))