1#ifndef CPPUNIT_TESTCALLER_H    // -*- C++ -*-
2#define CPPUNIT_TESTCALLER_H
3
4#include <cppunit/Exception.h>
5#include <cppunit/TestCase.h>
6
7
8#if CPPUNIT_USE_TYPEINFO_NAME
9#  include <cppunit/extensions/TypeInfoHelper.h>
10#endif
11
12
13namespace CppUnit {
14
15/*! \brief Marker class indicating that no exception is expected by TestCaller.
16 * This class is an implementation detail. You should never use this class directly.
17 */
18class CPPUNIT_API NoExceptionExpected
19{
20private:
21  //! Prevent class instantiation.
22  NoExceptionExpected();
23};
24
25
26/*! \brief (Implementation) Traits used by TestCaller to expect an exception.
27 *
28 * This class is an implementation detail. You should never use this class directly.
29 */
30template<typename ExceptionType>
31struct ExpectedExceptionTraits
32{
33  static void expectedException()
34  {
35#if CPPUNIT_USE_TYPEINFO_NAME
36	  std::string message( "Expected exception of type " );
37	  message += TypeInfoHelper::getClassName( typeid( ExceptionType ) );
38	  message += ", but got none";
39#else
40	  std::string message( "Expected exception but got none" );
41#endif
42	  throw Exception( message );
43  }
44};
45
46
47/*! \brief (Implementation) Traits specialization used by TestCaller to
48 * expect no exception.
49 *
50 * This class is an implementation detail. You should never use this class directly.
51 */
52template<>
53struct ExpectedExceptionTraits<NoExceptionExpected>
54{
55  static void expectedException()
56  {
57  }
58};
59
60
61
62//*** FIXME: rework this when class Fixture is implemented. ***//
63
64
65/*! \brief Generate a test case from a fixture method.
66 * \ingroup WritingTestFixture
67 *
68 * A test caller provides access to a test case method
69 * on a test fixture class.  Test callers are useful when
70 * you want to run an individual test or add it to a
71 * suite.
72 * Test Callers invoke only one Test (i.e. test method) on one
73 * Fixture of a TestFixture.
74 *
75 * Here is an example:
76 * \code
77 * class MathTest : public CppUnit::TestFixture {
78 *         ...
79 *     public:
80 *         void         setUp();
81 *         void         tearDown();
82 *
83 *         void         testAdd();
84 *         void         testSubtract();
85 * };
86 *
87 * CppUnit::Test *MathTest::suite() {
88 *     CppUnit::TestSuite *suite = new CppUnit::TestSuite;
89 *
90 *     suite->addTest( new CppUnit::TestCaller<MathTest>( "testAdd", testAdd ) );
91 *     return suite;
92 * }
93 * \endcode
94 *
95 * You can use a TestCaller to bind any test method on a TestFixture
96 * class, as long as it accepts void and returns void.
97 *
98 * \see TestCase
99 */
100
101template <typename Fixture,
102	  typename ExpectedException = NoExceptionExpected>
103class TestCaller : public TestCase
104{
105  typedef void (Fixture::*TestMethod)();
106
107public:
108  /*!
109   * Constructor for TestCaller. This constructor builds a new Fixture
110   * instance owned by the TestCaller.
111   * \param name name of this TestCaller
112   * \param test the method this TestCaller calls in runTest()
113   */
114  TestCaller( std::string name, TestMethod test ) :
115	    TestCase( name ),
116	    m_ownFixture( true ),
117	    m_fixture( new Fixture() ),
118	    m_test( test )
119  {
120  }
121
122  /*!
123   * Constructor for TestCaller.
124   * This constructor does not create a new Fixture instance but accepts
125   * an existing one as parameter. The TestCaller will not own the
126   * Fixture object.
127   * \param name name of this TestCaller
128   * \param test the method this TestCaller calls in runTest()
129   * \param fixture the Fixture to invoke the test method on.
130   */
131  TestCaller(std::string name, TestMethod test, Fixture& fixture) :
132	    TestCase( name ),
133	    m_ownFixture( false ),
134	    m_fixture( &fixture ),
135	    m_test( test )
136  {
137  }
138
139  /*!
140   * Constructor for TestCaller.
141   * This constructor does not create a new Fixture instance but accepts
142   * an existing one as parameter. The TestCaller will own the
143   * Fixture object and delete it in its destructor.
144   * \param name name of this TestCaller
145   * \param test the method this TestCaller calls in runTest()
146   * \param fixture the Fixture to invoke the test method on.
147   */
148  TestCaller(std::string name, TestMethod test, Fixture* fixture) :
149	    TestCase( name ),
150	    m_ownFixture( true ),
151	    m_fixture( fixture ),
152	    m_test( test )
153  {
154  }
155
156  ~TestCaller()
157  {
158    if (m_ownFixture)
159      delete m_fixture;
160  }
161
162protected:
163  void runTest()
164  {
165	  try {
166	    (m_fixture->*m_test)();
167	  }
168	  catch ( ExpectedException & ) {
169	    return;
170	  }
171
172  	ExpectedExceptionTraits<ExpectedException>::expectedException();
173  }
174
175  void setUp()
176  {
177  	m_fixture->setUp ();
178  }
179
180  void tearDown()
181  {
182	  m_fixture->tearDown ();
183  }
184
185  std::string toString() const
186  {
187  	return "TestCaller " + getName();
188  }
189
190private:
191  TestCaller( const TestCaller &other );
192  TestCaller &operator =( const TestCaller &other );
193
194private:
195  bool m_ownFixture;
196  Fixture *m_fixture;
197  TestMethod m_test;
198};
199
200
201
202} // namespace CppUnit
203
204#endif // CPPUNIT_TESTCALLER_H
205