RCFProto
 All Classes Functions Typedefs
Test.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2013, Delta V Software. All rights reserved.
6 // http://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF
12 // under GPL terms.
13 //
14 // Version: 2.0
15 // Contact: support <at> deltavsoft.com
16 //
17 //******************************************************************************
18 
19 #ifndef RCF_TEST_TEST_HPP
20 #define RCF_TEST_TEST_HPP
21 
22 #include <iostream>
23 #include <string>
24 #include <vector>
25 #include <string>
26 
27 #include <RCF/util/VariableArgMacro.hpp>
28 
29 #include <RCF/CustomAllocator.hpp>
30 
31 #if defined(__GNUC__) && __GNUC__ >= 4
32  #ifdef RCF_TEST_BUILD_DLL
33  #define RCF_TEST_EXPORT __attribute__((visibility("default")))
34  #else
35  #define RCF_TEST_EXPORT __attribute__((visibility("default")))
36  #endif
37 #elif defined(__GNUC__)
38  #ifdef RCF_TEST_BUILD_DLL
39  #define RCF_TEST_EXPORT
40  #else
41  #define RCF_TEST_EXPORT
42  #endif
43 #else
44  #ifdef RCF_TEST_BUILD_DLL
45  #define RCF_TEST_EXPORT __declspec(dllexport)
46  #else
47  #define RCF_TEST_EXPORT
48  #endif
49 #endif
50 
51 #if defined(RCF_TEST_BUILD_DLL) && defined(_MSC_VER) && !defined(_DLL)
52 #error "Error: DLL builds of RCF require dynamic runtime linking. Select one of the DLL options in Properties -> C/C++ -> Code Generation -> Runtime Library."
53 #endif
54 
55 namespace RCF {
56 
57 // Test hierarchies.
58 class RCF_TEST_EXPORT TestHierarchy
59 {
60 public:
61 
62  TestHierarchy();
63  void pushTestCase(const std::string & name);
64  void popTestCase();
65  std::string currentTestCase();
66  void onlyRunTestCase(const std::string & testCase, bool caseSensitive);
67  void enumerateTestCasesOnly();
68  bool shouldCurrentTestCaseRun();
69  bool didTestCaseRun();
70 
71 private:
72 
73  void split(
74  const std::string & s,
75  char delim,
76  std::vector<std::string> & elems);
77 
78  bool doesCurrentTestCaseMatch();
79 
80  std::vector<std::string> mCurrentTestCase;
81 
82  std::vector<std::string> mTestCaseToRun;
83  bool mCaseSensitive;
84  bool mHasTestCaseRun;
85 
86  bool mEnumerateOnly;
87 };
88 
89 class RCF_TEST_EXPORT TestCaseSentry
90 {
91 public:
92  TestCaseSentry(const std::string & name);
93  TestCaseSentry(std::size_t n);
94  ~TestCaseSentry();
95 
96  bool shouldRun();
97  void setHasRun();
98 
99 private:
100 
101  std::string mName;
102  bool mRunnable;
103  bool mHasRun;
104 };
105 
106 #define TEST_CASE(name) TEST_CASE_IMPL(name, BOOST_PP_CAT(testCase, __LINE__))
107 #define TEST_CASE_IMPL(name, instName) \
108  for (RCF::TestCaseSentry instName((name)); instName.shouldRun(); instName.setHasRun())
109 
110 class RCF_TEST_EXPORT TestEnv
111 {
112 public:
113  TestEnv();
114 
115  void setTestCaseToRun(const std::string & testCase, bool caseSensitive = true);
116  void setEnumerationOnly();
117  void setAssertOnFail(bool assertOnFail);
118 
119  typedef void (*PfnAssert)(const char * file, int line, const char * condition , const char * info);
120  void setPfnAssert(PfnAssert pfnAssert);
121 
122  std::size_t getFailCount();
123  bool didTestCaseRun();
124 
125  void printTestMessage(const std::string & msg);
126 
127  void reportTestFailure(
128  const char * file,
129  int line,
130  const char * condition,
131  const char * info);
132 
133 private:
134 
135  friend class TestCaseSentry;
136 
137  TestHierarchy mTestHierarchy;
138 
139  std::size_t mFailCount;
140 
141  bool mAssertOnFail;
142  PfnAssert mPfnAssert;
143 };
144 
145 RCF_TEST_EXPORT TestEnv & gTestEnv();
146 
147  std::string getRelativePathToCheckoutRoot();
148  std::string getRelativeTestDataPath();
149  std::string getWorkingDir();
150 
151 } // namespace RCF
152 
153 // RCF_CHECK
154 
155 class RcfCheckFunctor : public RCF::VariableArgMacroFunctor
156 {
157 public:
158 
159  RcfCheckFunctor & setArgs(const char * file, int line, const char * cond)
160  {
161  mFile = file;
162  mLine = line;
163  mCond = cond;
164  return *this;
165  }
166 
167  ~RcfCheckFunctor()
168  {
169  std::string values(mArgs->str(), static_cast<std::size_t>(mArgs->tellp()));
170  RCF::gTestEnv().reportTestFailure(mFile, mLine, mCond, values.c_str());
171  }
172 
173 private:
174  const char * mFile;
175  int mLine;
176  const char * mCond;
177 };
178 
179 #ifdef _MSC_VER
180 #pragma warning( push )
181 #pragma warning( disable : 4355 ) // warning C4355: 'this' : used in base member initializer list
182 #endif
183 
184 DECLARE_VARIABLE_ARG_MACRO( RCF_CHECK, RcfCheckFunctor );
185 
186 #define RCF_CHECK(cond) \
187  if (cond); \
188  else \
189  ::VariableArgMacro<RcfCheckFunctor>() \
190  .setArgs(__FILE__, __LINE__, #cond) \
191  .cast( (::VariableArgMacro<RcfCheckFunctor> *) NULL ) \
192  .RCF_CHECK_A
193 
194 #define RCF_CHECK_A(x) RCF_CHECK_OP(x, B)
195 #define RCF_CHECK_B(x) RCF_CHECK_OP(x, A)
196 #define RCF_CHECK_OP(x, next) RCF_CHECK_A.notify_((x), #x).RCF_CHECK_ ## next
197 
198 #ifdef _MSC_VER
199 #pragma warning( pop )
200 #endif
201 
202 #define RCF_CHECK_EQ(a,b) RCF_CHECK(a == b)(a)(b)
203 #define RCF_CHECK_NEQ(a,b) RCF_CHECK(a != b)(a)(b)
204 
205 #define RCF_CHECK_LT(a,b) RCF_CHECK(a < b)(a)(b)
206 #define RCF_CHECK_LTEQ(a,b) RCF_CHECK(a <= b)(a)(b)
207 
208 #define RCF_CHECK_GT(a,b) RCF_CHECK(a > b)(a)(b)
209 #define RCF_CHECK_GTEQ(a,b) RCF_CHECK(a >= b)(a)(b)
210 
211 #define RCF_CHECK_FAIL() RCF_CHECK(0)
212 #define RCF_CHECK_OK() RCF_CHECK(1)
213 
214 #endif // ! RCF_TEST_TEST_HPP