source: trunk/test/Suite.cc @ 1435

Last change on this file since 1435 was 1435, checked in by Jari Häkkinen, 10 years ago

Removed unused cassert and cerrno includes.

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