source: trunk/test/Suite.cc @ 1207

Last change on this file since 1207 was 1207, checked in by Peter Johansson, 12 years ago

new function 'diff' to compare two strings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.9 KB
Line 
1// $Id: Suite.cc 1207 2010-10-07 03:25:31Z peter $
2
3/*
4  Copyright (C) 2008 Jari Häkkinen, Peter Johansson
5  Copyright (C) 2009, 2010 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 "environment.h"
27
28#include "lib/Stats.h"
29#include "lib/StatsCollection.h"
30#include "lib/utility.h"
31
32#include <algorithm>
33#include <cassert>
34#include <fstream>
35#include <iostream>
36#include <iterator>
37#include <string>
38
39namespace theplu {
40namespace svndigest {
41namespace test {
42
43  Suite::Suite(int argc, char* argv[], bool need_test_repo)
44    : ok_(true)
45  {
46    chdir(abs_builddir());
47    std::string test_dir = concatenate_path("testSubDir", file_name(argv[0]));
48    mkdir_p(test_dir);
49    chdir(test_dir);
50    out() << "running `" << argv[0] << "' in `" << test_dir << "'\n";
51    if (need_test_repo) {
52      bool have_test_repo=false;
53      #ifdef HAVE_TEST_REPO
54      have_test_repo=true;
55      #endif
56      if (!have_test_repo) {
57        out() << "Skipping test because test repository is not available\n";
58        exit (EXIT_SKIP);
59      }
60      update_test_wc();
61    }
62
63  }
64
65
66  Suite::~Suite(void)
67  {
68  }
69
70 
71  bool Suite::add(bool b)
72  {
73    ok_ = ok_ && b;
74    return b;
75  }
76
77
78  int Suite::exit_status(void) const
79  {
80    int value = EXIT_FAILURE;
81    if (ok()) {
82      value = EXIT_SUCCESS; 
83    }
84    out() << "exit status: " << value << "\n";
85    return value;
86  }
87
88
89  bool Suite::ok(void) const
90  {
91    return ok_;
92  }
93
94
95  std::ostream& Suite::out(void) const
96  {
97    return std::cout;
98  }
99
100
101  bool check_all(const Stats& stats, test::Suite& suite)
102  {
103    for (int lt=0; lt<=LineTypeParser::total; ++lt) {
104      for (svn_revnum_t rev=0; rev<=stats.revision(); ++rev) {
105        size_t all = 0;
106        for (std::set<std::string>::const_iterator a=stats.authors().begin();
107             a!=stats.authors().end(); ++a) {
108          all += stats(lt, *a, rev);
109        }
110        if (all!=stats(lt, "all", rev)) {
111          suite.out() << "error: check_all\n"
112                      << " lt = " << lt << "\n"
113                      << " rev = " << rev << "\n"
114                      << " all = " << all << "\n"
115                      << " stats = " << stats(lt, "all", rev) << "\n";
116          for (std::set<std::string>::const_iterator a=stats.authors().begin();
117               a!=stats.authors().end(); ++a) {
118            suite.out() << *a << " " << stats(lt, *a, rev) << "\n";
119          }
120          return false;
121        }
122      }
123    }
124    return true;
125  }
126 
127
128  bool check_total(const Stats& stats, test::Suite& suite)
129  {
130    for (svn_revnum_t rev=0; rev<=stats.revision(); ++rev) {
131      for (std::set<std::string>::const_iterator a=stats.authors().begin();
132           a!=stats.authors().end(); ++a) {
133        unsigned int total=0;
134        for (int lt=0; lt<4; ++lt) {
135          total += stats(lt, *a, rev);
136        }
137        unsigned int total2=stats(LineTypeParser::total, *a, rev);
138       
139        if (total!=total2) {
140          suite.out() << "error: check_total\n"
141                      << " author = " << *a << "\n"
142                      << " rev = " << rev << "\n"
143                      << " sum = " << total << "\n"
144                      << " total = " << total2 << "\n";
145          return false;
146        }
147      }
148    }
149    return true;
150  }
151 
152
153  bool check_comment_or_copy(const Stats& stats, test::Suite& suite)
154  {
155    for (svn_revnum_t rev=0; rev<=stats.revision(); ++rev) {
156      for (std::set<std::string>::const_iterator a=stats.authors().begin();
157           a!=stats.authors().end(); ++a) {
158        unsigned int x=stats(LineTypeParser::comment, *a, rev);
159        x+=stats(LineTypeParser::copyright, *a, rev);
160        unsigned int y=stats(LineTypeParser::comment_or_copy, *a, rev);
161       
162        if (x!=y) {
163          suite.out() << "error: check_total\n"
164                      << " author = " << *a << "\n"
165                      << " rev = " << rev << "\n"
166                      << " comment + copyright = " << x << "\n"
167                      << " comment_or_copy = " << y << "\n";
168          return false;
169        }
170      }
171    }
172    return true;
173  }
174
175
176  bool consistent(const StatsCollection& sc, test::Suite& suite)
177  {
178    std::map<std::string, Stats*>::const_iterator iter = sc.stats().begin();
179    while (iter != sc.stats().end()) {
180      if (!consistent(*iter->second, suite)) {
181        suite.out() << "error in " << iter->first << "\n";
182        return false;
183      }
184      ++iter;
185    }
186    return true;
187  }
188
189
190  bool consistent(const Stats& stats, test::Suite& suite)
191  {
192    suite.add(check_all(stats, suite));
193    suite.add(check_total(stats, suite));
194    suite.add(check_comment_or_copy(stats, suite));
195    return true;
196  }
197
198
199  bool diff(const std::string& a, const std::string& b)
200  {
201    if (a==b)
202      return false;
203
204    std::istringstream ssa(a);
205    std::istringstream ssb(b);
206
207    std::string linea;
208    std::string lineb;
209    while (ssa || ssb) {
210      if (!ssa) {
211        getline(ssb, lineb);
212        std::cout << "+ " << lineb << "\n";
213      }
214      else if (!ssb) {
215        getline(ssa, linea);
216        std::cout << "- " << lineb << "\n";
217      }
218      else {
219        getline(ssa, linea);
220        getline(ssb, lineb);
221        if (linea==lineb)
222          std::cout << "  " << linea << "\n";
223        else {
224          std::cout << "- " << linea << "\n";
225          std::cout << "+ " << lineb << "\n";
226        }
227      }
228    }
229    return true;
230  }
231
232
233  bool equal(const StatsCollection& a, const StatsCollection& b, 
234             Suite& suite)
235  {
236    if (a.stats().size() != b.stats().size()) {
237      suite.out() << "size mismatch\n";
238      return false;
239    }
240    std::map<std::string, Stats*>::const_iterator iter1 = a.stats().begin();
241    std::map<std::string, Stats*>::const_iterator iter2 = b.stats().begin();
242    while (iter1 != a.stats().end()) {
243      if (iter1->first != iter2->first) {
244        suite.out() << "key mismatch\n";
245        suite.out() << iter1->first << " vs " << iter2->first << "\n";
246        return false;
247      }
248      if (!equal(*iter1->second, *iter2->second, suite)) {
249        suite.out() << "error in " << iter1->first << "\n";
250        return false;
251      }
252      ++iter1;
253      ++iter2;
254    }
255    return true;
256  }
257 
258
259  bool equal(const Stats& a, const Stats& b, test::Suite& suite)
260  {
261    if (a.authors() != b.authors()) {
262      suite.out() << "authors are not equal\n";
263      suite.out() << "lhs:\n";
264      std::copy(a.authors().begin(), a.authors().end(), 
265                std::ostream_iterator<std::string>(suite.out(), "\n"));
266      suite.out() << "rhs:\n";
267      std::copy(b.authors().begin(), b.authors().end(), 
268                std::ostream_iterator<std::string>(suite.out(), "\n"));
269      return false;
270    }
271    if (a.revision() != b.revision()) {
272      suite.out() << "revision mismatch\n";
273      return false;
274    }
275    std::vector<std::string> authors;
276    authors.reserve(a.authors().size()+1);
277    std::copy(a.authors().begin(), a.authors().end(), 
278              std::back_inserter(authors));
279    authors.push_back("all");
280    for (int linetype=0; linetype <= LineTypeParser::total; ++linetype) {
281      for (std::vector<std::string>::const_iterator author=authors.begin(); 
282           author!=authors.end(); ++author) {
283        for (svn_revnum_t rev=0; rev<a.revision(); ++rev) {
284          size_t ax = a(linetype, *author, rev);
285          size_t bx = b(linetype, *author, rev);
286          if (ax != bx) {
287            suite.out() << "error: linetype: " << linetype
288                        << " author " << *author 
289                        << " rev " << rev << "\n"
290                        << "   a: " << ax << "\n"
291                        << "   b: " << bx << "\n";
292            return false;
293          }
294        }
295      }
296    }
297    return true;
298  }
299
300
301  void Suite::update_test_wc(void) const
302  {
303    std::string cmd = abs_builddir()+"/svn_update.sh";
304    out() << cmd << std::endl;
305    int status = system(cmd.c_str());
306    if (status) {
307      out() << "failed with status: " << status << std::endl;
308      exit (1);
309    }
310  }
311
312
313  bool Suite::verbose(void) const
314  {
315    // we are always verbose nowadays
316    return true;
317  }
318
319
320  std::string filename(const std::string& path)
321  {
322    return abs_builddir()+"/"+path;
323  }
324
325
326  std::string src_filename(const std::string& path)
327  {
328    return abs_srcdir()+"/"+path;
329  }
330
331
332}}}
Note: See TracBrowser for help on using the repository browser.