// $Id$ /* Copyright (C) 2008 Jari Häkkinen, Peter Johansson Copyright (C) 2009, 2010, 2012 Peter Johansson This file is part of the yat library, http://dev.thep.lu.se/yat The yat library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. The yat library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with svndigest. If not, see . */ #include #include "Suite.h" // include from topdir to allow VPATH build #include "test/environment.h" #include "lib/Stats.h" #include "lib/StatsCollection.h" #include "lib/utility.h" #include #include #include #include #include #include #include #include namespace theplu { namespace svndigest { namespace test { Suite::Suite(int argc, char* argv[], bool need_test_repo) : ok_(true) { chdir(abs_builddir()); std::string test_dir = concatenate_path("testSubDir", file_name(argv[0])); mkdir_p(test_dir); chdir(test_dir); out() << "running `" << argv[0] << "' in `" << test_dir << "'\n"; if (need_test_repo) { bool have_test_repo=false; #ifdef HAVE_TEST_REPO have_test_repo=true; #endif if (!have_test_repo) { out() << "Skipping test because test repository is not available\n"; exit (EXIT_SKIP); } update_test_wc(); } } Suite::~Suite(void) { } bool Suite::add(bool b) { ok_ = ok_ && b; return b; } int Suite::exit_status(void) const { int value = EXIT_FAILURE; if (ok()) { value = EXIT_SUCCESS; } out() << "exit status: " << value << "\n"; return value; } bool Suite::ok(void) const { return ok_; } std::ostream& Suite::out(void) const { return std::cout; } bool check_all(const Stats& stats, test::Suite& suite) { for (int lt=0; lt<=LineTypeParser::total; ++lt) { for (svn_revnum_t rev=0; rev<=stats.revision(); ++rev) { size_t all = 0; for (std::set::const_iterator a=stats.authors().begin(); a!=stats.authors().end(); ++a) { all += stats(lt, *a, rev); } if (all!=stats(lt, "all", rev)) { suite.out() << "error: check_all\n" << " lt = " << lt << "\n" << " rev = " << rev << "\n" << " all = " << all << "\n" << " stats = " << stats(lt, "all", rev) << "\n"; for (std::set::const_iterator a=stats.authors().begin(); a!=stats.authors().end(); ++a) { suite.out() << *a << " " << stats(lt, *a, rev) << "\n"; } return false; } } } return true; } bool check_total(const Stats& stats, test::Suite& suite) { for (svn_revnum_t rev=0; rev<=stats.revision(); ++rev) { for (std::set::const_iterator a=stats.authors().begin(); a!=stats.authors().end(); ++a) { unsigned int total=0; for (int lt=0; lt<4; ++lt) { total += stats(lt, *a, rev); } unsigned int total2=stats(LineTypeParser::total, *a, rev); if (total!=total2) { suite.out() << "error: check_total\n" << " author = " << *a << "\n" << " rev = " << rev << "\n" << " sum = " << total << "\n" << " total = " << total2 << "\n"; return false; } } } return true; } bool check_comment_or_copy(const Stats& stats, test::Suite& suite) { for (svn_revnum_t rev=0; rev<=stats.revision(); ++rev) { for (std::set::const_iterator a=stats.authors().begin(); a!=stats.authors().end(); ++a) { unsigned int x=stats(LineTypeParser::comment, *a, rev); x+=stats(LineTypeParser::copyright, *a, rev); unsigned int y=stats(LineTypeParser::comment_or_copy, *a, rev); if (x!=y) { suite.out() << "error: check_total\n" << " author = " << *a << "\n" << " rev = " << rev << "\n" << " comment + copyright = " << x << "\n" << " comment_or_copy = " << y << "\n"; return false; } } } return true; } bool consistent(const StatsCollection& sc, test::Suite& suite) { std::map::const_iterator iter = sc.stats().begin(); while (iter != sc.stats().end()) { if (!consistent(*iter->second, suite)) { suite.out() << "error in " << iter->first << "\n"; return false; } ++iter; } return true; } bool consistent(const Stats& stats, test::Suite& suite) { suite.add(check_all(stats, suite)); suite.add(check_total(stats, suite)); suite.add(check_comment_or_copy(stats, suite)); return true; } bool diff(const std::string& a, const std::string& b) { if (a==b) return false; std::istringstream ssa(a); std::istringstream ssb(b); std::string linea; std::string lineb; while (ssa || ssb) { if (!ssa) { getline(ssb, lineb); std::cout << "+ " << lineb << "\n"; } else if (!ssb) { getline(ssa, linea); std::cout << "- " << lineb << "\n"; } else { getline(ssa, linea); getline(ssb, lineb); if (linea==lineb) std::cout << " " << linea << "\n"; else { std::cout << "- " << linea << "\n"; std::cout << "+ " << lineb << "\n"; } } } return true; } bool equal(const StatsCollection& a, const StatsCollection& b, Suite& suite) { if (a.stats().size() != b.stats().size()) { suite.out() << "size mismatch\n"; return false; } std::map::const_iterator iter1 = a.stats().begin(); std::map::const_iterator iter2 = b.stats().begin(); while (iter1 != a.stats().end()) { if (iter1->first != iter2->first) { suite.out() << "key mismatch\n"; suite.out() << iter1->first << " vs " << iter2->first << "\n"; return false; } if (!equal(*iter1->second, *iter2->second, suite)) { suite.out() << "error in " << iter1->first << "\n"; return false; } ++iter1; ++iter2; } return true; } bool equal(const Stats& a, const Stats& b, test::Suite& suite) { if (a.authors() != b.authors()) { suite.out() << "authors are not equal\n"; suite.out() << "lhs:\n"; std::copy(a.authors().begin(), a.authors().end(), std::ostream_iterator(suite.out(), "\n")); suite.out() << "rhs:\n"; std::copy(b.authors().begin(), b.authors().end(), std::ostream_iterator(suite.out(), "\n")); return false; } if (a.revision() != b.revision()) { suite.out() << "revision mismatch\n"; return false; } std::vector authors; authors.reserve(a.authors().size()+1); std::copy(a.authors().begin(), a.authors().end(), std::back_inserter(authors)); authors.push_back("all"); for (int linetype=0; linetype <= LineTypeParser::total; ++linetype) { for (std::vector::const_iterator author=authors.begin(); author!=authors.end(); ++author) { for (svn_revnum_t rev=0; rev