test.cpp
Go to the documentation of this file.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
00039
00040 #include "test/test.hh"
00041
00042 #ifdef GECODE_HAS_MTRACE
00043 #include <mcheck.h>
00044 #endif
00045
00046 #include <iostream>
00047
00048 #include <cstdlib>
00049 #include <cstring>
00050 #include <ctime>
00051 #include <vector>
00052 #include <utility>
00053
00054 namespace Test {
00055
00056
00057 std::ostringstream olog;
00058
00059
00060
00061
00062
00063 Base::Base(const std::string& s)
00064 : _name(s), _next(_tests) {
00065 _tests = this; _n_tests++;
00066 }
00067
00068 Base* Base::_tests = NULL;
00069 unsigned int Base::_n_tests = 0;
00070
00072 class SortByName {
00073 public:
00074 forceinline bool
00075 operator()(Base* x, Base* y) {
00076 return x->name() > y->name();
00077 }
00078 };
00079
00080 void
00081 Base::sort(void) {
00082 Base** b = Gecode::heap.alloc<Base*>(_n_tests);
00083 unsigned int i=0;
00084 for (Base* t = _tests; t != NULL; t = t->next())
00085 b[i++] = t;
00086 SortByName sbn;
00087 Gecode::Support::quicksort(b,_n_tests,sbn);
00088 i=0;
00089 _tests = NULL;
00090 for ( ; i < _n_tests; i++) {
00091 b[i]->next(_tests); _tests = b[i];
00092 }
00093 Gecode::heap.free(b,_n_tests);
00094 }
00095
00096 Base::~Base(void) {}
00097
00098 Gecode::Support::RandomGenerator Base::rand
00099 = Gecode::Support::RandomGenerator();
00100
00101 Options opt;
00102
00103 void report_error(std::string name) {
00104 std::cout << "Options: -seed " << opt.seed;
00105 if (opt.fixprob != opt.deffixprob)
00106 std::cout << " -fixprob " << opt.fixprob;
00107 std::cout << " -test " << name << std::endl;
00108 if (opt.log)
00109 std::cout << olog.str();
00110 }
00111
00113 enum MatchType {
00114 MT_ANY,
00115 MT_NOT,
00116 MT_FIRST
00117 };
00118
00119 std::vector<std::pair<MatchType, const char*> > testpat;
00120 const char* startFrom = NULL;
00121 bool list = false;
00122
00123 void
00124 Options::parse(int argc, char* argv[]) {
00125 int i = 1;
00126 while (i < argc) {
00127 if (!strcmp(argv[i],"-help") || !strcmp(argv[i],"--help")) {
00128 std::cerr << "Options for testing:" << std::endl
00129 << "\t-seed (unsigned int or \"time\") default: "
00130 << seed << std::endl
00131 << "\t\tseed for random number generator (unsigned int),"
00132 << std::endl
00133 << "\t\tor \"time\" for a random seed based on "
00134 << "current time" << std::endl
00135 << "\t-fixprob (unsigned int) default: "
00136 << fixprob << std::endl
00137 << "\t\t1/fixprob is the probability of computing a fixpoint"
00138 << std::endl
00139 << "\t-iter (unsigned int) default: " <<iter<< std::endl
00140 << "\t\tthe number of iterations" << std::endl
00141 << "\t-test (string) default: (none)" << std::endl
00142 << "\t\tsimple pattern for the tests to run" << std::endl
00143 << "\t\tprefixing with \"-\" negates the pattern" << std::endl
00144 << "\t\tprefixing with \"^\" requires a match at the beginning" << std::endl
00145 << "\t\tmultiple pattern-options may be given"
00146 << std::endl
00147 << "\t-start (string) default: (none)" << std::endl
00148 << "\t\tsimple pattern for the first test to run" << std::endl
00149 << "\t-log"
00150 << std::endl
00151 << "\t\tlog execution of tests"
00152 << std::endl
00153 << "\t\tthe optional argument determines the style of the log"
00154 << std::endl
00155 << "\t\twith text as the default style"
00156 << std::endl
00157 << "\t-stop (boolean) default: "
00158 << (stop ? "true" : "false") << std::endl
00159 << "\t\tstop on first error or continue" << std::endl
00160 << "\t-list" << std::endl
00161 << "\t\toutput list of all test cases and exit" << std::endl
00162 ;
00163 exit(EXIT_SUCCESS);
00164 } else if (!strcmp(argv[i],"-seed")) {
00165 if (++i == argc) goto missing;
00166 if (!strcmp(argv[i],"time")) {
00167 seed = static_cast<unsigned int>(time(NULL));
00168 } else {
00169 seed = static_cast<unsigned int>(atoi(argv[i]));
00170 }
00171 } else if (!strcmp(argv[i],"-iter")) {
00172 if (++i == argc) goto missing;
00173 iter = static_cast<unsigned int>(atoi(argv[i]));
00174 } else if (!strcmp(argv[i],"-fixprob")) {
00175 if (++i == argc) goto missing;
00176 fixprob = static_cast<unsigned int>(atoi(argv[i]));
00177 } else if (!strcmp(argv[i],"-test")) {
00178 if (++i == argc) goto missing;
00179 if (argv[i][0] == '^')
00180 testpat.push_back(std::make_pair(MT_FIRST, argv[i] + 1));
00181 else if (argv[i][0] == '-')
00182 testpat.push_back(std::make_pair(MT_NOT, argv[i] + 1));
00183 else
00184 testpat.push_back(std::make_pair(MT_ANY, argv[i]));
00185 } else if (!strcmp(argv[i],"-start")) {
00186 if (++i == argc) goto missing;
00187 startFrom = argv[i];
00188 } else if (!strcmp(argv[i],"-log")) {
00189 log = true;
00190 } else if (!strcmp(argv[i],"-stop")) {
00191 if (++i == argc) goto missing;
00192 if(argv[i][0] == 't') {
00193 stop = true;
00194 } else if (argv[i][0] == 'f') {
00195 stop = false;
00196 }
00197 } else if (!strcmp(argv[i],"-list")) {
00198 list = true;
00199 }
00200 i++;
00201 }
00202 return;
00203 missing:
00204 std::cerr << "Erroneous argument (" << argv[i-1] << ")" << std::endl
00205 << " missing parameter" << std::endl;
00206 exit(EXIT_FAILURE);
00207 }
00208
00209 }
00210
00211 int
00212 main(int argc, char* argv[]) {
00213 using namespace Test;
00214 #ifdef GECODE_HAS_MTRACE
00215 mtrace();
00216 #endif
00217
00218 opt.parse(argc, argv);
00219
00220 Base::sort();
00221
00222 if (list) {
00223 for (Base* t = Base::tests() ; t != NULL; t = t->next() ) {
00224 std::cout << t->name() << std::endl;
00225 }
00226 exit(EXIT_SUCCESS);
00227 }
00228
00229 Base::rand.seed(opt.seed);
00230
00231 bool started = startFrom == NULL ? true : false;
00232
00233 for (Base* t = Base::tests() ; t != NULL; t = t->next() ) {
00234 try {
00235 if (!started) {
00236 if (t->name().find(startFrom) != std::string::npos)
00237 started = true;
00238 else
00239 goto next;
00240 }
00241 if (testpat.size() != 0) {
00242 bool match_found = false;
00243 bool some_positive = false;
00244 for (unsigned int i = 0; i < testpat.size(); ++i) {
00245 if (testpat[i].first == MT_NOT) {
00246 if (t->name().find(testpat[i].second) != std::string::npos)
00247 goto next;
00248 } else {
00249 some_positive = true;
00250 if (((testpat[i].first == MT_ANY) &&
00251 (t->name().find(testpat[i].second) != std::string::npos)) ||
00252 ((testpat[i].first == MT_FIRST) &&
00253 (t->name().find(testpat[i].second) == 0)))
00254 match_found = true;
00255 }
00256 }
00257 if (some_positive && !match_found) goto next;
00258 }
00259 std::cout << t->name() << " ";
00260 std::cout.flush();
00261 for (unsigned int i = opt.iter; i--; ) {
00262 opt.seed = Base::rand.seed();
00263 if (t->run()) {
00264 std::cout << '+';
00265 std::cout.flush();
00266 } else {
00267 std::cout << "-" << std::endl;
00268 report_error(t->name());
00269 if (opt.stop)
00270 return 1;
00271 }
00272 }
00273 std::cout << std::endl;
00274 } catch (Gecode::Exception e) {
00275 std::cout << "Exception in \"Gecode::" << e.what()
00276 << "." << std::endl
00277 << "Stopping..." << std::endl;
00278 report_error(t->name());
00279 if (opt.stop)
00280 return 1;
00281 }
00282 next:;
00283 }
00284 return 0;
00285 }
00286
00287 std::ostream&
00288 operator<<(std::ostream& os, const Test::ind& i) {
00289 for (int j=i.l; j--; )
00290 os << " ";
00291 return os;
00292 }
00293
00294