r26238: Add a loadparm context parameter to torture_context, remove more uses of...
[garming/samba-autobuild/.git] / source4 / torture / ui.h
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture UI functions
4
5    Copyright (C) Jelmer Vernooij 2006
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 #ifndef __TORTURE_UI_H__
22 #define __TORTURE_UI_H__
23
24 struct torture_test;
25 struct torture_context;
26 struct torture_suite;
27 struct torture_tcase;
28
29 enum torture_result { 
30         TORTURE_OK=0, 
31         TORTURE_FAIL=1,
32         TORTURE_ERROR=2,
33         TORTURE_SKIP=3
34 };
35
36 /* 
37  * These callbacks should be implemented by any backend that wishes 
38  * to listen to reports from the torture tests.
39  */
40 struct torture_ui_ops
41 {
42         void (*init) (struct torture_context *);
43         void (*comment) (struct torture_context *, const char *);
44         void (*warning) (struct torture_context *, const char *);
45         void (*suite_start) (struct torture_context *, struct torture_suite *);
46         void (*suite_finish) (struct torture_context *, struct torture_suite *);
47         void (*tcase_start) (struct torture_context *, struct torture_tcase *); 
48         void (*tcase_finish) (struct torture_context *, struct torture_tcase *);
49         void (*test_start) (struct torture_context *, 
50                                                 struct torture_tcase *,
51                                                 struct torture_test *);
52         void (*test_result) (struct torture_context *, 
53                                                  enum torture_result, const char *reason);
54 };
55
56 void torture_ui_test_start(struct torture_context *context,
57                                                            struct torture_tcase *tcase,
58                                                            struct torture_test *test);
59
60 void torture_ui_test_result(struct torture_context *context,
61                                                                 enum torture_result result,
62                                                                 const char *comment);
63
64 /*
65  * Holds information about a specific run of the testsuite. 
66  * The data in this structure should be considered private to 
67  * the torture tests and should only be used directly by the torture 
68  * code and the ui backends.
69  *
70  * Torture tests should instead call the torture_*() macros and functions 
71  * specified below.
72  */
73
74 struct torture_context
75 {
76         const struct torture_ui_ops *ui_ops;
77         void *ui_data;
78
79         char *active_testname;
80         struct torture_test *active_test;
81         struct torture_tcase *active_tcase;
82
83         bool quiet; /* Whether tests should avoid writing output to stdout */
84
85         enum torture_result last_result;
86         char *last_reason;
87
88         bool returncode;
89
90         const char *outputdir;
91         int level;
92         struct event_context *ev;
93
94         struct loadparm_context *lp_ctx;
95 };
96
97 /* 
98  * Describes a particular torture test
99  */
100 struct torture_test {
101         const char *name;
102         const char *description;
103         bool dangerous;
104         /* Function to call to run this test */
105         bool (*run) (struct torture_context *torture_ctx, 
106                                  struct torture_tcase *tcase,
107                                  struct torture_test *test);
108
109         struct torture_test *prev, *next;
110
111         /* Pointer to the actual test function. This is run by the 
112          * run() function above. */
113         void *fn;
114         const void *data;
115 };
116
117 /* 
118  * Describes a particular test case.
119  */
120 struct torture_tcase {
121     const char *name;
122         const char *description;
123         bool (*setup) (struct torture_context *tcase, void **data);
124         bool (*teardown) (struct torture_context *tcase, void *data); 
125         bool fixture_persistent;
126         void *data;
127         struct torture_test *tests;
128         struct torture_tcase *prev, *next;
129 };
130
131 struct torture_suite
132 {
133         const char *name;
134         const char *description;
135         struct torture_tcase *testcases;
136         struct torture_suite *children;
137
138         /* Pointers to siblings of this torture suite */
139         struct torture_suite *prev, *next;
140 };
141
142 /** Create a new torture suite */
143 struct torture_suite *torture_suite_create(TALLOC_CTX *mem_ctx, 
144                                                                                    const char *name);
145
146 /** Change the setup and teardown functions for a testcase */
147 void torture_tcase_set_fixture(struct torture_tcase *tcase, 
148                 bool (*setup) (struct torture_context *, void **),
149                 bool (*teardown) (struct torture_context *, void *));
150
151 /* Add another test to run for a particular testcase */
152 struct torture_test *torture_tcase_add_test(struct torture_tcase *tcase, 
153                 const char *name, 
154                 bool (*run) (struct torture_context *test, const void *tcase_data,
155                                          const void *test_data),
156                 const void *test_data);
157
158 /* Add a testcase to a testsuite */
159 struct torture_tcase *torture_suite_add_tcase(struct torture_suite *suite, 
160                                                          const char *name);
161
162 /* Convenience wrapper that adds a testcase against only one 
163  * test will be run */
164 struct torture_tcase *torture_suite_add_simple_tcase(
165                 struct torture_suite *suite, 
166                 const char *name,
167                 bool (*run) (struct torture_context *test, const void *test_data),
168                 const void *data);
169
170 /* Convenience function that adds a test which only 
171  * gets the test case data */
172 struct torture_test *torture_tcase_add_simple_test(
173                 struct torture_tcase *tcase,
174                 const char *name,
175                 bool (*run) (struct torture_context *test, const void *tcase_data));
176
177 /* Convenience wrapper that adds a test that doesn't need any 
178  * testcase data */
179 struct torture_tcase *torture_suite_add_simple_test(
180                 struct torture_suite *suite, 
181                 const char *name,
182                 bool (*run) (struct torture_context *test));
183
184 /* Add a child testsuite to an existing testsuite */
185 bool torture_suite_add_suite(struct torture_suite *suite,
186                                                          struct torture_suite *child);
187
188 /* Run the specified testsuite recursively */
189 bool torture_run_suite(struct torture_context *context, 
190                                            struct torture_suite *suite);
191
192 /* Run the specified testcase */
193 bool torture_run_tcase(struct torture_context *context, 
194                                            struct torture_tcase *tcase);
195
196 /* Run the specified test */
197 bool torture_run_test(struct torture_context *context, 
198                                           struct torture_tcase *tcase,
199                                           struct torture_test *test);
200
201 void torture_comment(struct torture_context *test, const char *comment, ...) PRINTF_ATTRIBUTE(2,3);
202 void torture_warning(struct torture_context *test, const char *comment, ...) PRINTF_ATTRIBUTE(2,3);
203 void torture_result(struct torture_context *test, 
204                         enum torture_result, const char *reason, ...) PRINTF_ATTRIBUTE(3,4);
205
206 #define torture_assert(torture_ctx,expr,cmt) \
207         if (!(expr)) { \
208                 torture_result(torture_ctx, TORTURE_FAIL, __location__": Expression `%s' failed: %s", __STRING(expr), cmt); \
209                 return false; \
210         }
211
212 #define torture_assert_werr_equal(torture_ctx, got, expected, cmt) \
213         do { WERROR __got = got, __expected = expected; \
214         if (!W_ERROR_EQUAL(__got, __expected)) { \
215                 torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", win_errstr(__got), win_errstr(__expected), cmt); \
216                 return false; \
217         } \
218         } while (0)
219
220 #define torture_assert_ntstatus_equal(torture_ctx,got,expected,cmt) \
221         do { NTSTATUS __got = got, __expected = expected; \
222         if (!NT_STATUS_EQUAL(__got, __expected)) { \
223                 torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", nt_errstr(__got), nt_errstr(__expected), cmt); \
224                 return false; \
225         }\
226         } while(0)
227
228 #define torture_assert_ndr_err_equal(torture_ctx,got,expected,cmt) \
229         do { enum ndr_err_code __got = got, __expected = expected; \
230         if (__got != __expected) { \
231                 torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %d, expected %d (%s): %s", __got, __expected, __STRING(expected), cmt); \
232                 return false; \
233         }\
234         } while(0)
235
236 #define torture_assert_casestr_equal(torture_ctx,got,expected,cmt) \
237         do { const char *__got = (got), *__expected = (expected); \
238         if (!strequal(__got, __expected)) { \
239                 torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", __got, __expected, cmt); \
240                 return false; \
241         } \
242         } while(0)
243
244 #define torture_assert_str_equal(torture_ctx,got,expected,cmt)\
245         do { const char *__got = (got), *__expected = (expected); \
246         if (strcmp_safe(__got, __expected) != 0) { \
247                 torture_result(torture_ctx, TORTURE_FAIL, \
248                                            __location__": "#got" was %s, expected %s: %s", \
249                                            __got, __expected, cmt); \
250                 return false; \
251         } \
252         } while(0)
253
254 #define torture_assert_file_contains_text(torture_ctx,filename,expected,cmt)\
255         do { \
256         char *__got; \
257         const char *__expected = (expected); \
258         size_t __size; \
259         __got = file_load(filename, &__size, torture_ctx); \
260         if (__got == NULL) { \
261                 torture_result(torture_ctx, TORTURE_FAIL, \
262                                __location__": unable to open %s: %s\n", \
263                                filename, cmt); \
264                 return false; \
265         } \
266         \
267         if (strcmp_safe(__got, __expected) != 0) { \
268                 torture_result(torture_ctx, TORTURE_FAIL, \
269                         __location__": %s contained:\n%sExpected: %s%s\n", \
270                         filename, __got, __expected, cmt); \
271                 talloc_free(__got); \
272                 return false; \
273         } \
274         talloc_free(__got); \
275         } while(0)
276
277 #define torture_assert_file_contains(torture_ctx,filename,expected,cmt)\
278         do { const char *__got, *__expected = (expected); \
279         size_t __size; \
280         __got = file_load(filename, *size, torture_ctx); \
281         if (strcmp_safe(__got, __expected) != 0) { \
282                 torture_result(torture_ctx, TORTURE_FAIL, \
283                                            __location__": %s contained:\n%sExpected: %s%s\n", \
284                                            __got, __expected, cmt); \
285                 talloc_free(__got); \
286                 return false; \
287         } \
288         talloc_free(__got); \
289         } while(0)
290
291 #define torture_assert_int_equal(torture_ctx,got,expected,cmt)\
292         do { int __got = (got), __expected = (expected); \
293         if (__got != __expected) { \
294                 torture_result(torture_ctx, TORTURE_FAIL, \
295                         __location__": "#got" was %d, expected %d: %s", \
296                         __got, __expected, cmt); \
297                 return false; \
298         } \
299         } while(0)
300
301 #define torture_assert_u64_equal(torture_ctx,got,expected,cmt)\
302         do { uint64_t __got = (got), __expected = (expected); \
303         if (__got != __expected) { \
304                 torture_result(torture_ctx, TORTURE_FAIL, \
305                         __location__": "#got" was %llu, expected %llu: %s", \
306                         (unsigned long long)__got, (unsigned long long)__expected, cmt); \
307                 return false; \
308         } \
309         } while(0)
310
311 #define torture_assert_errno_equal(torture_ctx,expected,cmt)\
312         do { int __expected = (expected); \
313         if (errno != __expected) { \
314                 torture_result(torture_ctx, TORTURE_FAIL, \
315                         __location__": errno was %d (%s), expected %d: %s: %s", \
316                                            errno, strerror(errno), __expected, \
317                                            strerror(__expected), cmt); \
318                 return false; \
319         } \
320         } while(0)
321
322
323
324 #define torture_skip(torture_ctx,cmt) do {\
325                 torture_result(torture_ctx, TORTURE_SKIP, __location__": %s", cmt);\
326                 return true; \
327         } while(0)
328 #define torture_fail(torture_ctx,cmt) do {\
329                 torture_result(torture_ctx, TORTURE_FAIL, __location__": %s", cmt);\
330                 return false; \
331         } while (0)
332 #define torture_fail_goto(torture_ctx,label,cmt) do {\
333                 torture_result(torture_ctx, TORTURE_FAIL, __location__": %s", cmt);\
334                 goto label; \
335         } while (0)
336
337 #define torture_out stderr
338
339 /* Convenience macros */
340 #define torture_assert_ntstatus_ok(torture_ctx,expr,cmt) \
341                 torture_assert_ntstatus_equal(torture_ctx,expr,NT_STATUS_OK,cmt)
342
343 #define torture_assert_werr_ok(torture_ctx,expr,cmt) \
344                 torture_assert_werr_equal(torture_ctx,expr,WERR_OK,cmt)
345
346 #define torture_assert_ndr_success(torture_ctx,expr,cmt) \
347                 torture_assert_ndr_err_equal(torture_ctx,expr,NDR_ERR_SUCCESS,cmt)
348
349 /* Getting settings */
350 const char *torture_setting_string(struct torture_context *test, \
351                                                                    const char *name, 
352                                                                    const char *default_value);
353
354 int torture_setting_int(struct torture_context *test, 
355                                                 const char *name, 
356                                                 int default_value);
357
358 double torture_setting_double(struct torture_context *test, 
359                                                 const char *name, 
360                                                 double default_value);
361
362 bool torture_setting_bool(struct torture_context *test, 
363                                                   const char *name, 
364                                                   bool default_value);
365
366 struct torture_suite *torture_find_suite(struct torture_suite *parent, 
367                                                                                  const char *name);
368
369
370 #endif /* __TORTURE_UI_H__ */