1 /*
2  * Copyright (c) 2003, 2004
3  * Zdenek Nemec
4  *
5  * This material is provided "as is", with absolutely no warranty expressed
6  * or implied. Any use is at your own risk.
7  *
8  * Permission to use or copy this software for any purpose is hereby granted
9  * without fee, provided the above notices are retained on all copies.
10  * Permission to modify the code and to distribute modified code is granted,
11  * provided the above notices are retained, and a notice that the code was
12  * modified is included with the above copyright notice.
13  *
14  */
15 
16 /* $Id$ */
17 
18 #ifndef _CPPUNITMPFR_H_
19 #define _CPPUNITMPFR_H_
20 
21 #if 0
22 #  define CPPUNIT_NS CppUnitMini
23 #else
24 #  define CPPUNIT_NS
25 #endif
26 
27 #include <string.h>
28 
29 #if 0
30 namespace CPPUNIT_NS
31 {
32 #endif
33   class Reporter {
34   public:
~Reporter()35     virtual ~Reporter() {}
error(const char *,const char *,const char *,int)36     virtual void error(const char * /*macroName*/, const char * /*in_macro*/, const char * /*in_file*/, int /*in_line*/) {}
message(const char *)37     virtual void message( const char * /*msg*/ ) {}
progress(const char *,const char *,bool,bool)38     virtual void progress( const char * /*in_className*/, const char * /*in_testName*/, bool /*ignored*/, bool /* explicit */) {}
end()39     virtual void end() {}
printSummary()40     virtual void printSummary() {}
41   };
42 
43   class TestFixture {
44   public:
~TestFixture()45     virtual ~TestFixture() {}
46 
47     //! \brief Set up context before running a test.
setUp()48     virtual void setUp() {}
49 
50     //! Clean up after the test run.
tearDown()51     virtual void tearDown() {}
52   };
53 
54   class TestCase : public TestFixture {
55   public:
TestCase()56     TestCase() { registerTestCase(this); }
57 
setUp()58     void setUp() { m_failed = false; }
59     static int run(Reporter *in_reporter = 0, const char *in_testName = "", bool invert = false);
numErrors()60     int numErrors() { return m_numErrors; }
61     static void registerTestCase(TestCase *in_testCase);
62 
63     virtual void myRun(const char * /*in_name*/, bool /*invert*/ = false) {}
64 
error(const char * in_macroName,const char * in_macro,const char * in_file,int in_line)65     virtual void error(const char *in_macroName, const char *in_macro, const char *in_file, int in_line) {
66       m_failed = true;
67       if (m_reporter) {
68         m_reporter->error(in_macroName, in_macro, in_file, in_line);
69       }
70     }
71 
message(const char * msg)72     static void message(const char *msg) {
73       if (m_reporter) {
74         m_reporter->message(msg);
75       }
76     }
77 
equalDoubles(double in_expected,double in_real,double in_maxErr)78     bool equalDoubles(double in_expected, double in_real, double in_maxErr) {
79       double diff = in_expected - in_real;
80       if (diff < 0.) {
81         diff = -diff;
82       }
83       return diff < in_maxErr;
84     }
85 
progress(const char * in_className,const char * in_functionName,bool ignored,bool explicitTest)86     virtual void progress(const char *in_className, const char *in_functionName, bool ignored, bool explicitTest) {
87       ++m_numTests;
88       if (m_reporter) {
89         m_reporter->progress(in_className, in_functionName, ignored, explicitTest);
90       }
91     }
92 
shouldRunThis(const char * in_desiredTest,const char * in_className,const char * in_functionName,bool invert,bool explicit_test,bool & do_progress)93     bool shouldRunThis(const char *in_desiredTest, const char *in_className, const char *in_functionName,
94                        bool invert, bool explicit_test, bool &do_progress) {
95       if ((in_desiredTest) && (in_desiredTest[0] != '\0')) {
96         do_progress = false;
97         const char *ptr = strstr(in_desiredTest, "::");
98         if (ptr) {
99           bool match = (strncmp(in_desiredTest, in_className, strlen(in_className)) == 0) &&
100                        (strncmp(ptr + 2, in_functionName, strlen(in_functionName)) == 0);
101           // Invert shall not make explicit test run:
102           return invert ? (match ? !match : !explicit_test)
103                         : match;
104         }
105         bool match = (strcmp(in_desiredTest, in_className) == 0);
106         do_progress = match;
107         return !explicit_test && (match == !invert);
108       }
109       do_progress = true;
110       return !explicit_test;
111     }
112 
tearDown()113     void tearDown() {
114       if (m_failed)
115         ++m_numErrors;
116       m_reporter->end();
117     }
118 
119   protected:
120     static int m_numErrors;
121     static int m_numTests;
122 
123   private:
124     static TestCase *m_root;
125     TestCase *m_next;
126     bool m_failed;
127 
128     static Reporter *m_reporter;
129   };
130 #if 0
131 }
132 #endif
133 
134 #if !defined (CPPUNIT_MINI_HIDE_UNUSED_VARIABLE)
135 #  if defined (_MSC_VER)
136 #    define CPPUNIT_MINI_HIDE_UNUSED_VARIABLE(v) (v);
137 #  else
138 #    define CPPUNIT_MINI_HIDE_UNUSED_VARIABLE(v)
139 #  endif
140 #endif
141 
142 #define CPPUNIT_TEST_SUITE(X) \
143   typedef CPPUNIT_NS::TestCase Base; \
144   virtual void myRun(const char *in_name, bool invert = false) { \
145     const char *className = #X; CPPUNIT_MINI_HIDE_UNUSED_VARIABLE(className) \
146     bool ignoring = false; CPPUNIT_MINI_HIDE_UNUSED_VARIABLE(ignoring)
147 
148 #if defined CPPUNIT_MINI_USE_EXCEPTIONS
149 #  define CPPUNIT_TEST_BASE(X, Y) \
150   { \
151     bool do_progress; \
152     bool shouldRun = shouldRunThis(in_name, className, #X, invert, Y, do_progress); \
153     if (shouldRun || do_progress) { \
154       setUp(); \
155       progress(className, #X, ignoring || !shouldRun, !ignoring && Y); \
156       if (shouldRun && !ignoring) { \
157         try { \
158           X(); \
159         } \
160         catch(...) { \
161           Base::error("Test Failed: An Exception was thrown.", #X, __FILE__, __LINE__); \
162         } \
163       } \
164       tearDown(); \
165     } \
166   }
167 #else
168 #  define CPPUNIT_TEST_BASE(X, Y) \
169   { \
170     bool do_progress; \
171     bool shouldRun = shouldRunThis(in_name, className, #X, invert, Y, do_progress); \
172     if (shouldRun || do_progress) { \
173       setUp(); \
174       progress(className, #X, ignoring || !shouldRun, !ignoring && Y); \
175       if (shouldRun && !ignoring) \
176         X(); \
177       tearDown(); \
178     } \
179   }
180 #endif
181 
182 #define CPPUNIT_TEST(X) CPPUNIT_TEST_BASE(X, false)
183 #define CPPUNIT_EXPLICIT_TEST(X) CPPUNIT_TEST_BASE(X, true)
184 
185 #define CPPUNIT_IGNORE \
186   ignoring = true
187 
188 #define CPPUNIT_STOP_IGNORE \
189   ignoring = false
190 
191 #define CPPUNIT_TEST_SUITE_END() }
192 
193 #define CPPUNIT_TEST_SUITE_REGISTRATION(X) static X local
194 
195 #define CPPUNIT_CHECK(X) \
196   if (!(X)) { \
197     Base::error("CPPUNIT_CHECK", #X, __FILE__, __LINE__); \
198   }
199 
200 #define CPPUNIT_ASSERT(X) \
201   if (!(X)) { \
202     Base::error("CPPUNIT_ASSERT", #X, __FILE__, __LINE__); \
203     return; \
204   }
205 
206 #define CPPUNIT_FAIL { \
207     Base::error("CPPUNIT_FAIL", "", __FILE__, __LINE__); \
208     return; \
209   }
210 
211 #define CPPUNIT_ASSERT_EQUAL(X, Y) \
212   if ((X) != (Y)) { \
213     Base::error("CPPUNIT_ASSERT_EQUAL", #X","#Y, __FILE__, __LINE__); \
214     return; \
215   }
216 
217 #define CPPUNIT_ASSERT_DOUBLES_EQUAL(X, Y, Z) \
218   if (!equalDoubles((X), (Y), (Z))) { \
219     Base::error("CPPUNIT_ASSERT_DOUBLES_EQUAL", #X","#Y","#Z, __FILE__, __LINE__); \
220     return; \
221   }
222 
223 #define CPPUNIT_MESSAGE(m) CPPUNIT_NS::TestCase::message(m)
224 
225 #endif
226