Removed old map tests
[libcds.git] / tests / cppunit / cppunit_mini.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8     
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
29 */
30
31 /*
32  * Copyright (c) 2003, 2004
33  * Zdenek Nemec
34  *
35  * This material is provided "as is", with absolutely no warranty expressed
36  * or implied. Any use is at your own risk.
37  *
38  * Permission to use or copy this software for any purpose is hereby granted
39  * without fee, provided the above notices are retained on all copies.
40  * Permission to modify the code and to distribute modified code is granted,
41  * provided the above notices are retained, and a notice that the code was
42  * modified is included with the above copyright notice.
43  *
44  */
45
46 /*
47     Partially changed and expanded by Maxim Khiszinsky (cds), 2009
48 */
49
50 /* $Id$ */
51
52 #ifndef CDS_CPPUNIT_MPFR_H_
53 #define CDS_CPPUNIT_MPFR_H_
54
55 #include <string.h>
56 #include <sstream>
57 #include <iostream>
58 #include <vector>
59 #include <string>
60 #include <map>
61 #include <random>
62
63 #include <assert.h>
64
65 #include <boost/lexical_cast.hpp>
66
67 namespace CppUnitMini
68 {
69   class Reporter {
70   public:
71     virtual ~Reporter() {}
72     virtual void error(const char * /*macroName*/, const char * /*in_macro*/, const char * /*in_file*/, int /*in_line*/) {}
73     virtual void message( const char * /*msg*/ ) {}
74     virtual void progress( const char * /*in_className*/, const char * /*in_testName*/, bool /*ignored*/, bool /* explicit */) {}
75     virtual void end() {}
76     virtual void printSummary() {}
77   };
78
79   struct TestCfg
80   {
81       typedef std::map< std::string, std::string >  cfg_map;
82       cfg_map    m_Cfg ; // map param_name => value
83
84       template <typename T>
85       T get( const std::string& strParamName, T defVal ) const
86       {
87           cfg_map::const_iterator it = m_Cfg.find( strParamName );
88           if ( it == m_Cfg.end() )
89               return defVal ; // param not found -> returns default value
90           try {
91               return boost::lexical_cast< T >( it->second );
92           }
93           catch ( boost::bad_lexical_cast& ex )
94           {
95               std::cerr << "bad_lexical_cast encountered while getting parameter "
96                   << strParamName << "=" << it->second
97                   << ": " << ex.what()
98                   << std::endl
99 ;
100           }
101           return defVal;
102       }
103
104       template <typename T>
105       T get( const char * pszParamName, T defVal ) const
106       {
107           return get( std::string( pszParamName ), defVal );
108       }
109
110       int getInt( const char * pszParamName, int nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
111       unsigned int getUInt( const char * pszParamName, unsigned int nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
112       long getLong( const char * pszParamName, long nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
113       unsigned long getULong( const char * pszParamName, unsigned long nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
114       size_t getSizeT( const char * pszParamName, size_t nDefVal = 0 ) const
115       {
116           return static_cast<size_t>( getULong( pszParamName, static_cast<unsigned long>(nDefVal)));
117       }
118
119       bool getBool( const char * pszParamName, bool bDefVal = false ) const
120       {
121           std::string strParamName( pszParamName );
122           cfg_map::const_iterator it = m_Cfg.find( strParamName );
123           if ( it == m_Cfg.end() )
124               return bDefVal ; // param not found -> returns default value
125           try {
126               return boost::lexical_cast< int >( it->second ) != 0;
127           }
128           catch ( boost::bad_lexical_cast& ex )
129           {
130               std::cerr << "bad_lexical_cast encountered while getting parameter "
131                   << strParamName << "=" << it->second
132                   << ": " << ex.what()
133                   << std::endl;
134           }
135           return bDefVal;
136       }
137
138   };
139
140   class Config {
141       std::map< std::string, TestCfg>  m_Cfg;
142
143   public:
144       Config() {}
145
146       void load( const char * fileName );
147
148       TestCfg& get( const std::string& strTestName )
149       {
150           return m_Cfg[ strTestName ];
151       }
152   };
153
154   class TestFixture {
155   public:
156     virtual ~TestFixture() {}
157
158     //! \brief Set up context before running a test.
159     virtual void setUp() {}
160
161     //! Clean up after the test run.
162     virtual void tearDown() {}
163   };
164
165   class TestCase : public TestFixture {
166   public:
167     TestCase()
168     {
169         registerTestCase(this);
170     }
171
172     void setUp() { m_failed = false; }
173     static int run(Reporter *in_reporter = 0, const char *in_testName = "", bool invert = false);
174     int numErrors() { return m_numErrors; }
175     static void registerTestCase(TestCase *in_testCase);
176
177     static TestCase * current_test()
178     {
179         assert( m_pCurTestCase );
180         return m_pCurTestCase;
181     }
182
183     virtual void setUpParams( const TestCfg& /*cfg*/ ) {}
184     virtual void endTestCase() {}
185     virtual void myRun(const char * /*in_name*/, bool /*invert*/ = false) {}
186
187     virtual void error(const char *in_macroName, const char *in_macro, const char *in_file, int in_line) {
188       m_failed = true;
189       if (m_reporter) {
190         m_reporter->error(in_macroName, in_macro, in_file, in_line);
191       }
192     }
193     virtual char const * test_name() const = 0;
194
195     static void message(const char *msg) {
196       if (m_reporter) {
197         m_reporter->message(msg);
198       }
199     }
200
201     bool equalDoubles(double in_expected, double in_real, double in_maxErr) {
202       double diff = in_expected - in_real;
203       if (diff < 0.) {
204         diff = -diff;
205       }
206       return diff < in_maxErr;
207     }
208
209     virtual void progress(const char *in_className, const char *in_functionName, bool ignored, bool explicitTest) {
210       ++m_numTests;
211       if (m_reporter) {
212         m_reporter->progress(in_className, in_functionName, ignored, explicitTest);
213       }
214     }
215
216     bool shouldRunThis( const char *in_desiredTest, const char *in_className, const char *in_functionName,
217                         bool invert, bool explicit_test, bool &do_progress );
218
219     void tearDown() {
220       print_gc_state();
221       if (m_failed)
222         ++m_numErrors;
223       m_reporter->end();
224     }
225
226     static void print_gc_state();
227
228     static std::vector<std::string> const&  getTestStrings();
229
230     template <typename RandomIt>
231     static void shuffle( RandomIt first, RandomIt last )
232     {
233         std::shuffle( first, last, m_RandomGen );
234     }
235
236     static void print_test_list();
237
238   protected:
239     static std::vector<std::string>  m_arrStrings ;   // array of test strings
240
241   public:
242       static bool m_bPrintGCState   ;   // print GC state after each test
243       static Config m_Cfg;
244       static std::string m_strTestDataDir;
245       static bool m_bExactMatch;
246
247       // random shuffle support
248       static std::random_device m_RandomDevice;
249       static std::mt19937       m_RandomGen;
250
251   protected:
252     static int m_numErrors;
253     static int m_numTests;
254
255     static TestCase * m_pCurTestCase;
256
257   private:
258     static TestCase *m_root;
259     TestCase *m_next;
260     bool m_failed;
261
262     static Reporter *m_reporter;
263   };
264
265 }
266
267 #if !defined (CPPUNIT_MINI_HIDE_UNUSED_VARIABLE)
268 #  if defined (_MSC_VER)
269 #    define CPPUNIT_MINI_HIDE_UNUSED_VARIABLE(v) (v);
270 #  else
271 #    define CPPUNIT_MINI_HIDE_UNUSED_VARIABLE(v)
272 #  endif
273 #endif
274
275 #define CPPUNIT_TEST_SUITE_(X, cfgBranchName) \
276     typedef CppUnitMini::TestCase Base; \
277     virtual char const * test_name() const { return #X; } \
278     virtual void myRun(const char *in_name, bool invert = false) { \
279     const char *className = #X; CPPUNIT_MINI_HIDE_UNUSED_VARIABLE(className) \
280     bool ignoring = false; CPPUNIT_MINI_HIDE_UNUSED_VARIABLE(ignoring) \
281     setUpParams( m_Cfg.get( cfgBranchName ));
282
283 #define CPPUNIT_TEST_SUITE(X) CPPUNIT_TEST_SUITE_(X, #X)
284
285 #if defined CPPUNIT_MINI_USE_EXCEPTIONS
286 #  define CPPUNIT_TEST_BASE(X, Y) \
287   { \
288     bool do_progress; \
289     bool shouldRun = shouldRunThis(in_name, className, #X, invert, Y, do_progress); \
290     if (shouldRun || do_progress) { \
291       setUp(); \
292       progress(className, #X, ignoring || !shouldRun, !ignoring && Y); \
293       if (shouldRun && !ignoring) { \
294         try { \
295           X(); \
296         } \
297         catch(...) { \
298           Base::error("Test Failed: An exception was thrown.", #X, __FILE__, __LINE__); \
299         } \
300       } \
301       tearDown(); \
302     } \
303   }
304 #else
305 #  define CPPUNIT_TEST_BASE(X, Y) \
306   { \
307     bool do_progress; \
308     bool shouldRun = shouldRunThis(in_name, className, #X, invert, Y, do_progress); \
309     if (shouldRun || do_progress) { \
310       setUp(); \
311       progress(className, #X, ignoring || !shouldRun, !ignoring && Y); \
312       if (shouldRun && !ignoring) \
313         X(); \
314       tearDown(); \
315     } \
316   }
317 #endif
318
319 #define CPPUNIT_TEST(X) CPPUNIT_TEST_BASE(X, false)
320 #define CPPUNIT_EXPLICIT_TEST(X) CPPUNIT_TEST_BASE(X, true)
321
322 #define CDSUNIT_DECLARE_TEST(X) void X();
323
324 #define CPPUNIT_IGNORE \
325   ignoring = true
326
327 #define CPPUNIT_STOP_IGNORE \
328   ignoring = false
329
330 #define CPPUNIT_TEST_SUITE_END() endTestCase(); }
331 #define CPPUNIT_TEST_SUITE_END_PART() }
332
333 #define CPPUNIT_TEST_SUITE_REGISTRATION_(X, NAME) static X NAME
334 #define CPPUNIT_TEST_SUITE_REGISTRATION(X) CPPUNIT_TEST_SUITE_REGISTRATION_(X, local)
335
336 #define CPPUNIT_CHECK(X) \
337   if (!(X)) { \
338     Base::error("CPPUNIT_CHECK", #X, __FILE__, __LINE__); \
339   }
340
341 #define CPPUNIT_CHECK_CURRENT(X) \
342   if (!(X)) { \
343     CppUnitMini::TestCase::current_test()->error("CPPUNIT_CHECK", #X, __FILE__, __LINE__); \
344   }
345
346 #define CPPUNIT_CHECK_EX(X, Y) \
347     if (!(X)) { \
348         std::stringstream st    ;   \
349         st << #X << ": " << Y   ;   \
350         Base::error("CPPUNIT_CHECK", st.str().c_str(), __FILE__, __LINE__); \
351     }
352
353 #define CPPUNIT_CHECK_CURRENT_EX(X, Y) \
354     if (!(X)) { \
355         std::stringstream st    ;   \
356         st << #X << ": " << Y   ;   \
357         CppUnitMini::TestCase::current_test()->error("CPPUNIT_CHECK", st.str().c_str(), __FILE__, __LINE__); \
358     }
359
360 #define CPPUNIT_ASSERT(X) \
361   if (!(X)) { \
362     Base::error("CPPUNIT_ASSERT", #X, __FILE__, __LINE__); \
363     return; \
364   }
365
366 #define CPPUNIT_ASSERT_CURRENT(X) \
367     if (!(X)) { \
368         CppUnitMini::TestCase::current_test()->error("CPPUNIT_ASSERT", #X, __FILE__, __LINE__); \
369         return; \
370     }
371
372
373 #define CPPUNIT_ASSERT_EX(A, X) \
374     if (!(A)) { \
375         std::stringstream st    ;   \
376         st << #A << ": " << X   ;   \
377         Base::error("CPPUNIT_ASSERT", st.str().c_str(), __FILE__, __LINE__); \
378         return; \
379     }
380
381 #define CPPUNIT_FAIL { \
382     Base::error("CPPUNIT_FAIL", "", __FILE__, __LINE__); \
383     return; \
384   }
385
386 #define CPPUNIT_ASSERT_EQUAL(X, Y) \
387   if ((X) != (Y)) { \
388     Base::error("CPPUNIT_ASSERT_EQUAL", #X","#Y, __FILE__, __LINE__); \
389     return; \
390   }
391
392 #define CPPUNIT_ASSERT_DOUBLES_EQUAL(X, Y, Z) \
393   if (!equalDoubles((X), (Y), (Z))) { \
394     Base::error("CPPUNIT_ASSERT_DOUBLES_EQUAL", #X","#Y","#Z, __FILE__, __LINE__); \
395     return; \
396   }
397
398 // added by cds
399 #define CPPUNIT_MSG( X ) \
400     {   \
401         std::stringstream st    ;   \
402         st << X ;   \
403         if ( !st.str().empty() ) \
404             CppUnitMini::TestCase::message( st.str().c_str() );   \
405     }
406
407 #define CPPUNIT_MESSAGE(m) CppUnitMini::TestCase::message(m)
408
409 #define CPPUNIT_ASSERT_MSG( A, X ) \
410     if ( !(A) ){   \
411         std::stringstream st    ;   \
412         st << #A << ": " << X ;   \
413         error( "CPPUNIT_ASSERT_MSG", st.str().c_str(), __FILE__, __LINE__ )     ;   \
414     }
415
416 #endif // #ifndef CDS_CPPUNIT_MPFR_H_