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