source: trunk/test/Suite.cc

Last change on this file was 1525, checked in by Peter Johansson, 9 years ago

replace recursive Makefile with one single Makefile. Keeping multiple Makefile.ams which are included into main Makefile.am.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.3 KB
Line 
1// $Id: Suite.cc 1525 2012-10-01 06:31:07Z peter $
2
3/*
4  Copyright (C) 2008 Jari Häkkinen, Peter Johansson
5  Copyright (C) 2009, 2010, 2012 Peter Johansson
6
7  This file is part of the yat library, http://dev.thep.lu.se/yat
8
9  The yat library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 3 of the
12  License, or (at your option) any later version.
13
14  The yat library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with svndigest. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include <config.h>
24
25#include "Suite.h"
26// include from topdir to allow VPATH build
27#include "test/environment.h"
28
29#include "lib/Stats.h"
30#include "lib/StatsCollection.h"
31#include "lib/utility.h"
32
33#include <algorithm>
34#include <cstdlib>
35#include <fstream>
36#include <iostream>
37#include <iterator>
38#include <sstream>
39#include <stdexcept>
40#include <string>
41
42namespace theplu {
43namespace svndigest {
44namespace test {
45
46  Suite::Suite(int argc, char* argv[], bool need_test_repo)
47    : ok_(true)
48  {
49    chdir(abs_builddir());
50    std::string test_dir = concatenate_path("testSubDir", file_name(argv[0]));
51    mkdir_p(test_dir);
52    chdir(test_dir);
53    out() << "running `" << argv[0] << "' in `" << test_dir << "'\n";
54    if (need_test_repo) {
55      bool have_test_repo=false;
56      #ifdef HAVE_TEST_REPO
57      have_test_repo=true;
58      #endif
59      if (!have_test_repo) {
60        out() << "Skipping test because test repository is not available\n";
61        exit (EXIT_SKIP);
62      }
63      update_test_wc();
64    }
65
66  }
67
68
69  Suite::~Suite(void)
70  {
71  }
72
73 
74  bool Suite::add(bool b)
75  {
76    ok_ = ok_ && b;
77    return b;
78  }
79
80
81  int Suite::exit_status(void) const
82  {
83    int value = EXIT_FAILURE;
84    if (ok()) {
85      value = EXIT_SUCCESS; 
86    }
87    out() << "exit status: " << value << "\n";
88    return value;
89  }
90
91
92  bool Suite::ok(void) const
93  {
94    return ok_;
95  }
96
97
98  std::ostream& Suite::out(void) const
99  {
100    return std::cout;
101  }
102
103
104  bool check_all(const Stats& stats, test::Suite& suite)
105  {
106    for (int lt=0; lt<=LineTypeParser::total; ++lt) {
107      for (svn_revnum_t rev=0; rev<=stats.revision(); ++rev) {
108        size_t all = 0;
109        for (std::set<std::string>::const_iterator a=stats.authors().begin();
110             a!=stats.authors().end(); ++a) {
111          all += stats(lt, *a, rev);
112        }
113        if (all!=stats(lt, "all", rev)) {
114          suite.out() << "error: check_all\n"
115                      << " lt = " << lt << "\n"
116                      << " rev = " << rev << "\n"
117                      << " all = " << all << "\n"
118                      << " stats = " << stats(lt, "all", rev) << "\n";
119          for (std::set<std::string>::const_iterator a=stats.authors().begin();
120               a!=stats.authors().end(); ++a) {
121            suite.out() << *a << " " << stats(lt, *a, rev) << "\n";
122          }
123          return false;
124        }
125      }
126    }
127    return true;
128  }
129 
130
131  bool check_total(const Stats& stats, test::Suite& suite)
132  {
133    for (svn_revnum_t rev=0; rev<=stats.revision(); ++rev) {
134      for (std::set<std::string>::const_iterator a=stats.authors().begin();
135           a!=stats.authors().end(); ++a) {
136        unsigned int total=0;
137        for (int lt=0; lt<4; ++lt) {
138          total += stats(lt, *a, rev);
139        }
140        unsigned int total2=stats(LineTypeParser::total, *a, rev);
141       
142        if (total!=total2) {
143          suite.out() << "error: check_total\n"
144                      << " author = " << *a << "\n"
145                      << " rev = " << rev << "\n"
146                      << " sum = " << total << "\n"
147                      << " total = " << total2 << "\n";
148          return false;
149        }
150      }
151    }
152    return true;
153  }
154 
155
156  bool check_comment_or_copy(const Stats& stats, test::Suite& suite)
157  {
158    for (svn_revnum_t rev=0; rev<=stats.revision(); ++rev) {
159      for (std::set<std::string>::const_iterator a=stats.authors().begin();
160           a!=stats.authors().end(); ++a) {
161        unsigned int x=stats(LineTypeParser::comment, *a, rev);
162        x+=stats(LineTypeParser::copyright, *a, rev);
163        unsigned int y=stats(LineTypeParser::comment_or_copy, *a, rev);
164       
165        if (x!=y) {
166          suite.out() << "error: check_total\n"
167                      << " author = " << *a << "\n"
168                      << " rev = " << rev << "\n"
169                      << " comment + copyright = " << x << "\n"
170                      << " comment_or_copy = " << y << "\n";
171          return false;
172        }
173      }
174    }
175    return true;
176  }
177
178
179  bool consistent(const StatsCollection& sc, test::Suite& suite)
180  {
181    std::map<std::string, Stats*>::const_iterator iter = sc.stats().begin();
182    while (iter != sc.stats().end()) {
183      if (!consistent(*iter->second, suite)) {
184        suite.out() << "error in " << iter->first << "\n";
185        return false;
186      }
187      ++iter;
188    }
189    return true;
190  }
191
192
193  bool consistent(const Stats& stats, test::Suite& suite)
194  {
195    suite.add(check_all(stats, suite));
196    suite.add(check_total(stats, suite));
197    suite.add(check_comment_or_copy(stats, suite));
198    return true;
199  }
200
201
202  bool diff(const std::string& a, const std::string& b)
203  {
204    if (a==b)
205      return false;
206
207    std::istringstream ssa(a);
208    std::istringstream ssb(b);
209
210    std::string linea;
211    std::string lineb;
212    while (ssa || ssb) {
213      if (!ssa) {
214        getline(ssb, lineb);
215        std::cout << "+ " << lineb << "\n";
216      }
217      else if (!ssb) {
218        getline(ssa, linea);
219        std::cout << "- " << lineb << "\n";
220      }
221      else {
222        getline(ssa, linea);
223        getline(ssb, lineb);
224        if (linea==lineb)
225          std::cout << "  " << linea << "\n";
226        else {
227          std::cout << "- " << linea << "\n";
228          std::cout << "+ " << lineb << "\n";
229        }
230      }
231    }
232    return true;
233  }
234
235
236  bool equal(const StatsCollection& a, const StatsCollection& b, 
237             Suite& suite)
238  {
239    if (a.stats().size() != b.stats().size()) {
240      suite.out() << "size mismatch\n";
241      return false;
242    }
243    std::map<std::string, Stats*>::const_iterator iter1 = a.stats().begin();
244    std::map<std::string, Stats*>::const_iterator iter2 = b.stats().begin();
245    while (iter1 != a.stats().end()) {
246      if (iter1->first != iter2->first) {
247        suite.out() << "key mismatch\n";
248        suite.out() << iter1->first << " vs " << iter2->first << "\n";
249        return false;
250      }
251      if (!equal(*iter1->second, *iter2->second, suite)) {
252        suite.out() << "error in " << iter1->first << "\n";
253        return false;
254      }
255      ++iter1;
256      ++iter2;
257    }
258    return true;
259  }
260 
261
262  bool equal(const Stats& a, const Stats& b, test::Suite& suite)
263  {
264    if (a.authors() != b.authors()) {
265      suite.out() << "authors are not equal\n";
266      suite.out() << "lhs:\n";
267      std::copy(a.authors().begin(), a.authors().end(), 
268                std::ostream_iterator<std::string>(suite.out(), "\n"));
269      suite.out() << "rhs:\n";
270      std::copy(b.authors().begin(), b.authors().end(), 
271                std::ostream_iterator<std::string>(suite.out(), "\n"));
272      return false;
273    }
274    if (a.revision() != b.revision()) {
275      suite.out() << "revision mismatch\n";
276      return false;
277    }
278    std::vector<std::string> authors;
279    authors.reserve(a.authors().size()+1);
280    std::copy(a.authors().begin(), a.authors().end(), 
281              std::back_inserter(authors));
282    authors.push_back("all");
283    for (int linetype=0; linetype <= LineTypeParser::total; ++linetype) {
284      for (std::vector<std::string>::const_iterator author=authors.begin(); 
285           author!=authors.end(); ++author) {
286        for (svn_revnum_t rev=0; rev<a.revision(); ++rev) {
287          size_t ax = a(linetype, *author, rev);
288          size_t bx = b(linetype, *author, rev);
289          if (ax != bx) {
290            suite.out() << "error: linetype: " << linetype
291                        << " author " << *author 
292                        << " rev " << rev << "\n"
293                        << "   a: " << ax << "\n"
294                        << "   b: " << bx << "\n";
295            return false;
296          }
297        }
298      }
299    }
300    return true;
301  }
302
303
304  void Suite::update_test_wc(void) const
305  {
306    std::string cmd = abs_builddir()+"/svn_update.sh";
307    try {
308      system(cmd, 0);
309    }
310    catch (std::runtime_error& e) {
311      out() << e.what() << "\n";
312      exit (1);
313    }
314  }
315
316
317  bool Suite::verbose(void) const
318  {
319    // we are always verbose nowadays
320    return true;
321  }
322
323
324  std::string filename(const std::string& path)
325  {
326    return abs_builddir()+"/"+path;
327  }
328
329
330  std::string src_filename(const std::string& path)
331  {
332    return abs_srcdir()+"/"+path;
333  }
334
335
336  void Suite::system(const std::string& cmd, int ret) const
337  {
338    int status = ::system(cmd.c_str());
339    out() << "call: '" << cmd << "'\n";
340    if (status==ret)
341      return;
342    std::stringstream ss;
343    ss << "error: status: " << status;
344    throw std::runtime_error(ss.str());
345  }
346}}}
Note: See TracBrowser for help on using the repository browser.