Generated on Mon Aug 25 11:35:45 2008 for Gecode by doxygen 1.5.6

test.cc

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  *  Last modified:
00012  *     $Date: 2008-02-21 09:28:48 +0100 (Thu, 21 Feb 2008) $ by $Author: tack $
00013  *     $Revision: 6266 $
00014  *
00015  *  This file is part of Gecode, the generic constraint
00016  *  development environment:
00017  *     http://www.gecode.org
00018  *
00019  *  Permission is hereby granted, free of charge, to any person obtaining
00020  *  a copy of this software and associated documentation files (the
00021  *  "Software"), to deal in the Software without restriction, including
00022  *  without limitation the rights to use, copy, modify, merge, publish,
00023  *  distribute, sublicense, and/or sell copies of the Software, and to
00024  *  permit persons to whom the Software is furnished to do so, subject to
00025  *  the following conditions:
00026  *
00027  *  The above copyright notice and this permission notice shall be
00028  *  included in all copies or substantial portions of the Software.
00029  *
00030  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00031  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00032  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00033  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00034  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00035  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00036  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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   // Log stream
00057   std::ostringstream olog;
00058 
00059   /*
00060    * Iterator for propagation kinds
00061    *
00062    */
00063   const Gecode::PropKind PropKinds::pks[] =
00064     {Gecode::PK_MEMORY,Gecode::PK_SPEED};
00065   
00066 
00067   /*
00068    * Base class for tests
00069    *
00070    */
00071   Base::Base(const std::string& s)
00072     : _name(s) {
00073     if (_tests == NULL) {
00074       _tests = this; _next = NULL;
00075     } else {
00076       // Search alphabetic_testsy
00077       Base* p = NULL;
00078       Base* c = _tests;
00079       while ((c != NULL) && (c->name() < s)) {
00080         p = c; c = c->_next;
00081       }
00082       if (c == NULL) {
00083         p->_next = this; _next = NULL;
00084       } else if (c == _tests) {
00085         _next = _tests; _tests = this;
00086       } else {
00087         p->_next = this; _next = c;
00088       }
00089     }
00090   }
00091 
00092   Base* Base::_tests = NULL;
00093   
00094   Base::~Base(void) {}
00095   
00096   Gecode::Support::RandomGenerator Base::rand 
00097   = Gecode::Support::RandomGenerator();
00098 
00099   Options opt;
00100   
00101   void report_error(std::string name) {
00102     std::cout << "Options: -seed " << opt.seed;
00103     if (opt.fixprob != opt.deffixprob)
00104       std::cout << " -fixprob " << opt.fixprob;
00105     std::cout << " -test " << name << std::endl;
00106     if (opt.log)
00107       std::cout << olog.str();
00108   }
00109 
00110   std::vector<std::pair<bool, const char*> > testpat;
00111   const char* startFrom = NULL;
00112   bool list = false;
00113   
00114   void
00115   Options::parse(int argc, char* argv[]) {
00116     int i = 1;
00117     while (i < argc) {
00118       if (!strcmp(argv[i],"-help") || !strcmp(argv[i],"--help")) {
00119         std::cerr << "Options for testing:" << std::endl
00120                   << "\t-seed (unsigned int or \"time\") default: " 
00121                   << seed << std::endl
00122                   << "\t\tseed for random number generator (unsigned int),"
00123                   << std::endl
00124                   << "\t\tor \"time\" for a random seed based on "
00125                   << "current time" << std::endl
00126                   << "\t-fixprob (unsigned int) default: " 
00127                   << fixprob << std::endl
00128                   << "\t\t1/fixprob is the probability of computing a fixpoint"
00129                   << std::endl
00130                   << "\t-iter (unsigned int) default: " <<iter<< std::endl
00131                   << "\t\tthe number of iterations" << std::endl
00132                   << "\t-test (string) default: (none)" << std::endl
00133                   << "\t\tsimple pattern for the tests to run" << std::endl
00134                   << "\t\tprefixing the pattern with \"-\" negates the pattern"
00135                   << std::endl
00136                   << "\t\tmultiple pattern-options may be given" << std::endl
00137                   << "\t-start (string) default: (none)" << std::endl
00138                   << "\t\tsimple pattern for the first test to run" << std::endl
00139                   << "\t-log"
00140                   << std::endl
00141                   << "\t\tlog execution of tests"
00142                   << std::endl
00143                   << "\t\tthe optional argument determines the style of the log"
00144                   << std::endl
00145                   << "\t\twith text as the default style"
00146                   << std::endl
00147                   << "\t-stop (boolean) default: "
00148                   << (stop ? "true" : "false") << std::endl
00149                   << "\t\tstop on first error or continue" << std::endl
00150                   << "\t-reflection (boolean) default: "
00151                   << (reflection ? "true" : "false") << std::endl
00152                   << "\t\tuse reflection also for copying" << std::endl
00153                   << "\t-list" << std::endl
00154                   << "\t\toutput list of all test cases and exit" << std::endl
00155           ;
00156         exit(EXIT_SUCCESS);
00157       } else if (!strcmp(argv[i],"-seed")) {
00158         if (++i == argc) goto missing;
00159         if (!strcmp(argv[i],"time")) {
00160           seed = static_cast<unsigned int>(time(NULL));
00161         } else {
00162           seed = static_cast<unsigned int>(atoi(argv[i]));
00163         }
00164       } else if (!strcmp(argv[i],"-iter")) {
00165         if (++i == argc) goto missing;
00166         iter = static_cast<unsigned int>(atoi(argv[i]));
00167       } else if (!strcmp(argv[i],"-fixprob")) {
00168         if (++i == argc) goto missing;
00169         fixprob = static_cast<unsigned int>(atoi(argv[i]));
00170       } else if (!strcmp(argv[i],"-test")) {
00171         if (++i == argc) goto missing;
00172         if (argv[i][0] == '-')
00173           testpat.push_back(std::make_pair(true, argv[i] + 1));
00174         else
00175           testpat.push_back(std::make_pair(false, argv[i]));
00176       } else if (!strcmp(argv[i],"-start")) {
00177         if (++i == argc) goto missing;
00178         startFrom = argv[i];
00179       } else if (!strcmp(argv[i],"-log")) {
00180         log = true;
00181       } else if (!strcmp(argv[i],"-stop")) {
00182         if (++i == argc) goto missing;
00183         if(argv[i][0] == 't') {
00184           stop = true;
00185         } else if (argv[i][0] == 'f') {
00186           stop = false;
00187         }
00188       } else if (!strcmp(argv[i],"-reflection")) {
00189         if (++i == argc) goto missing;
00190         if(argv[i][0] == 't') {
00191           reflection = true;
00192         } else if (argv[i][0] == 'f') {
00193           reflection = false;
00194         }
00195       } else if (!strcmp(argv[i],"-list")) {
00196         list = true;
00197       }
00198       i++;
00199     }
00200     return;
00201   missing:
00202     std::cerr << "Erroneous argument (" << argv[i-1] << ")" << std::endl
00203               << "  missing parameter" << std::endl;
00204     exit(EXIT_FAILURE);
00205   }
00206 
00207 }
00208 
00209 int
00210 main(int argc, char* argv[]) {
00211   using namespace Test;
00212 #ifdef GECODE_HAS_MTRACE
00213   mtrace();
00214 #endif
00215 
00216   opt.parse(argc, argv);
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) { // 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 (t->name().find(testpat[i].second) != std::string::npos)
00247               match_found = true;
00248           }
00249         }
00250         if (some_positive && !match_found) goto next;
00251       }
00252       std::cout << t->name() << " ";
00253       std::cout.flush();
00254       for (unsigned int i = opt.iter; i--; ) {
00255         opt.seed = Base::rand.seed();
00256         if (t->run()) {
00257           std::cout << '+';
00258           std::cout.flush();
00259         } else {
00260           std::cout << "-" << std::endl;
00261           report_error(t->name());
00262           if (opt.stop) 
00263             return 1;
00264         }
00265       }
00266     std::cout << std::endl;
00267     } catch (Gecode::Exception e) {
00268       std::cout << "Exception in \"Gecode::" << e.what()
00269                 << "." << std::endl
00270                 << "Stopping..." << std::endl;
00271       report_error(t->name());
00272       if (opt.stop) 
00273         return 1;
00274     }
00275   next:;
00276   }
00277   return 0;
00278 }
00279 
00280 std::ostream&
00281 operator<<(std::ostream& os, const Test::ind& i) {
00282   for (int j=i.l; j--; )
00283     os << "  ";
00284   return os;
00285 }
00286 
00287 // STATISTICS: test-core