// $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