helper script for fred
[feisty_meow.git] / nucleus / library / unit_test / unit_base.h
1 #ifndef UNIT_BASE_GROUP
2 #define UNIT_BASE_GROUP
3
4 /*
5 *  Name   : unit_base tools for unit testing
6 *  Author : Chris Koeritz
7 **
8 * Copyright (c) 2009-$now By Author.  This program is free software; you can  *
9 * redistribute it and/or modify it under the terms of the GNU General Public  *
10 * License as published by the Free Software Foundation; either version 2 of   *
11 * the License or (at your option) any later version.  This is online at:      *
12 *     http://www.fsf.org/copyleft/gpl.html                                    *
13 * Please send any updates to: fred@gruntose.com                               *
14 */
15
16 //! Useful support functions for unit testing, especially within hoople.
17 /*!
18   Provides a simple framework for unit testing the hoople classes.
19 */
20
21 #include <basis/astring.h>
22 #include <basis/contracts.h>
23 #include <basis/enhance_cpp.h>
24 #include <basis/mutex.h>
25 #include <structures/string_table.h>
26
27 namespace unit_test {
28
29 // these macros can be used to put more information into the test name.
30 // using these is preferable to calling the class methods directly, since
31 // those cannot print out the original version of the formal parameters a
32 // and b for the test; the macros show the expressions that failed rather
33 // than just the values.
34 // note that these require the calling object to be derived from unit_base.
35 #define UNIT_BASE_THIS_OBJECT (*this)
36   // the macro for UNIT_BASE_THIS_OBJECT allows tests to use a single unit_base object by
37   // changing the value of UNIT_BASE_THIS_OBJECT to refer to the proper object's name.
38 #define ASSERT_EQUAL(a, b, test_name) { \
39   BASE_FUNCTION(func); \
40   UNIT_BASE_THIS_OBJECT.assert_equal(a, b, function_name, test_name, basis::astring(#a) + " must be equal to " + #b); \
41 }
42 #define ASSERT_INEQUAL(a, b, test_name) { \
43   BASE_FUNCTION(func); \
44   UNIT_BASE_THIS_OBJECT.assert_not_equal(a, b, function_name, test_name, basis::astring(#a) + " must be inequal to " + #b); \
45 }
46 #define ASSERT_TRUE(a, test_name) { \
47   BASE_FUNCTION(func); \
48   UNIT_BASE_THIS_OBJECT.assert_true(a, function_name, test_name, basis::astring(#a) + " must be true"); \
49 }
50 #define ASSERT_FALSE(a, test_name) { \
51   BASE_FUNCTION(func); \
52   UNIT_BASE_THIS_OBJECT.assert_false(a, function_name, test_name, basis::astring(#a) + " must be false"); \
53 }
54 // pointer versions for nicer syntax.
55 #define ASSERT_NULL(x, y) ASSERT_FALSE(x, y)
56 #define ASSERT_NON_NULL(x, y) ASSERT_TRUE(x, y)
57
58 class unit_base : public virtual basis::nameable
59 {
60 public:
61   unit_base();
62   virtual ~unit_base();
63
64   DEFINE_CLASS_NAME("unit_base");
65
66   int total_tests() const;  //!< the total count of tests that have been run.
67   int passed_tests() const;  //!< count of successful tests run.
68   int failed_tests() const;  //!< count of number of failed tests.
69
70   void assert_equal(const basis::hoople_standard &a, const basis::hoople_standard &b,
71       const basis::astring &class_name, const basis::astring &test_name,
72       const basis::astring &diagnostic_info);
73     //!< tests that the objects a and b are equal.
74   void assert_not_equal(const basis::hoople_standard &a, const basis::hoople_standard &b,
75       const basis::astring &class_name, const basis::astring &test_name,
76       const basis::astring &diagnostic_info);
77     //!< tests that objects a and b are NOT equal.
78
79   void assert_equal(const basis::byte_array &a, const basis::byte_array &b,
80       const basis::astring &class_name, const basis::astring &test_name,
81       const basis::astring &diagnostic_info);
82     //!< tests that the byte_arrays a and b are equal.
83   void assert_not_equal(const basis::byte_array &a, const basis::byte_array &b,
84       const basis::astring &class_name, const basis::astring &test_name,
85       const basis::astring &diagnostic_info);
86     //!< tests that the byte_arrays a and b are not equal.
87
88   void assert_equal(int a, int b,
89       const basis::astring &class_name, const basis::astring &test_name,
90       const basis::astring &diagnostic_info);
91     //!< tests that integers a and b are equal.
92   void assert_not_equal(int a, int b,
93       const basis::astring &class_name, const basis::astring &test_name,
94       const basis::astring &diagnostic_info);
95     //!< tests that integers a and b are NOT equal.
96
97   void assert_equal(double a, double b,
98       const basis::astring &class_name, const basis::astring &test_name,
99       const basis::astring &diagnostic_info);
100     //!< tests that doubles a and b are equal.
101   void assert_not_equal(double a, double b,
102       const basis::astring &class_name, const basis::astring &test_name,
103       const basis::astring &diagnostic_info);
104     //!< tests that doubles a and b are NOT equal.
105
106   void assert_equal(const void *a, const void *b,
107       const basis::astring &class_name, const basis::astring &test_name,
108       const basis::astring &diagnostic_info);
109     //!< tests that void pointers a and b are equal.
110     /*!< note that you can use this to compare any two pointers as long as
111     you cast them to (void *) first.  this reports whether the two have the
112     same address in memory, but nothing about their contents. */
113   void assert_not_equal(const void *a, const void *b,
114       const basis::astring &class_name, const basis::astring &test_name,
115       const basis::astring &diagnostic_info);
116     //!< tests that void pointers a and b are NOT equal.
117
118   void assert_true(bool result, 
119       const basis::astring &class_name, const basis::astring &test_name,
120       const basis::astring &diagnostic_info);
121     //!< tests that the "result" is a true boolean.
122   void assert_false(bool result, 
123       const basis::astring &class_name, const basis::astring &test_name,
124       const basis::astring &diagnostic_info);
125     //!< tests that the "result" is a false boolean.
126   
127   // these two methods can be used in an ad hoc manner when using the above
128   // assert methods is not helpful.  the "test_name" should be provided
129   // like above, but the "diagnostic_info" can be phrased in any way needed
130   // to describe the pass or fail event.
131   void record_pass(const basis::astring &class_name,
132           const basis::astring &test_name,
133           const basis::astring &diagnostic_info);
134     //!< very general recording of a successful test; better to use asserts.
135   void record_fail(const basis::astring &class_name,
136           const basis::astring &test_name,
137           const basis::astring &diagnostic_info);
138     //!< very general recording of a failed test; better to use asserts.
139
140   int final_report();
141     //!< generates a report of the total number of tests that succeeded.
142     /*!< the return value of this can be used as the exit value of the overall test.  if there
143     are any failures, then a failure result is returned (non-zero).  otherwise the successful
144     exit status of zero is returned. */
145
146 private:
147   basis::mutex c_lock;  //!< protects our objects for concurrent access.
148   int c_total_tests;  //!< how many tests have been run?
149   int c_passed_tests;  //!< how many of those passed?
150   structures::string_table c_successful;  //!< successful test names.
151   structures::string_table c_failed;  //!< failing test names.
152
153   void write_cppunit_xml();
154     //!< outputs a report file in cppunit format so CI engines can see results.
155
156   void count_successful_test(const basis::astring &class_name, const basis::astring &test_name);
157     //!< records one successful test.
158
159   void count_failed_test(const basis::astring &class_name, const basis::astring &test_name, const basis::astring &diag);
160     //!< records one failed test.
161
162   void record_successful_assertion(const basis::astring &class_name, const basis::astring &test_name,
163       const basis::astring &assertion_name);
164     //!< used by happy tests to record their success.
165
166   void record_failed_object_compare(const basis::hoople_standard &a,
167       const basis::hoople_standard &b, const basis::astring &class_name,
168       const basis::astring &test_name, const basis::astring &assertion_name);
169   void record_failed_int_compare(int a, int b,
170       const basis::astring &class_name, const basis::astring &test_name,
171       const basis::astring &assertion_name);
172   void record_failed_double_compare(double a, double b,
173       const basis::astring &class_name, const basis::astring &test_name,
174       const basis::astring &assertion_name);
175   void record_failed_tf_assertion(bool result, bool expected_result,
176       const basis::astring &class_name, const basis::astring &test_name,
177       const basis::astring &assertion_name);
178   void record_failed_pointer_compare(const void *a, const void *b,
179       const basis::astring &class_name, const basis::astring &test_name,
180       const basis::astring &assertion_name);
181 };
182
183 } //namespace.
184
185 #endif
186