Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
9.2 kB · 291 lines
C++
at develop
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- *//* * Main authors: * Christian Schulte <schulte@gecode.org> * Mikael Lagerkvist <lagerkvist@gecode.org> * * Copyright: * Christian Schulte, 2004 * Mikael Lagerkvist, 2005 * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */
#include "test/test.hh"
#ifdef GECODE_HAS_MTRACE#include <mcheck.h>#endif
#include <iostream>
#include <cstdlib>#include <cstring>#include <ctime>#include <utility>#include <vector>#include <utility>
namespace Test {
// Log stream std::ostringstream olog;
/* * Base class for tests * */ Base::Base(std::string s) : _name(std::move(s)), _next(_tests) { _tests = this; _n_tests++; }
Base* Base::_tests = nullptr; unsigned int Base::_n_tests = 0;
/// Sort tests by name class SortByName { public: forceinline bool operator()(Base* x, Base* y) { return x->name() > y->name(); } };
void Base::sort() { Base** b = Gecode::heap.alloc<Base*>(_n_tests); unsigned int i=0; for (Base* t = _tests; t != nullptr; t = t->next()) b[i++] = t; SortByName sbn; Gecode::Support::quicksort(b, _n_tests,sbn); i=0; _tests = nullptr; for ( ; i < _n_tests; i++) { b[i]->next(_tests); _tests = b[i]; } Gecode::heap.free(b,_n_tests); }
Base::~Base() = default;
Gecode::Support::RandomGenerator Base::rand = Gecode::Support::RandomGenerator();
Options opt;
void report_error(const std::string& name) { std::cout << "Options: -seed " << opt.seed; if (opt.fixprob != Test::Options::deffixprob) std::cout << " -fixprob " << opt.fixprob; std::cout << " -test " << name << std::endl; if (opt.log) std::cout << olog.str(); }
/// How to match enum MatchType { MT_ANY, //< Positive match anywhere in string MT_NOT, //< Negative match MT_FIRST //< Positive match at beginning };
std::vector<std::pair<MatchType, const char*> > testpat; const char* startFrom = nullptr; bool list = false;
void Options::parse(int argc, char* argv[]) { int i = 1; while (i < argc) { if (!strcmp(argv[i],"-help") || !strcmp(argv[i],"--help")) { std::cerr << "Options for testing:" << std::endl << "\t-seed (unsigned int or \"time\") default: " << seed << std::endl << "\t\tseed for random number generator (unsigned int)," << std::endl << "\t\tor \"time\" for a random seed based on " << "current time" << std::endl << "\t-fixprob (unsigned int) default: " << fixprob << std::endl << "\t\t1/fixprob is the probability of computing a fixpoint" << std::endl << "\t-iter (unsigned int) default: " <<iter<< std::endl << "\t\tthe number of iterations" << std::endl << "\t-test (string) default: (none)" << std::endl << "\t\tsimple pattern for the tests to run" << std::endl << "\t\tprefixing with \"-\" negates the pattern" << std::endl << "\t\tprefixing with \"^\" requires a match at the beginning" << std::endl << "\t\tmultiple pattern-options may be given" << std::endl << "\t-start (string) default: (none)" << std::endl << "\t\tsimple pattern for the first test to run" << std::endl << "\t-log" << std::endl << "\t\tlog execution of tests" << std::endl << "\t\tthe optional argument determines the style of the log" << std::endl << "\t\twith text as the default style" << std::endl << "\t-stop (boolean) default: " << (stop ? "true" : "false") << std::endl << "\t\tstop on first error or continue" << std::endl << "\t-list" << std::endl << "\t\toutput list of all test cases and exit" << std::endl ; exit(EXIT_SUCCESS); } else if (!strcmp(argv[i],"-seed")) { if (++i == argc) goto missing; if (!strcmp(argv[i],"time")) { seed = static_cast<unsigned int>(time(nullptr)); } else { seed = static_cast<unsigned int>(atoi(argv[i])); } } else if (!strcmp(argv[i],"-iter")) { if (++i == argc) goto missing; iter = static_cast<unsigned int>(atoi(argv[i])); } else if (!strcmp(argv[i],"-fixprob")) { if (++i == argc) goto missing; fixprob = static_cast<unsigned int>(atoi(argv[i])); } else if (!strcmp(argv[i],"-test")) { if (++i == argc) goto missing; if (argv[i][0] == '^') testpat.emplace_back(MT_FIRST, argv[i] + 1); else if (argv[i][0] == '-') testpat.emplace_back(MT_NOT, argv[i] + 1); else testpat.emplace_back(MT_ANY, argv[i]); } else if (!strcmp(argv[i],"-start")) { if (++i == argc) goto missing; startFrom = argv[i]; } else if (!strcmp(argv[i],"-log")) { log = true; } else if (!strcmp(argv[i],"-stop")) { if (++i == argc) goto missing; if(argv[i][0] == 't') { stop = true; } else if (argv[i][0] == 'f') { stop = false; } } else if (!strcmp(argv[i],"-list")) { list = true; } i++; } return; missing: std::cerr << "Erroneous argument (" << argv[i-1] << ")" << std::endl << " missing parameter" << std::endl; exit(EXIT_FAILURE); }
}
intmain(int argc, char* argv[]) { using namespace Test;#ifdef GECODE_HAS_MTRACE mtrace();#endif
opt.parse(argc, argv);
Base::sort();
if (list) { for (Base* t = Base::tests() ; t != nullptr; t = t->next() ) { std::cout << t->name() << std::endl; } exit(EXIT_SUCCESS); }
Base::rand.seed(opt.seed);
bool started = startFrom == nullptr ? true : false;
for (Base* t = Base::tests() ; t != nullptr; t = t->next() ) { try { if (!started) { if (t->name().find(startFrom) != std::string::npos) started = true; else goto next; } if (!testpat.empty()) { bool match_found = false; bool some_positive = false; for (unsigned int i = 0; i < testpat.size(); ++i) { if (testpat[i].first == MT_NOT) { // Negative pattern if (t->name().find(testpat[i].second) != std::string::npos) goto next; } else { // Positive pattern some_positive = true; if (((testpat[i].first == MT_ANY) && (t->name().find(testpat[i].second) != std::string::npos)) || ((testpat[i].first == MT_FIRST) && (t->name().find(testpat[i].second) == 0))) match_found = true; } } if (some_positive && !match_found) goto next; } std::cout << t->name() << " "; std::cout.flush(); for (unsigned int i = opt.iter; i--; ) { opt.seed = Base::rand.seed(); if (t->run()) { std::cout << '+'; std::cout.flush(); } else { std::cout << "-" << std::endl; report_error(t->name()); if (opt.stop) return 1; } } std::cout << std::endl; } catch (Gecode::Exception& e) { std::cout << "Exception in \"Gecode::" << e.what() << "." << std::endl << "Stopping..." << std::endl; report_error(t->name()); if (opt.stop) return 1; } next:; } return 0;}
std::ostream&operator<<(std::ostream& os, const Test::ind& i) { for (int j=i.l; j--; ) os << " "; return os;}
// STATISTICS: test-core