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 2 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, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 #ifndef __TORTURE_UI_H__ 23 #define __TORTURE_UI_H__ 24 25 struct torture_test; 26 struct torture_context; 27 struct torture_suite; 28 struct torture_tcase; 29 30 enum torture_result { 31 TORTURE_OK=0, 32 TORTURE_FAIL=1, 33 TORTURE_ERROR=2, 34 TORTURE_SKIP=3 35 }; 36 37 /* 38 * These callbacks should be implemented by any backend that wishes 39 * to listen to reports from the torture tests. 40 */ 41 struct torture_ui_ops 42 { 43 void (*comment) (struct torture_context *, const char *); 44 void (*suite_start) (struct torture_context *, struct torture_suite *); 45 void (*suite_finish) (struct torture_context *, struct torture_suite *); 46 void (*tcase_start) (struct torture_context *, struct torture_tcase *); 47 void (*tcase_finish) (struct torture_context *, struct torture_tcase *); 48 void (*test_start) (struct torture_context *, 49 struct torture_tcase *, 50 struct torture_test *); 51 void (*test_result) (struct torture_context *, 52 enum torture_result, const char *reason); 53 }; 54 55 void torture_ui_test_start(struct torture_context *context, 56 struct torture_tcase *tcase, 57 struct torture_test *test); 58 59 void torture_ui_test_result(struct torture_context *context, 60 enum torture_result result, 61 const char *comment); 62 63 /* 64 * Holds information about a specific run of the testsuite. 65 * The data in this structure should be considered private to 66 * the torture tests and should only be used directly by the torture 67 * code and the ui backends. 68 * 69 * Torture tests should instead call the torture_*() macros and functions 70 * specified below. 71 */ 72 73 struct torture_context 74 { 75 const struct torture_ui_ops *ui_ops; 76 void *ui_data; 77 78 char *active_testname; 79 struct torture_test *active_test; 80 struct torture_tcase *active_tcase; 81 82 char **expected_failures; 83 84 struct torture_results { 85 int skipped; 86 int todo; 87 int success; 88 int failed; 89 int errors; 90 91 const char **unexpected_failures; 92 const char **unexpected_successes; 93 const char **unexpected_errors; 94 95 bool returncode; 96 } results; 97 98 bool quiet; /* Whether tests should avoid writing output to stdout */ 99 100 enum torture_result last_result; 101 char *last_reason; 102 103 char *outputdir; 104 int level; 105 }; 106 107 /* 108 * Describes a particular torture test 109 */ 110 struct torture_test { 111 const char *name; 112 const char *description; 113 bool dangerous; 114 /* Function to call to run this test */ 115 bool (*run) (struct torture_context *torture_ctx, 116 struct torture_tcase *tcase, 117 struct torture_test *test); 118 119 struct torture_test *prev, *next; 120 121 /* Pointer to the actual test function. This is run by the 122 * run() function above. */ 123 void *fn; 124 const void *data; 125 }; 126 127 /* 128 * Describes a particular test case. 129 */ 130 struct torture_tcase { 131 const char *name; 132 const char *description; 133 bool (*setup) (struct torture_context *tcase, void **data); 134 bool (*teardown) (struct torture_context *tcase, void *data); 135 bool fixture_persistent; 136 void *data; 137 struct torture_test *tests; 138 struct torture_tcase *prev, *next; 139 }; 140 141 struct torture_suite 142 { 143 const char *name; 144 const char *path; /* Used by subunit tests only */ 145 const char *description; 146 struct torture_tcase *testcases; 147 struct torture_suite *children; 148 149 /* Pointers to siblings of this torture suite */ 150 struct torture_suite *prev, *next; 151 }; 152 153 /** Create a new torture suite */ 154 struct torture_suite *torture_suite_create(TALLOC_CTX *mem_ctx, 155 const char *name); 156 157 /** Change the setup and teardown functions for a testcase */ 158 void torture_tcase_set_fixture(struct torture_tcase *tcase, 159 bool (*setup) (struct torture_context *, void **), 160 bool (*teardown) (struct torture_context *, void *)); 161 162 /* Add another test to run for a particular testcase */ 163 struct torture_test *torture_tcase_add_test(struct torture_tcase *tcase, 164 const char *name, 165 bool (*run) (struct torture_context *test, const void *tcase_data, 166 const void *test_data), 167 const void *test_data); 168 169 /* Add a testcase to a testsuite */ 170 struct torture_tcase *torture_suite_add_tcase(struct torture_suite *suite, 171 const char *name); 172 173 /* Convenience wrapper that adds a testcase against only one 174 * test will be run */ 175 struct torture_tcase *torture_suite_add_simple_tcase( 176 struct torture_suite *suite, 177 const char *name, 178 bool (*run) (struct torture_context *test, const void *test_data), 179 const void *data); 180 181 /* Convenience wrapper that adds a test that doesn't need any 182 * testcase data */ 183 struct torture_tcase *torture_suite_add_simple_test( 184 struct torture_suite *suite, 185 const char *name, 186 bool (*run) (struct torture_context *test)); 187 188 /* Add a child testsuite to an existing testsuite */ 189 bool torture_suite_add_suite(struct torture_suite *suite, 190 struct torture_suite *child); 191 192 /* Run the specified testsuite recursively */ 193 bool torture_run_suite(struct torture_context *context, 194 struct torture_suite *suite); 195 196 /* Run the specified testcase */ 197 bool torture_run_tcase(struct torture_context *context, 198 struct torture_tcase *tcase); 199 200 /* Run the specified test */ 201 bool torture_run_test(struct torture_context *context, 202 struct torture_tcase *tcase, 203 struct torture_test *test); 204 205 void torture_comment(struct torture_context *test, const char *comment, ...) PRINTF_ATTRIBUTE(2,3); 206 void torture_result(struct torture_context *test, 207 enum torture_result, const char *reason, ...) PRINTF_ATTRIBUTE(3,4); 208 209 #define torture_assert(torture_ctx,expr,cmt) \ 210 if (!(expr)) { \ 211 torture_result(torture_ctx, TORTURE_FAIL, __location__": Expression `%s' failed: %s", __STRING(expr), cmt); \ 212 return false; \ 213 } 214 215 #define torture_assert_werr_equal(torture_ctx, got, expected, cmt) \ 216 do { WERROR __got = got, __expected = expected; \ 217 if (!W_ERROR_EQUAL(__got, __expected)) { \ 218 torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", win_errstr(__got), win_errstr(__expected), cmt); \ 219 return false; \ 220 } \ 221 } while (0) 222 223 #define torture_assert_ntstatus_equal(torture_ctx,got,expected,cmt) \ 224 do { NTSTATUS __got = got, __expected = expected; \ 225 if (!NT_STATUS_EQUAL(__got, __expected)) { \ 226 torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", nt_errstr(__got), nt_errstr(__expected), cmt); \ 227 return false; \ 228 }\ 229 } while(0) 230 231 232 #define torture_assert_casestr_equal(torture_ctx,got,expected,cmt) \ 233 do { const char *__got = (got), *__expected = (expected); \ 234 if (!strequal(__got, __expected)) { \ 235 torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", __got, __expected, cmt); \ 236 return false; \ 237 } \ 238 } while(0) 239 240 #define torture_assert_str_equal(torture_ctx,got,expected,cmt)\ 241 do { const char *__got = (got), *__expected = (expected); \ 242 if (strcmp_safe(__got, __expected) != 0) { \ 243 torture_result(torture_ctx, TORTURE_FAIL, \ 244 __location__": "#got" was %s, expected %s: %s", \ 245 __got, __expected, cmt); \ 246 return false; \ 247 } \ 248 } while(0) 249 250 #define torture_assert_int_equal(torture_ctx,got,expected,cmt)\ 251 do { int __got = (got), __expected = (expected); \ 252 if (__got != __expected) { \ 253 torture_result(torture_ctx, TORTURE_FAIL, \ 254 __location__": "#got" was %d, expected %d: %s", \ 255 __got, __expected, cmt); \ 256 return false; \ 257 } \ 258 } while(0) 259 260 #define torture_assert_errno_equal(torture_ctx,expected,cmt)\ 261 do { int __expected = (expected); \ 262 if (errno != __expected) { \ 263 torture_result(torture_ctx, TORTURE_FAIL, \ 264 __location__": errno was %d (%s), expected %d: %s: %s", \ 265 errno, strerror(errno), __expected, \ 266 strerror(__expected), cmt); \ 267 return false; \ 268 } \ 269 } while(0) 270 271 272 273 #define torture_skip(torture_ctx,cmt) do {\ 274 torture_result(torture_ctx, TORTURE_SKIP, __location__": %s", cmt);\ 275 return true; \ 276 } while(0) 277 #define torture_fail(torture_ctx,cmt) do {\ 278 torture_result(torture_ctx, TORTURE_FAIL, __location__": %s", cmt);\ 279 return false; \ 280 } while (0) 281 282 #define torture_out stderr 283 284 /* Convenience macros */ 285 #define torture_assert_ntstatus_ok(torture_ctx,expr,cmt) \ 286 torture_assert_ntstatus_equal(torture_ctx,expr,NT_STATUS_OK,cmt) 287 288 #define torture_assert_werr_ok(torture_ctx,expr,cmt) \ 289 torture_assert_werr_equal(torture_ctx,expr,WERR_OK,cmt) 290 291 /* Getting settings */ 292 const char *torture_setting_string(struct torture_context *test, \ 293 const char *name, 294 const char *default_value); 295 296 int torture_setting_int(struct torture_context *test, 297 const char *name, 298 int default_value); 299 300 bool torture_setting_bool(struct torture_context *test, 301 const char *name, 302 bool default_value); 303 304 struct torture_suite *torture_find_suite(struct torture_suite *parent, 305 const char *name); 306 307 308 #endif /* __TORTURE_UI_H__ */ 309