source: trunk/test/utility_test.cc @ 2209

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

added an errno exception class (fixes #616) and implementing exception classes in source file (rather than inlining).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.2 KB
Line 
1// $Id: utility_test.cc 2209 2010-03-05 13:15:39Z peter $
2
3/*
4  Copyright (C) 2006 Jari Häkkinen, Markus Ringnér
5  Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson
6  Copyright (C) 2009, 2010 Peter Johansson
7
8  This file is part of the yat library, http://dev.thep.lu.se/yat
9
10  The yat library is free software; you can redistribute it and/or
11  modify it under the terms of the GNU General Public License as
12  published by the Free Software Foundation; either version 3 of the
13  License, or (at your option) any later version.
14
15  The yat library is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  General Public License for more details.
19
20  You should have received a copy of the GNU General Public License
21  along with yat. If not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "Suite.h"
25
26#include "yat/utility/Exception.h"
27#include "yat/utility/Matrix.h"
28#include "yat/utility/utility.h"
29#include "yat/utility/Vector.h"
30#include "yat/utility/VectorConstView.h"
31#include "yat/utility/sort_index.h"
32#include "yat/utility/stl_utility.h"
33
34#include <boost/concept_archetype.hpp>
35
36#include <cerrno>
37#include <fstream>
38#include <iostream>
39#include <limits>
40#include <list>
41#include <map>
42#include <string>
43#include <vector>
44
45using namespace theplu::yat;
46void test_errno_error(test::Suite& suite);
47void test_errno_error_func(void);
48void test_get_map(test::Suite&);
49void test_inverse(test::Suite&);
50
51template<typename InputIterator, typename Key>
52void test_inverse_validate(InputIterator first, InputIterator last,
53                           const std::map<Key, std::vector<size_t> >& m,
54                           test::Suite& suite);
55template<typename InputIterator, typename Key>
56void test_inverse_validate(InputIterator first,
57                           const std::multimap<Key, size_t>& m,
58                           test::Suite& suite);
59
60void test_sort_index(test::Suite& suite);
61void test_less_nan(test::Suite& suite);
62
63int main(int argc, char* argv[])
64{ 
65  using namespace theplu::yat;
66  test::Suite suite(argc, argv);
67  suite.err() << "testing utility ... " << std::endl;
68
69  // test float/double
70  std::string s("1.2");
71  if (!utility::is<double>(s)){
72    suite.add(false);
73  }
74  else if (!utility::is<float>(s)) {
75    suite.add(false);
76  }
77  else if (utility::is<int>(s)) {
78    suite.add(false);
79  }
80  else if (utility::is_nan(s)) {
81    suite.add(false);
82  }
83
84  // test int
85  s="23";
86  if (!utility::is<double>(s)){
87    suite.add(false);
88  }
89  else if (!utility::is<float>(s)) {
90    suite.add(false);
91  }
92  else if (!utility::is<int>(s)) {
93    suite.add(false);
94  }
95  else if (utility::is_nan(s)) {
96    suite.add(false);
97  }
98
99  // test nan
100  s=" nAn  ";
101  if (!utility::is<double>(s)){
102    suite.add(false);
103    suite.err() << "error: " << s << " is a double\n";
104  }
105  /* we don't require NaN for float and int
106  else if (!utility::is_float(s)) {
107    suite.add(false);
108    suite.err() << "error: " << s << " is a float\n";
109  }
110  else if (!utility::is_int(s)) {
111    suite.add(false);
112    suite.err() << "error: " << s << " is a int\n";
113  }
114  */
115  else if (!utility::is_nan(s)) {
116    suite.add(false);
117    suite.err() << "error: " << s << " is nan\n";
118
119  }
120 
121  // testing trailing values
122  s=" 23 23   ";
123  if (utility::is<double>(s)){
124    suite.add(false);
125  }
126  else if (utility::is<float>(s)) {
127    suite.add(false);
128  }
129  else if (utility::is<int>(s)) {
130    suite.add(false);
131  }
132  else if (utility::is_nan(s)) {
133    suite.add(false);
134  }
135
136  if (utility::convert<double>("1.23")!=1.23)
137    suite.add(false);
138  utility::convert<double>("-inf");
139  utility::convert<double>("inf");
140  utility::convert<double>("NaN");
141
142  if (!suite.add(utility::is<double>("-inf")))
143    suite.err() << "is<double>(\"-inf\") should return true\n";
144  if (!suite.add(utility::is<double>("inf")))
145    suite.err() << "is<double>(\"inf\") should return true\n";
146  if (!suite.add(utility::is<double>("NaN")))
147    suite.err() << "is<double>(\"NaN\") should return true\n";
148  if (!suite.add(utility::is<double>("1.23")))
149    suite.err() << "is<double>(\"1.23\") should return true\n";
150  if (!suite.add(!utility::is<double>("1.23.2")))
151    suite.err() << "is<double>(\"1.23.2\") should return false\n";
152  if (!suite.add(!utility::is<int>("1.23")))
153    suite.err() << "is<int>(\"1.23\") should return false\n";
154  if (!suite.add(!utility::is<int>("")))
155    suite.err() << "is<int>(\"\") should return false\n";
156
157  {
158    utility::Log<long double> f;
159    utility::Log<double> f2(1.3);
160    f(2.0);
161    utility::Exp<double> e;
162    e(3.2);
163  }
164
165  test_get_map(suite);
166  test_inverse(suite);
167  test_sort_index(suite);
168  test_less_nan(suite);
169  test_errno_error(suite);
170
171  return suite.return_value();
172}
173
174
175void test_errno_error_func(void)
176{
177  errno=1;
178  throw utility::errno_error("");
179}
180
181
182void test_errno_error(test::Suite& suite)
183{
184  suite.out() << "testing errno_error\n";
185  try {
186    test_errno_error_func();
187  }
188  catch ( utility::errno_error& e) {
189    suite.out() << "catching expected exception with what():\n";
190    suite.out() << e.what() << "\n";
191    return;
192  }
193  suite.err() << "error: expected thrown exception\n";
194  suite.add(false);
195}
196
197
198void test_get_map(test::Suite& suite)
199{
200  std::map<std::string, int> m;
201  m["one"] = 1;
202  m["two"] = 2;
203  const std::map<std::string, int> m2(m);
204  int i = utility::get(m2, static_cast<std::string>("one"));
205  i = 0; // avoid compiler warning
206  try {
207    utility::get(m2, static_cast<std::string>("three"));
208    suite.add(false);
209  }
210  catch (std::runtime_error& e) {
211    suite.out() << "expected exception thrown with what() = " 
212                << e.what() << "\n";
213  }
214}
215
216void test_less_nan(test::Suite& suite)
217{
218  bool prior_ok=suite.ok();
219  utility::less_nan<double> f;
220  suite.add(f(2.7,3.14));
221  suite.add(!f(2.7,-3.14));
222  suite.add(!f(2.7,2.7));
223  suite.add(f(3.14, std::numeric_limits<double>::quiet_NaN()));
224  suite.add(!f(std::numeric_limits<double>::quiet_NaN(), 2.7));
225  suite.add(!f(std::numeric_limits<double>::quiet_NaN(),
226               std::numeric_limits<double>::quiet_NaN()));
227  utility::less_nan<utility::DataWeight> fw;
228  suite.add(fw(utility::DataWeight(2), utility::DataWeight(3)));
229
230  bool post_ok=suite.ok();
231  if (!post_ok && prior_ok)
232    suite.err() << "test_less_nan failed\n";
233}
234
235
236void test_inverse(test::Suite& suite)
237{
238  suite.err() << "Testing inverse\n";
239  std::vector<std::string> vec;
240  vec.push_back("No");
241  vec.push_back("one");
242  vec.push_back("shall");
243  vec.push_back("be");
244  vec.push_back("subjected");
245  std::map<std::string, std::vector<size_t> > map;
246  utility::inverse(vec.begin(), vec.end(), map);
247  test_inverse_validate(vec.begin(), vec.end(), map, suite);
248  utility::inverse(vec.begin()+1, vec.end(), map);
249  test_inverse_validate(vec.begin()+1, vec.end(), map, suite);
250  const std::vector<std::string> vec2(vec);
251  utility::inverse(vec2.begin(), vec2.end(), map);
252  test_inverse_validate(vec2.begin(), vec2.end(), map, suite);
253  std::multimap<std::string, size_t> mmap;
254  utility::inverse(vec.begin(), vec.end(), mmap);
255  test_inverse_validate(vec.begin(), mmap, suite);
256  utility::inverse(vec.begin()+1, vec.end(), mmap);
257  test_inverse_validate(vec.begin()+1, mmap, suite);
258  // do not run compile tests
259  if (false) {
260    std::map<std::string, std::vector<size_t> > m;
261    boost::input_iterator_archetype<std::string> start;
262    boost::input_iterator_archetype<std::string> end;
263    utility::inverse(start, end, m);
264    std::map<std::string, std::vector<size_t>, std::greater<std::string> > m2;
265    utility::inverse(start, end, m2);
266    std::multimap<std::string, size_t> m3;
267    utility::inverse(start, end, m3);
268    std::multimap<std::string, size_t, std::greater<std::string> > m4;
269    utility::inverse(start, end, m4);
270  }
271}
272
273
274template<typename InputIterator, typename Key>
275void test_inverse_validate(InputIterator first, InputIterator last,
276                           const std::map<Key, std::vector<size_t> >& m,
277                           test::Suite& suite)
278{
279  typedef typename std::map<Key, std::vector<size_t> >::const_iterator Iter;
280  for ( InputIterator iter=first; iter != last; ++iter) {
281    Iter map_iter = m.find(*iter);
282    if (!suite.add(map_iter!=m.end())) {
283      suite.err() << "test_inverse_validate() failed\n";
284      suite.err() << "  could not find: " << *first << " in map m\n";
285    }
286    for (size_t i=0; i<map_iter->second.size(); ++i)
287      if (!suite.add(map_iter->second[i] ==
288                     static_cast<size_t>(distance(first, iter))) ) {
289        suite.err() << "test_inverse_validate() failed\n";
290        suite.err() << "  comparing: " << map_iter->second[i] 
291                    << " and " << distance(first, iter) 
292                    << " expected them to be equal\n";
293      }
294  }
295}
296
297
298template<typename InputIterator, typename Key>
299void test_inverse_validate(InputIterator first,
300                           const std::multimap<Key, size_t>& m,
301                           test::Suite& suite)
302{
303  for (typename std::multimap<Key, size_t>::const_iterator iter=m.begin();
304       iter!=m.end(); ++iter) {
305    suite.add(*(first + iter->second) == iter->first);
306  }
307 
308}
309
310void test_sort_index(test::Suite& suite)
311{
312  suite.err() << "testing sort_index" << std::endl;
313  utility::Vector a(10);
314  for (size_t i=0; i<a.size(); ++i)
315    a(i) = std::pow(i-4.2,2);
316  std::vector<size_t> vec;
317  utility::sort_index(vec, a);
318
319  std::vector<size_t> vec2;
320  utility::sort_index(a.begin(), a.end(), vec2);
321  if (vec.size()==vec2.size()) {
322    if (!suite.equal_range(vec.begin(), vec.end(), vec2.begin())) {
323      suite.add(false);
324    }
325  }
326  else {
327    suite.add(false);
328    suite.err() << "size mismatch: vec.size()=" << vec.size() 
329                << "vec2.size()=" << vec2.size() << "\n"; 
330  }
331  const utility::VectorConstView b(a, 0, 5, 2);
332
333  std::vector<size_t> vec3;
334  utility::sort_index(vec3, b);
335  std::vector<size_t> vec4;
336  utility::sort_index(b.begin(), b.end(), vec4);
337  if (vec3.size()!=vec4.size()) {
338    suite.add(false);
339    suite.err() << "size mismatch: vec3.size()=" << vec3.size() 
340                << " vec4.size()=" << vec4.size() << "\n"; 
341  }
342  else {
343    if (!suite.equal_range(vec3.begin(), vec3.end(), vec4.begin())){
344      suite.add(false);
345    }
346  }
347
348  std::list<double> list;
349  for (size_t i=0; i<a.size(); ++i)
350    list.push_back(a(i));
351  std::vector<size_t> vec5;
352  utility::sort_index(list.begin(), list.end(), vec5);
353  if (vec.size()!=vec5.size()) {
354    suite.add(false);
355    suite.err() << "size mismatch: vec.size()=" << vec.size() 
356                << " vec5.size()=" << vec5.size() << "\n"; 
357  }
358  else {
359    if (!suite.equal_range(vec.begin(), vec.end(), vec5.begin())){
360      suite.add(false);
361    }
362  }
363
364  // do not run compiler tests
365  if (false) {
366    std::vector<size_t> vec;
367    utility::sort_index(boost::forward_iterator_archetype<double>(),
368                        boost::forward_iterator_archetype<double>(),
369                        vec);
370  }
371}
Note: See TracBrowser for help on using the repository browser.