source: trunk/test/Suite.cc

Last change on this file was 1525, checked in by Peter Johansson, 10 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.