tests/harness/testsuite.h

Go to the documentation of this file.
00001 /* testsuite.h: a generic test suite engine
00002  *
00003  * Copyright 1999,2000,2001 BrightStation PLC
00004  * Copyright 2002,2003,2005,2006,2007,2008 Olly Betts
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License as
00008  * published by the Free Software Foundation; either version 2 of the
00009  * License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
00019  * USA
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" // For STRINGIZE().
00030 
00031 #include <iomanip>
00032 #include <map>
00033 #include <sstream>
00034 #include <string>
00035 #include <vector>
00036 
00037 #include <float.h> // For DBL_DIG.
00038 
00041 class TestFail { };
00042 
00048 class TestSkip { };
00049 
00052 // Don't bracket a, because it may have <<'s in it
00053 #define FAIL_TEST(a) do { TestFail testfail; \
00054                           if (verbose) { tout << a << '\n'; } \
00055                           throw testfail; } while (0)
00056 
00059 // Don't bracket a, because it may have <<'s in it
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 //  If verbose is set, then the test harness will display diagnostic output
00079 //  for tests which fail or skip.  Individual tests may use this flag to avoid
00080 //  needless generation of diagnostic output in cases when it's expensive.
00081 extern bool verbose;
00082 
00084 //  Used to detect if such an exception was mishandled by the
00085 //  compiler/runtime.
00086 extern const char * expected_exception;
00087 
00091 extern std::ostringstream tout;
00092 
00094 class test_driver {
00096         void write_and_clear_tout();
00097 
00098     public:
00102         struct result {
00104             unsigned int succeeded;
00105 
00107             unsigned int failed;
00108 
00110             unsigned int skipped;
00111 
00112             result() : succeeded(0), failed(0), skipped(0) { }
00113 
00114             result & operator+=(const result & o) {
00115                 succeeded += o.succeeded;
00116                 failed += o.failed;
00117                 skipped += o.skipped;
00118                 return *this;
00119             }
00120 
00121             void reset() {
00122                 succeeded = 0;
00123                 failed = 0;
00124                 skipped = 0;
00125             }
00126         };
00127 
00136         static void add_command_line_option(const std::string &l, char s,
00137                                             std::string * arg);
00138 
00144         static void parse_command_line(int argc, char **argv);
00145 
00146         XAPIAN_NORETURN(static void usage());
00147 
00148         static int run(const test_desc *tests);
00149 
00154         test_driver(const test_desc *tests_);
00155 
00158         result run_tests();
00159 
00162         result run_tests(std::vector<std::string>::const_iterator b,
00163                          std::vector<std::string>::const_iterator e);
00164 
00168         static std::string get_srcdir();
00169 
00170         // Running subtotal for current backend.
00171         static result subtotal;
00172 
00173         // Running total for the whole test run.
00174         static result total;
00175 
00177         static void report(const test_driver::result &r, const std::string &desc);
00178 
00179     private:
00181         test_driver(const test_driver &);
00182         test_driver & operator = (const test_driver &);
00183 
00184         typedef enum { PASS = 1, FAIL = 0, SKIP = -1 } test_result;
00185 
00186         static std::map<int, std::string *> short_opts;
00187 
00188         static std::string opt_help;
00189 
00190         static std::vector<std::string> test_names;
00191 
00198         test_result runtest(const test_desc *test);
00199 
00207         result do_run_tests(std::vector<std::string>::const_iterator b,
00208                             std::vector<std::string>::const_iterator e);
00209 
00210         // abort tests at the first failure
00211         static bool abort_on_error;
00212 
00213         // the default stream to output to
00214         std::ostream out;
00215 
00216         // the list of tests to run.
00217         const test_desc *tests;
00218 
00219         // how many test runs we've done - no summary if just one run
00220         static int runs;
00221 
00222         // program name
00223         static std::string argv0;
00224 
00225         // strings to use for colouring - empty if output isn't a tty
00226         static std::string col_red, col_green, col_yellow, col_reset;
00227 
00228         // use \r to not advance a line when a test passes (this only
00229         // really makes sense if the output is a tty)
00230         static bool use_cr;
00231 };
00232 
00234 #define TESTCASE_LOCN(a) __FILE__":"STRINGIZE(__LINE__)": "STRINGIZE(a)
00235 
00240 #define TEST_AND_EXPLAIN(a, b) do {\
00241         if (!(a)) FAIL_TEST(TESTCASE_LOCN(a) << std::endl << b << std::endl);\
00242     } while (0)
00243 
00245 #define TEST(a) TEST_AND_EXPLAIN(a, "")
00246 
00247 // Crude wrapper for compatibility with tests backported from 1.1.x.
00248 #define TEST_REL(A,R,B) TEST((A) R (B))
00249 
00251 #define TEST_EQUAL(a, b) TEST_AND_EXPLAIN(((a) == (b)), \
00252         "Expected `"STRINGIZE(a)"' and `"STRINGIZE(b)"' to be equal:" \
00253         " were " << (a) << " and " << (b))
00254 
00260 #define TEST_STRINGS_EQUAL(a, b) TEST_AND_EXPLAIN(((a) == (b)), \
00261         "Expected "STRINGIZE(a)" and "STRINGIZE(b)" to be equal, were:\n\"" \
00262         << (a) << "\"\n\"" << (b) << '"')
00263 
00265 extern bool TEST_EQUAL_DOUBLE_(double a, double b);
00266 
00268 #define TEST_EQUAL_DOUBLE(a, b) TEST_AND_EXPLAIN(TEST_EQUAL_DOUBLE_((a), (b)), \
00269         "Expected `"STRINGIZE(a)"' and `"STRINGIZE(b)"' to be (nearly) equal:" \
00270         " were " << setprecision(DBL_DIG) << (a) << " and " << (b) << ")" << setprecision(6))
00271 
00273 #define TEST_NOT_EQUAL_DOUBLE(a, b) TEST_AND_EXPLAIN(!TEST_EQUAL_DOUBLE_((a), (b)), \
00274         "Expected `"STRINGIZE(a)"' and `"STRINGIZE(b)"' not to be (nearly) equal:" \
00275         " were " << setprecision(DBL_DIG) << (a) << " and " << (b) << ")" << setprecision(6))
00276 
00278 #define TEST_NOT_EQUAL(a, b) TEST_AND_EXPLAIN(((a) != (b)), \
00279         "Expected `"STRINGIZE(a)"' and `"STRINGIZE(b)"' not to be equal:" \
00280         " were " << (a) << " and " << (b))
00281 
00283 #define TEST_GREATER_OR_EQUAL(a, b) TEST_AND_EXPLAIN(((a) >= (b)), \
00284         "Expected `"STRINGIZE(a)"' to be greater than or equal to `"STRINGIZE(b)"':" \
00285         " were " << (a) << " and " << (b))
00286 
00288 #define TEST_GREATER(a, b) TEST_AND_EXPLAIN(((a) > (b)), \
00289         "Expected `"STRINGIZE(a)"' to be greater than `"STRINGIZE(b)"':" \
00290         " were " << (a) << " and " << (b))
00291 
00293 #define TEST_LESSER_OR_EQUAL(a, b) TEST_AND_EXPLAIN(((a) <= (b)), \
00294         "Expected `"STRINGIZE(a)"' to be less than or equal to `"STRINGIZE(b)"':" \
00295         " were " << (a) << " and " << (b))
00296 
00298 #define TEST_LESSER(a, b) TEST_AND_EXPLAIN(((a) < (b)), \
00299         "Expected `"STRINGIZE(a)"' to be less than than `"STRINGIZE(b)"':" \
00300         " were " << (a) << " and " << (b))
00301 
00302 #endif // OM_HGUARD_TESTSUITE_H

Documentation for Xapian (version 1.0.20).
Generated on 28 Apr 2010 by Doxygen 1.5.2.