00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef TESTSUITE_C_DEFINED
00039 #define TESTSUITE_C_DEFINED
00040
00041 #include "TestSuite/TestSuite.H"
00042
00043 #include "Image/IO.H"
00044 #include "Image/Image.H"
00045 #include "Image/MathOps.H"
00046 #include "Image/Pixels.H"
00047 #include "rutz/prof.h"
00048
00049 #include <iomanip>
00050 #include <iostream>
00051 #include <sstream>
00052 #include <string>
00053 #include <vector>
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 struct TestData
00064 {
00065 TestData(const std::string& n, TestFunc f) : name(n), func(f) {}
00066
00067 std::string name;
00068 TestFunc func;
00069 };
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 struct TestSuite::Impl
00084 {
00085 Impl() : itsTests(), itsSuccess(true), itsOutput() {}
00086
00087 std::vector<TestData> itsTests;
00088 bool itsSuccess;
00089 std::ostringstream itsOutput;
00090
00091 void printResult()
00092 {
00093 std::cout << itsSuccess << "\n"
00094 << itsOutput.str() << "\n";
00095 }
00096
00097 template <class T>
00098 bool requireScalarEq(const T& expr, const T& expected,
00099 const char* srcfile, int line, const char* expr_str)
00100 {
00101 const bool ok = (expr == expected);
00102 if ( !ok )
00103 {
00104 itsSuccess = false;
00105 itsOutput << "\tFAILED @ " << srcfile << ":" << line << ": "
00106 << expr_str << ", "
00107 << "expected '"
00108 << std::setprecision(30) << std::showpoint << expected
00109 << "', got '"
00110 << std::setprecision(30) << std::showpoint << expr
00111 << "'\n";
00112 }
00113 return ok;
00114 }
00115
00116 template <class T>
00117 bool requireImgEq(const Image<T>& expr, const Image<T>& expected,
00118 const char* srcfile, int line, const char* expr_str)
00119 {
00120 const bool ok = (expr == expected);
00121 if ( !ok )
00122 {
00123 itsSuccess = false;
00124 itsOutput << "\tFAILED @ " << srcfile << ":" << line << ": "
00125 << expr_str << ", "
00126 << "expected (" << convertToString(expected.getDims()) << ") "
00127 << expected << ", "
00128 << "got (" << convertToString(expr.getDims()) << ") "
00129 << expr << "\n";
00130 }
00131 return ok;
00132 }
00133
00134 bool requireImgEqFp(const Image<float>& expr, const Image<float>& expected,
00135 const float prec, const char* srcfile, int line,
00136 const char* expr_str)
00137 {
00138 bool ok = false;
00139 std::ostringstream extrainfo;
00140
00141 if (expr.getDims() == expected.getDims())
00142 {
00143 Image<float> diff = abs(expr - expected);
00144 float ma; Point2D<int> loc;
00145 findMax(diff, loc, ma);
00146
00147 ok = (ma <= prec);
00148
00149 extrainfo << "(largest difference of " << ma << " at [x="
00150 << loc.i << ",y=" << loc.j << "])\n";
00151 }
00152
00153 if ( !ok )
00154 {
00155 itsSuccess = false;
00156 itsOutput << "\tFAILED @ " << srcfile << ":" << line << ": "
00157 << expr_str << ", "
00158 << "expected (" << convertToString(expected.getDims()) << ") "
00159 << expected << ", "
00160 << "got (" << convertToString(expr.getDims()) << ") "
00161 << expr << "\n"
00162 << extrainfo.str();
00163 }
00164 return ok;
00165 }
00166
00167 bool requireEqUserTypeImpl(const bool ok,
00168 const std::string& expr,
00169 const std::string& expected,
00170 const char* srcfile, int line,
00171 const char* expr_str)
00172
00173 {
00174 if ( !ok )
00175 {
00176 itsSuccess = false;
00177 itsOutput << "\tFAILED @ " << srcfile << ":" << line << ": "
00178 << expr_str << ", "
00179 << "expected '"
00180 << expected
00181 << "', got '"
00182 << expr
00183 << "'\n";
00184 }
00185 return ok;
00186 }
00187
00188 template <class T>
00189 static bool compare(const T& lhs, Op op, const T& rhs)
00190 {
00191 switch (op)
00192 {
00193 case EQ: return lhs == rhs;
00194 case NEQ: return lhs != rhs;
00195 case LT: return lhs < rhs;
00196 case LTE: return lhs <= rhs;
00197 case GT: return lhs > rhs;
00198 case GTE: return lhs >= rhs;
00199 }
00200 LFATAL("invalid Op '%d'", int(op));
00201 return false;
00202 }
00203
00204 static const char* opname(Op op)
00205 {
00206 switch (op)
00207 {
00208 case EQ: return " == ";
00209 case NEQ: return " != ";
00210 case LT: return " < ";
00211 case LTE: return " <= ";
00212 case GT: return " > ";
00213 case GTE: return " >= ";
00214 }
00215 LFATAL("invalid Op '%d'", int(op));
00216 return "";
00217 }
00218
00219 template <class T>
00220 bool require(const T& lhs, Op op, const T& rhs,
00221 const char* srcfile, int line,
00222 const char* lhs_str, const char* rhs_str)
00223 {
00224 const bool ok = compare(lhs, op, rhs);
00225 if ( !ok )
00226 {
00227 itsSuccess = false;
00228 itsOutput << "\tFAILED @ " << srcfile << ":" << line << ":\n"
00229 << "\t expected " << lhs_str << opname(op) << rhs_str << ",\n "
00230 << "\t got " << lhs_str << "==" << lhs
00231 << " and " << rhs_str << "==" << rhs << '\n';
00232 }
00233 return ok;
00234 }
00235 };
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 TestSuite::TestSuite() :
00246 rep(new Impl)
00247 {}
00248
00249
00250 TestSuite::~TestSuite()
00251 {
00252 delete rep;
00253 }
00254
00255
00256 void TestSuite::addTest(const char* name, TestFunc func)
00257 {
00258 rep->itsTests.push_back(TestData(name, func));
00259 }
00260
00261
00262 void TestSuite::printAvailableTests() const
00263 {
00264 for (unsigned int i = 0; i < rep->itsTests.size(); ++i)
00265 std::cout << '{' << i << '\t' << rep->itsTests[i].name << "}\n";
00266 }
00267
00268
00269 void TestSuite::printAvailableTestsForPerl() const
00270 {
00271 for (unsigned int i = 0; i < rep->itsTests.size(); ++i)
00272 std::cout << i << '\t' << rep->itsTests[i].name << "\n";
00273 }
00274
00275
00276 void TestSuite::runTest(int test_n, int repeat_n)
00277 {
00278 if (test_n < 0 || (unsigned int) test_n >= rep->itsTests.size())
00279 return;
00280
00281 for (int i = 0; i < repeat_n; ++i)
00282 rep->itsTests.at(test_n).func(*this);
00283
00284 rep->printResult();
00285 }
00286
00287
00288 namespace
00289 {
00290 void showUsageAndExit(const char* argv0)
00291 {
00292 std::cerr << "usage: " << argv0 << " <options>\n"
00293 << "available options:\n"
00294 << "\t--query print test names and number (for tcl)\n"
00295 << "\t--perlquery print test names and number (for perl)\n"
00296 << "\t--run <n> run the test number <n>\n"
00297 << "\t--repeat <n> repeat the test <n> times (for profiling, etc.)\n"
00298 << "\t--dump-prof print a profiling summary before exit\n";
00299
00300 exit(1);
00301 }
00302 }
00303
00304
00305 void TestSuite::parseAndRun(int argc, const char** argv)
00306 {
00307 if (argc == 1)
00308 {
00309 showUsageAndExit(argv[0]);
00310 }
00311
00312 int test_n = -1;
00313 int repeat_n = 1;
00314 bool dump_prof = false;
00315
00316 for (int i = 1; i < argc; ++i)
00317 {
00318 if (strcmp(argv[i], "--run") == 0)
00319 {
00320 if (++i < argc) test_n = atoi(argv[i]);
00321 }
00322
00323 else if (strcmp(argv[i], "--repeat") == 0)
00324 {
00325 if (++i < argc) repeat_n = atoi(argv[i]);
00326 }
00327
00328 else if (strcmp(argv[i], "--query") == 0)
00329 {
00330 printAvailableTests();
00331 return;
00332 }
00333
00334 else if (strcmp(argv[i], "--perlquery") == 0)
00335 {
00336 printAvailableTestsForPerl();
00337 return;
00338 }
00339
00340 else if (strcmp(argv[i], "--dump-prof") == 0)
00341 {
00342 dump_prof = true;
00343 }
00344
00345 else
00346 {
00347 showUsageAndExit(argv[0]);
00348 }
00349 }
00350
00351 runTest(test_n, repeat_n);
00352
00353 if (dump_prof)
00354 rutz::prof::print_all_prof_data(std::cerr);
00355 }
00356
00357
00358 bool TestSuite::require(bool expr, const char* srcfile, int line, const char* expr_str)
00359 {
00360 if (!expr)
00361 {
00362 rep->itsSuccess = false;
00363 rep->itsOutput << "\tFAILED @ " << srcfile << ":" << line << ": "
00364 << expr_str << "\n";
00365 }
00366 return expr;
00367 }
00368
00369
00370 bool TestSuite::requireEq(int expr, int expected,
00371 const char* srcfile, int line, const char* expr_str)
00372 { return rep->requireScalarEq(expr, expected, srcfile, line, expr_str); }
00373
00374
00375 bool TestSuite::requireEq(uint expr, uint expected,
00376 const char* srcfile, int line, const char* expr_str)
00377 { return rep->requireScalarEq(expr, expected, srcfile, line, expr_str); }
00378
00379
00380 bool TestSuite::requireEq(long expr, long expected,
00381 const char* srcfile, int line, const char* expr_str)
00382 { return rep->requireScalarEq(expr, expected, srcfile, line, expr_str); }
00383
00384
00385 bool TestSuite::requireEq(unsigned long expr, unsigned long expected,
00386 const char* srcfile, int line, const char* expr_str)
00387 { return rep->requireScalarEq(expr, expected, srcfile, line, expr_str); }
00388
00389
00390 bool TestSuite::requireEq(double expr, double expected,
00391 const char* srcfile, int line, const char* expr_str)
00392 { return rep->requireScalarEq(expr, expected, srcfile, line, expr_str); }
00393
00394
00395 bool TestSuite::requireEq(const std::string& expr, const std::string& expected,
00396 const char* srcfile, int line, const char* expr_str)
00397 { return rep->requireScalarEq(expr, expected, srcfile, line, expr_str); }
00398
00399
00400 template <class T>
00401 bool TestSuite::requireEq(const Image<T>& expr, const Image<T>& expected,
00402 const char* srcfile, int line, const char* expr_str)
00403 { return rep->requireImgEq(expr, expected, srcfile, line, expr_str); }
00404
00405
00406 bool TestSuite::requireEq(const Image<float>& expr,
00407 const Image<float>& expected,
00408 const float prec, const char* srcfile, int line,
00409 const char* expr_str)
00410 { return rep->requireImgEqFp(expr, expected, prec, srcfile, line, expr_str); }
00411
00412
00413 bool TestSuite::require(int lhs, Op op, int rhs,
00414 const char* srcfile, int line,
00415 const char* lhs_str, const char* rhs_str)
00416 { return rep->require(lhs, op, rhs, srcfile, line, lhs_str, rhs_str); }
00417
00418
00419 bool TestSuite::require(long lhs, Op op, long rhs,
00420 const char* srcfile, int line,
00421 const char* lhs_str, const char* rhs_str)
00422 { return rep->require(lhs, op, rhs, srcfile, line, lhs_str, rhs_str); }
00423
00424
00425 bool TestSuite::require(double lhs, Op op, double rhs,
00426 const char* srcfile, int line,
00427 const char* lhs_str, const char* rhs_str)
00428 { return rep->require(lhs, op, rhs, srcfile, line, lhs_str, rhs_str); }
00429
00430
00431 bool TestSuite::requireEqUserTypeImpl(const bool ok,
00432 const std::string& expr,
00433 const std::string& expected,
00434 const char* srcfile, int line,
00435 const char* expr_str)
00436 { return rep->requireEqUserTypeImpl(ok, expr, expected, srcfile, line, expr_str); }
00437
00438
00439
00440 #define INST_CLASS TestSuite::
00441 #include "inst/TestSuite/TestSuite.I"
00442
00443 template bool INST_CLASS requireEq(const Image<int>& expr, const Image<int>& expected, const char* srcfile, int line, const char* expr_str);
00444
00445
00446
00447
00448
00449
00450 #endif // !TESTSUITE_C_DEFINED