Generated on Thu Apr 11 13:59:23 2019 for Gecode by doxygen 1.6.3

test.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00006  *
00007  *  Copyright:
00008  *     Christian Schulte, 2004
00009  *     Mikael Lagerkvist, 2005
00010  *
00011  *  This file is part of Gecode, the generic constraint
00012  *  development environment:
00013  *     http://www.gecode.org
00014  *
00015  *  Permission is hereby granted, free of charge, to any person obtaining
00016  *  a copy of this software and associated documentation files (the
00017  *  "Software"), to deal in the Software without restriction, including
00018  *  without limitation the rights to use, copy, modify, merge, publish,
00019  *  distribute, sublicense, and/or sell copies of the Software, and to
00020  *  permit persons to whom the Software is furnished to do so, subject to
00021  *  the following conditions:
00022  *
00023  *  The above copyright notice and this permission notice shall be
00024  *  included in all copies or substantial portions of the Software.
00025  *
00026  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00027  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00028  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00029  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00030  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00031  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00032  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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   // Log stream
00053   std::ostringstream olog;
00054 
00055   /*
00056    * Base class for tests
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,  //< Positive match anywhere in string
00111     MT_NOT,  //< Negative match
00112     MT_FIRST //< Positive match at beginning
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) { // Negative pattern
00242             if (t->name().find(testpat[i].second) != std::string::npos)
00243               goto next;
00244           } else {               // Positive pattern
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 // STATISTICS: test-core