00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef OM_HGUARD_TESTSUITE_H
00023 #define OM_HGUARD_TESTSUITE_H
00024
00025 #include "noreturn.h"
00026
00027 #include "output.h"
00028
00029 #include "stringutils.h"
00030
00031 #include <iomanip>
00032 #include <map>
00033 #include <sstream>
00034 #include <string>
00035 #include <vector>
00036
00037 #include <float.h>
00038
00041 class TestFail { };
00042
00048 class TestSkip { };
00049
00052
00053 #define FAIL_TEST(a) do { TestFail testfail; \
00054 if (verbose) { tout << a << '\n'; } \
00055 throw testfail; } while (0)
00056
00059
00060 #define SKIP_TEST(a) do { TestSkip testskip; \
00061 if (verbose) { tout << a << '\n'; } \
00062 throw testskip; } while (0)
00063
00065 typedef bool (*test_func)();
00066
00068 struct test_desc {
00070 const char *name;
00071
00073 test_func run;
00074 };
00075
00077
00078
00079
00080
00081 extern bool verbose;
00082
00084
00085
00086 extern const char * expected_exception;
00087
00091 extern std::ostringstream tout;
00092
00094 class test_driver {
00095 public:
00099 struct result {
00101 unsigned int succeeded;
00102
00104 unsigned int failed;
00105
00107 unsigned int skipped;
00108
00109 result() : succeeded(0), failed(0), skipped(0) { }
00110
00111 result & operator+=(const result & o) {
00112 succeeded += o.succeeded;
00113 failed += o.failed;
00114 skipped += o.skipped;
00115 return *this;
00116 }
00117
00118 void reset() {
00119 succeeded = 0;
00120 failed = 0;
00121 skipped = 0;
00122 }
00123 };
00124
00133 static void add_command_line_option(const std::string &l, char s,
00134 std::string * arg);
00135
00141 static void parse_command_line(int argc, char **argv);
00142
00143 XAPIAN_NORETURN(static void usage());
00144
00145 static int run(const test_desc *tests);
00146
00151 test_driver(const test_desc *tests_);
00152
00155 result run_tests();
00156
00159 result run_tests(std::vector<std::string>::const_iterator b,
00160 std::vector<std::string>::const_iterator e);
00161
00165 static std::string get_srcdir();
00166
00167
00168 static result subtotal;
00169
00170
00171 static result total;
00172
00174 static void report(const test_driver::result &r, const std::string &desc);
00175
00176 private:
00178 test_driver(const test_driver &);
00179 test_driver & operator = (const test_driver &);
00180
00181 typedef enum { PASS = 1, FAIL = 0, SKIP = -1 } test_result;
00182
00183 static std::map<int, std::string *> short_opts;
00184
00185 static std::string opt_help;
00186
00187 static std::vector<std::string> test_names;
00188
00195 test_result runtest(const test_desc *test);
00196
00204 result do_run_tests(std::vector<std::string>::const_iterator b,
00205 std::vector<std::string>::const_iterator e);
00206
00207
00208 static bool abort_on_error;
00209
00210
00211 std::ostream out;
00212
00213
00214 const test_desc *tests;
00215
00216
00217 static int runs;
00218
00219
00220 static std::string argv0;
00221
00222
00223 static std::string col_red, col_green, col_yellow, col_reset;
00224
00225
00226
00227 static bool use_cr;
00228 };
00229
00231 #define TESTCASE_LOCN(a) __FILE__":"STRINGIZE(__LINE__)": "STRINGIZE(a)
00232
00237 #define TEST_AND_EXPLAIN(a, b) do {\
00238 if (!(a)) FAIL_TEST(TESTCASE_LOCN(a) << std::endl << b << std::endl);\
00239 } while (0)
00240
00242 #define TEST(a) TEST_AND_EXPLAIN(a, "")
00243
00245 #define TEST_EQUAL(a, b) TEST_AND_EXPLAIN(((a) == (b)), \
00246 "Expected `"STRINGIZE(a)"' and `"STRINGIZE(b)"' to be equal:" \
00247 " were " << (a) << " and " << (b))
00248
00254 #define TEST_STRINGS_EQUAL(a, b) TEST_AND_EXPLAIN(((a) == (b)), \
00255 "Expected "STRINGIZE(a)" and "STRINGIZE(b)" to be equal, were:\n\"" \
00256 << (a) << "\"\n\"" << (b) << '"')
00257
00259 extern bool TEST_EQUAL_DOUBLE_(double a, double b);
00260
00262 #define TEST_EQUAL_DOUBLE(a, b) TEST_AND_EXPLAIN(TEST_EQUAL_DOUBLE_((a), (b)), \
00263 "Expected `"STRINGIZE(a)"' and `"STRINGIZE(b)"' to be (nearly) equal:" \
00264 " were " << setprecision(DBL_DIG) << (a) << " and " << (b) << ")" << setprecision(6))
00265
00267 #define TEST_NOT_EQUAL_DOUBLE(a, b) TEST_AND_EXPLAIN(!TEST_EQUAL_DOUBLE_((a), (b)), \
00268 "Expected `"STRINGIZE(a)"' and `"STRINGIZE(b)"' not to be (nearly) equal:" \
00269 " were " << setprecision(DBL_DIG) << (a) << " and " << (b) << ")" << setprecision(6))
00270
00272 #define TEST_NOT_EQUAL(a, b) TEST_AND_EXPLAIN(((a) != (b)), \
00273 "Expected `"STRINGIZE(a)"' and `"STRINGIZE(b)"' not to be equal:" \
00274 " were " << (a) << " and " << (b))
00275
00277 #define TEST_GREATER_OR_EQUAL(a, b) TEST_AND_EXPLAIN(((a) >= (b)), \
00278 "Expected `"STRINGIZE(a)"' to be greater than or equal to `"STRINGIZE(b)"':" \
00279 " were " << (a) << " and " << (b))
00280
00282 #define TEST_GREATER(a, b) TEST_AND_EXPLAIN(((a) > (b)), \
00283 "Expected `"STRINGIZE(a)"' to be greater than `"STRINGIZE(b)"':" \
00284 " were " << (a) << " and " << (b))
00285
00287 #define TEST_LESSER_OR_EQUAL(a, b) TEST_AND_EXPLAIN(((a) <= (b)), \
00288 "Expected `"STRINGIZE(a)"' to be less than or equal to `"STRINGIZE(b)"':" \
00289 " were " << (a) << " and " << (b))
00290
00292 #define TEST_LESSER(a, b) TEST_AND_EXPLAIN(((a) < (b)), \
00293 "Expected `"STRINGIZE(a)"' to be less than than `"STRINGIZE(b)"':" \
00294 " were " << (a) << " and " << (b))
00295
00296 #endif // OM_HGUARD_TESTSUITE_H