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
00112 std::vector<std::pair<bool, const char*> > testpat;
00113 const char* startFrom = NULL;
00114 bool list = false;
00115
00116 void
00117 Options::parse(int argc, char* argv[]) {
00118 int i = 1;
00119 while (i < argc) {
00120 if (!strcmp(argv[i],"-help") || !strcmp(argv[i],"--help")) {
00121 std::cerr << "Options for testing:" << std::endl
00122 << "\t-seed (unsigned int or \"time\") default: "
00123 << seed << std::endl
00124 << "\t\tseed for random number generator (unsigned int),"
00125 << std::endl
00126 << "\t\tor \"time\" for a random seed based on "
00127 << "current time" << std::endl
00128 << "\t-fixprob (unsigned int) default: "
00129 << fixprob << std::endl
00130 << "\t\t1/fixprob is the probability of computing a fixpoint"
00131 << std::endl
00132 << "\t-iter (unsigned int) default: " <<iter<< std::endl
00133 << "\t\tthe number of iterations" << std::endl
00134 << "\t-test (string) default: (none)" << std::endl
00135 << "\t\tsimple pattern for the tests to run" << std::endl
00136 << "\t\tprefixing the pattern with \"-\" negates the pattern"
00137 << std::endl
00138 << "\t\tmultiple pattern-options may be given" << std::endl
00139 << "\t-start (string) default: (none)" << std::endl
00140 << "\t\tsimple pattern for the first test to run" << std::endl
00141 << "\t-log"
00142 << std::endl
00143 << "\t\tlog execution of tests"
00144 << std::endl
00145 << "\t\tthe optional argument determines the style of the log"
00146 << std::endl
00147 << "\t\twith text as the default style"
00148 << std::endl
00149 << "\t-stop (boolean) default: "
00150 << (stop ? "true" : "false") << std::endl
00151 << "\t\tstop on first error or continue" << std::endl
00152 << "\t-list" << std::endl
00153 << "\t\toutput list of all test cases and exit" << std::endl
00154 ;
00155 exit(EXIT_SUCCESS);
00156 } else if (!strcmp(argv[i],"-seed")) {
00157 if (++i == argc) goto missing;
00158 if (!strcmp(argv[i],"time")) {
00159 seed = static_cast<unsigned int>(time(NULL));
00160 } else {
00161 seed = static_cast<unsigned int>(atoi(argv[i]));
00162 }
00163 } else if (!strcmp(argv[i],"-iter")) {
00164 if (++i == argc) goto missing;
00165 iter = static_cast<unsigned int>(atoi(argv[i]));
00166 } else if (!strcmp(argv[i],"-fixprob")) {
00167 if (++i == argc) goto missing;
00168 fixprob = static_cast<unsigned int>(atoi(argv[i]));
00169 } else if (!strcmp(argv[i],"-test")) {
00170 if (++i == argc) goto missing;
00171 if (argv[i][0] == '-')
00172 testpat.push_back(std::make_pair(true, argv[i] + 1));
00173 else
00174 testpat.push_back(std::make_pair(false, argv[i]));
00175 } else if (!strcmp(argv[i],"-start")) {
00176 if (++i == argc) goto missing;
00177 startFrom = argv[i];
00178 } else if (!strcmp(argv[i],"-log")) {
00179 log = true;
00180 } else if (!strcmp(argv[i],"-stop")) {
00181 if (++i == argc) goto missing;
00182 if(argv[i][0] == 't') {
00183 stop = true;
00184 } else if (argv[i][0] == 'f') {
00185 stop = false;
00186 }
00187 } else if (!strcmp(argv[i],"-list")) {
00188 list = true;
00189 }
00190 i++;
00191 }
00192 return;
00193 missing:
00194 std::cerr << "Erroneous argument (" << argv[i-1] << ")" << std::endl
00195 << " missing parameter" << std::endl;
00196 exit(EXIT_FAILURE);
00197 }
00198
00199 }
00200
00201 int
00202 main(int argc, char* argv[]) {
00203 using namespace Test;
00204 #ifdef GECODE_HAS_MTRACE
00205 mtrace();
00206 #endif
00207
00208 opt.parse(argc, argv);
00209
00210 Base::sort();
00211
00212 if (list) {
00213 for (Base* t = Base::tests() ; t != NULL; t = t->next() ) {
00214 std::cout << t->name() << std::endl;
00215 }
00216 exit(EXIT_SUCCESS);
00217 }
00218
00219 Base::rand.seed(opt.seed);
00220
00221 bool started = startFrom == NULL ? true : false;
00222
00223 for (Base* t = Base::tests() ; t != NULL; t = t->next() ) {
00224 try {
00225 if (!started) {
00226 if (t->name().find(startFrom) != std::string::npos)
00227 started = true;
00228 else
00229 goto next;
00230 }
00231 if (testpat.size() != 0) {
00232 bool match_found = false;
00233 bool some_positive = false;
00234 for (unsigned int i = 0; i < testpat.size(); ++i) {
00235 if (testpat[i].first) {
00236 if (t->name().find(testpat[i].second) != std::string::npos)
00237 goto next;
00238 } else {
00239 some_positive = true;
00240 if (t->name().find(testpat[i].second) != std::string::npos)
00241 match_found = true;
00242 }
00243 }
00244 if (some_positive && !match_found) goto next;
00245 }
00246 std::cout << t->name() << " ";
00247 std::cout.flush();
00248 for (unsigned int i = opt.iter; i--; ) {
00249 opt.seed = Base::rand.seed();
00250 if (t->run()) {
00251 std::cout << '+';
00252 std::cout.flush();
00253 } else {
00254 std::cout << "-" << std::endl;
00255 report_error(t->name());
00256 if (opt.stop)
00257 return 1;
00258 }
00259 }
00260 std::cout << std::endl;
00261 } catch (Gecode::Exception e) {
00262 std::cout << "Exception in \"Gecode::" << e.what()
00263 << "." << std::endl
00264 << "Stopping..." << std::endl;
00265 report_error(t->name());
00266 if (opt.stop)
00267 return 1;
00268 }
00269 next:;
00270 }
00271 return 0;
00272 }
00273
00274 std::ostream&
00275 operator<<(std::ostream& os, const Test::ind& i) {
00276 for (int j=i.l; j--; )
00277 os << " ";
00278 return os;
00279 }
00280
00281