RCFProto
 All Classes Functions Typedefs
TestMinimal.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 INCLUDE_RCF_TEST_TESTMINIMAL_HPP
20 #define INCLUDE_RCF_TEST_TESTMINIMAL_HPP
21 
22 #ifdef RCF_VLD
23 #include <vld.h>
24 #endif
25 
26 // Include valarray early so it doesn't get trampled by min/max macro definitions.
27 #if defined(_MSC_VER) && _MSC_VER == 1310 && RCF_FEATURE_BOOST_SERIALIZATION==1
28 #include <valarray>
29 #endif
30 
31 // For msvc-7.1, prevent including <locale> from generating warnings.
32 #if defined(_MSC_VER) && _MSC_VER == 1310
33 #pragma warning( disable : 4995 ) // 'func': name was marked as #pragma deprecated
34 #include <locale>
35 #pragma warning( default : 4995 )
36 #endif
37 
38 #include <RCF/Exception.hpp>
39 #include <RCF/InitDeinit.hpp>
40 #include <RCF/ThreadLibrary.hpp>
41 #include <RCF/Tools.hpp>
42 
43 #include <RCF/test/ProgramTimeLimit.hpp>
44 #include <RCF/test/Test.hpp>
45 
46 #include <RCF/util/Platform/OS/BsdSockets.hpp>
47 #include <RCF/util/Log.hpp>
48 
49 #include <iostream>
50 #include <sstream>
51 
52 #ifdef _MSC_VER
53 #include <RCF/test/MiniDump.hpp>
54 #endif
55 
56 #ifdef _MSC_VER
57 #include <crtdbg.h>
58 #endif
59 
60 // Test custom allocation support, if applicable.
61 #if RCF_FEATURE_CUSTOM_ALLOCATOR==1
62 #if defined(_MSC_VER) && !defined(NDEBUG)
63 #include <RCF/test/AllocationHookCRT.hpp>
64 #endif
65 #endif
66 
67 int gProcessReturnValue = 0;
68 
69 #if defined(RCF_VLD) && !defined(NDEBUG)
70 
71 int vldLeakReporter(int reportType, wchar_t * message, int * returnValue)
72 {
73  RCF_UNUSED_VARIABLE(reportType);
74  RCF_UNUSED_VARIABLE(message);
75 
76  // We allow one leak (for the root mutex).
77  int leakCount = VLDGetLeaksCount();
78  if (leakCount > 1)
79  {
80  std::wcout << L"VLD has detected " << leakCount << L" leaks. Call stacks follow." << std::endl;
81  VLDSetReportHook(VLD_RPTHOOK_REMOVE, vldLeakReporter);
82  VLDReportLeaks();
83  *returnValue = gProcessReturnValue + leakCount;
84  exit(*returnValue);
85  }
86  else
87  {
88  *returnValue = gProcessReturnValue;
89  exit(*returnValue);
90  }
91  return 0;
92 }
93 
94 #endif // defined(RCF_VLD) && !defined(NDEBUG)
95 
96 int test_main(int argc, char **argv);
97 
98 int main(int argc, char **argv)
99 {
100 
101 #ifdef RCF_VLD
102  VLDSetReportHook(VLD_RPTHOOK_INSTALL, vldLeakReporter);
103 #endif
104 
105  Platform::OS::BsdSockets::disableBrokenPipeSignals();
106 
107  RCF::RcfInitDeinit rcfInit;
108 
109  RCF::Timer testTimer;
110 
111  std::cout << "Commandline: ";
112  for (int i=0; i<argc; ++i)
113  {
114  std::cout << argv[i] << " ";
115  }
116  std::cout << std::endl;
117 
118  bool shouldNotCatch = false;
119 
120 #ifndef NDEBUG
121  unsigned int defaultTimeLimit = 0;
122 #else
123  unsigned int defaultTimeLimit = 5 * 60;
124 #endif
125 
126  {
127  RCF::CommandLineOption<std::string> clTestCase( "testcase", "", "Run a specific test case.");
128  RCF::CommandLineOption<bool> clListTests("list", false, "List all test cases.");
129  RCF::CommandLineOption<bool> clAssert( "assert", false, "Enable assert popups, and assert on test failures.");
130  RCF::CommandLineOption<int> clLogLevel( "loglevel", 1, "Set RCF log level.");
131  RCF::CommandLineOption<std::string> clLogFormat("logformat", "", "Set RCF log format.");
132  RCF::CommandLineOption<std::string> clLogFile("logfile", "", "Set RCF log file.");
133  RCF::CommandLineOption<bool> clNoCatch( "nocatch", false, "Don't catch exceptions at top level.");
134  RCF::CommandLineOption<unsigned int> clTimeLimit("timelimit", defaultTimeLimit, "Set program time limit in seconds. 0 to disable.");
135 
136 #ifdef _MSC_VER
137  RCF::CommandLineOption<bool> clMinidump("minidump", true, "Enable minidump creation.");
138 #endif
139 
140  bool exitOnHelp = false;
141  RCF::CommandLine::getSingleton().parse(argc, argv, exitOnHelp);
142 
143  // -testcase
144  std::string testCase = clTestCase.get();
145  if (!testCase.empty())
146  {
147  RCF::gTestEnv().setTestCaseToRun(testCase);
148  }
149 
150  // -list
151  bool list = clListTests.get();
152  if (list)
153  {
154  RCF::gTestEnv().setEnumerationOnly();
155  }
156 
157  // -assert
158  bool assertOnFail = clAssert.get();
159  RCF::gTestEnv().setAssertOnFail(assertOnFail);
160 
161 #ifdef BOOST_WINDOWS
162  if (!assertOnFail)
163  {
164  // Try to prevent those pesky crash dialogs from popping up.
165 
166  DWORD dwFlags = SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS;
167  DWORD dwOldFlags = SetErrorMode(dwFlags);
168  SetErrorMode(dwOldFlags | dwFlags);
169 
170 #ifdef _MSC_VER
171  // Disable CRT asserts.
172  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
173  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
174  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
175 #endif
176 
177  }
178 #endif
179 
180 
181  // -loglevel
182  int logName = RCF::LogNameRcf;
183  int logLevel = clLogLevel.get();
184 
185  std::string logFormat = clLogFormat.get();
186  if (logFormat.empty())
187  {
188  logFormat = "%E(%F): [Thread: %D][Time: %H] %X";
189  }
190 
191 #ifdef BOOST_WINDOWS
192  RCF::LoggerPtr loggerPtr(new RCF::Logger(logName, logLevel, RCF::LogToDebugWindow(), logFormat) );
193  loggerPtr->activate();
194 #else
195  RCF::LoggerPtr loggerPtr(new RCF::Logger(logName, logLevel, RCF::LogToStdout(), logFormat) );
196  loggerPtr->activate();
197 #endif
198 
199  std::string logFile = clLogFile.get();
200  if ( logFile.size() > 0 )
201  {
202  RCF::LoggerPtr loggerPtr(new RCF::Logger(logName, logLevel, RCF::LogToFile(logFile, true), logFormat));
203  loggerPtr->activate();
204  }
205 
206  // -minidump
207 #if defined(_MSC_VER)
208  bool enableMinidumps = clMinidump.get();
209  if (enableMinidumps)
210  {
211  setMiniDumpExceptionFilter();
212  }
213 #endif
214 
215  // -timelimit
216  unsigned int timeLimitS = clTimeLimit.get();
217  gpProgramTimeLimit = new ProgramTimeLimit(timeLimitS);
218 
219  shouldNotCatch = clNoCatch.get();
220  }
221 
222  int ret = 0;
223 
224  bool shouldCatch = !shouldNotCatch;
225  if (shouldCatch)
226  {
227  try
228  {
229  ret = test_main(argc, argv);
230  }
231  catch(const RCF::RemoteException & e)
232  {
233  std::cout << "Caught top-level exception (RCF::RemoteException): " << e.getErrorString() << std::endl;
234  RCF_CHECK(1==0);
235  }
236  catch(const RCF::Exception & e)
237  {
238  std::cout << "Caught top-level exception (RCF::Exception): " << e.getErrorString() << std::endl;
239  RCF_CHECK(1==0);
240  }
241  catch(const std::exception & e)
242  {
243  std::cout << "Caught top-level exception (std::exception): " << e.what() << std::endl;
244  RCF_CHECK(1==0);
245  }
246  catch (...)
247  {
248  std::cout << "Caught top-level exception (...)" << std::endl;
249  RCF_CHECK(1==0);
250  }
251  }
252  else
253  {
254  ret = test_main(argc, argv);
255  }
256 
257  std::string exitMsg;
258  std::size_t failCount = RCF::gTestEnv().getFailCount();
259  if (failCount)
260  {
261  std::ostringstream os;
262  os << "*** Test Failures: " << failCount << " ***" << std::endl;
263  exitMsg = os.str();
264  }
265  else
266  {
267  exitMsg = "*** All Tests Passed ***\n";
268  }
269 
270  RCF::gTestEnv().printTestMessage(exitMsg);
271 
272  // Print out how long the test took.
273  boost::uint32_t durationMs = testTimer.getDurationMs();
274  std::cout << "Time elapsed: " << durationMs/1000 << " (s)" << std::endl;
275 
276  RCF::deinit();
277 
278  // Delete the time limit object and its thread, otherwise VLD reports allocations.
279  delete gpProgramTimeLimit;
280  gpProgramTimeLimit = NULL;
281 
282  gProcessReturnValue = ret + static_cast<int>(failCount);
283  return gProcessReturnValue;
284 }
285 
286 // Minidump creation code, for Visual C++ 2003 and later.
287 #if defined(_MSC_VER)
288 #include <RCF/test/MiniDump.cpp>
289 #endif
290 
291 #include <RCF/../../src/RCF/test/Test.cpp>
292 
293 #endif // ! INCLUDE_RCF_TEST_TESTMINIMAL_HPP