source: TestRunnerClient.cpp@ dcbb5d

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since dcbb5d was 88b400, checked in by Frederik Heber <heber@…>, 14 years ago

converted #define's to enums, consts and typedefs [Meyers, "Effective C++", item 1].

basic changes:

  • #define bla 1.3 -> const double bla = 1.3
  • #define bla "test" -> const char * const bla = "test
  • use class specific constants! (HULLEPSILON)

const int Class::bla = 1.3; (in .cpp)
static const int bla; (in .hpp inside class private section)

  • "enum hack": #define bla 5 -> enum { bla = 5 };
    • if const int bla=5; impossible
    • e.g. necessary if constant is used in array declaration (int blabla[bla];)

details:

  • new file defs.cpp where const double reside in and are referenced by extern "C" const double
  • joiner.cpp: main() had to be changed due to concatenation of two #define possible, of two const char * not
  • class specific constants: HULLEPSILON, BONDTHRESHOLD, SPHERERADIUS
  • extended GetPathLengthonCircumCircle to additional parameter HULLEPSILON
  • Property mode set to 100644
File size: 11.8 KB
Line 
1/*******************************************************************************
2 * Copyright (c) 2008 Gerhard Leonhartsberger.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *******************************************************************************/
8
9#include "TestRunnerClient.h"
10
11#ifdef CPPUNIT_MAIN
12
13#include "cppunit/TestResultCollector.h"
14#include "cppunit/XmlOutputter.h"
15#include "cppunit/TestSuite.h"
16#include "cppunit/TestResult.h"
17#include "cppunit/TestFailure.h"
18#include "cppunit/SourceLine.h"
19#include "cppunit/Exception.h"
20#include "cppunit/extensions/TestFactoryRegistry.h"
21#include "cppunit/extensions/TestDecorator.h"
22#include "cppunit/ui/text/TestRunner.h"
23
24#include <iostream>
25#include <sstream>
26#include <typeinfo>
27#include <vector>
28#include <cstring>
29
30#include <errno.h>
31#include <unistd.h>
32#include <sys/time.h>
33#include <stdlib.h>
34
35
36#ifdef _WIN32 // Bugzilla 40710
37#include <windows.h>
38#include <winbase.h>
39#include <winsock.h>
40#else
41#include <netinet/in.h>
42#include <sys/socket.h>
43#include <arpa/inet.h>
44#include <netdb.h>
45#endif
46
47enum { MAX_HOSTNAME_SIZE=255 };
48
49/*
50 * CppUnitServer protocol constants
51 */
52static const std::string TRACE_START = "%TRACES ";
53static const std::string TRACE_END = "%TRACEE ";
54static const std::string TEST_RUN_START = "%TESTC ";
55static const std::string TEST_START = "%TESTS ";
56static const std::string TEST_END = "%TESTE ";
57static const std::string TEST_ERROR = "%ERROR ";
58static const std::string TEST_FAILED = "%FAILED ";
59static const std::string TEST_RUN_END = "%RUNTIME";
60static const std::string TEST_STOPPED = "%TSTSTP ";
61static const std::string TEST_TREE = "%TSTTREE";
62
63TestRunnerClient::TestRunnerClient()
64{
65 fTestResult = 0;
66 fClientSocket = -1;
67 fPort = 0;
68 fKeepAlive = 0;
69 fDebugMode = 0;
70
71 fHost = (char *) malloc(MAX_HOSTNAME_SIZE);
72 strcpy(fHost, "");
73}
74
75TestRunnerClient::~TestRunnerClient() {
76
77 if (fHost != NULL) {
78 free(fHost);
79 }
80}
81
82int TestRunnerClient::Run()
83{
84 if (fDebugMode)
85 {
86 std::cerr << "TestRunnerClient: Starting client." << std::endl;
87 }
88
89 if (Connect() == -1) {
90 return -1;
91 }
92
93 InstallListeners();
94
95 RunTests();
96
97 UninstallListeners();
98
99 if(fTestResult != NULL)
100 {
101 fTestResult->stop();
102 fTestResult= NULL;
103 }
104
105 ShutDown();
106
107 return 0;
108}
109
110void TestRunnerClient::Init(int n, char *args[])
111{
112 ParseCommandLine(n, args);
113 DefineHostName();
114}
115
116void TestRunnerClient::ParseCommandLine(int n, char *args[])
117{
118 // parse all arguments passed by args
119 for(int i = 0; i < n; i++)
120 {
121 std::string arg(args[i]);
122
123 // port option
124 std::string portOption("-port=");
125 int pos = arg.find(portOption);
126 if(pos> -1)
127 {
128 std::string v = arg.substr(pos + portOption.length(), arg.length());
129 fPort = atoi(v.c_str());
130 }
131
132 // debug option
133 std::string debugOption("-debug");
134 pos = arg.find(debugOption);
135 if(pos> - 1)
136 {
137 fDebugMode = 1;
138 }
139 }
140}
141
142void TestRunnerClient::DefineHostName()
143{
144 // set fHost to hostname or localhost
145 int ret = gethostname(fHost, MAX_HOSTNAME_SIZE);
146 if (ret == -1)
147 {
148 strcpy(fHost, "localhost");
149 }
150}
151
152int TestRunnerClient::Connect()
153{
154
155#ifdef _WIN32 // Bugzilla 40710
156 if (fDebugMode)
157 {
158 std::cerr << "TestRunnerClient: Starting Windows Sockets WSAStartup()." << std:endl;
159 }
160
161 // start up Windows Sockets
162 WSADATA WSAData;
163 int result = WSAStartup (MAKEWORD(1, 1), &WSAData);
164 if (result != NO_ERROR)
165 {
166 std::cerr << "TestRunnerClient: WSAStartup() failed! Error code: " << result << std::endl;
167 return -1;
168 }
169#endif
170
171 if (fDebugMode)
172 {
173 std::cerr << "TestRunnerClient: Trying to connect to " << fHost << ":" << fPort << std::endl;
174 }
175
176 fClientSocket = socket(AF_INET, SOCK_STREAM, 0);
177 if (fClientSocket == -1)
178 {
179 std::cerr << "TestRunnerClient: Socket creation failed! error code: " << fClientSocket << std::endl;
180 return -1;
181 }
182
183 struct hostent *host = gethostbyname(fHost);
184 if (host == NULL)
185 {
186 std::cerr << "TestRunnerClient: Cannot find host address for " << fHost << "." << std::endl;
187 fClientSocket = -1;
188 return -1;
189 }
190
191 struct sockaddr_in name;
192 memset((void *)&name, 0, sizeof(struct sockaddr_in));
193 name.sin_family = AF_INET;
194 name.sin_port = htons(fPort);
195
196 memcpy(&name.sin_addr, host->h_addr, host->h_length);
197
198 if (fDebugMode) {
199 std::cerr << "TestRunnerClient: Waiting for the JVM to listen ... (trying 3 times)" << std::endl;
200 }
201
202 int ret = -1;
203 int j = 0;
204 while ((j < 3) && (ret == -1))
205 {
206 ret = ::connect(fClientSocket, (struct sockaddr *) &name, sizeof(struct sockaddr_in));
207 if (ret == -1)
208 {
209 if (fDebugMode) {
210 std::cerr << "TestRunnerClient: Connection request, waiting 1 second. "
211 << ((j-3)*-1) << " times left." << std::endl;
212 }
213 PrivateSleep(1000);
214 j++;
215 }
216 }
217 if (ret == -1)
218 {
219 std::cerr << "TestRunnerClient: No connection established. Error code: " << errno << std::endl;
220 fClientSocket = -1;
221 return -1;
222 }
223
224 if (fDebugMode) {
225 std::cerr << "TestRunnerClient: Connection established." << std::endl;
226 }
227 return 0;
228}
229
230void TestRunnerClient::InstallListeners()
231{
232 fTestResult = new CppUnit::TestResult();
233 fTestResult->addListener(this);
234}
235
236void TestRunnerClient::UninstallListeners()
237{
238 fTestResult->removeListener(this);
239}
240
241void TestRunnerClient::RunTests()
242{
243
244 CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
245 CppUnit::Test *suite = registry.makeTest();
246 int count = suite->countTestCases();
247 NotifyTestRunStarted(count);
248
249 if (count == 0)
250 {
251 NotifyTestRunEnded(0);
252 }
253
254 long startTime = CurrentTimeMillis();
255 if (fDebugMode)
256 {
257 std::cerr <<"TestRunnerClient: Start sending test case tree ..." << std::endl;
258 }
259
260 SendTestTree(suite);
261
262 int elapsedTime = CurrentTimeMillis() - startTime;
263 if (fDebugMode) {
264 std::cerr << "TestRunnerClient: Done sending test case tree. Elapsed time is "
265 << elapsedTime << "ms." << std::endl;
266 }
267
268 long testStartTime = CurrentTimeMillis();
269 if (fDebugMode) {
270 std::cerr << "TestRunnerClient: Test start time is " << testStartTime
271 << "ms." << std::endl;
272 }
273
274 suite->run(fTestResult);
275
276 if (fTestResult == NULL || fTestResult->shouldStop())
277 {
278 NotifyTestRunStopped(CurrentTimeMillis() - testStartTime);
279 }
280 else
281 {
282 NotifyTestRunEnded(CurrentTimeMillis() - testStartTime);
283 }
284}
285
286void TestRunnerClient::ShutDown()
287{
288 if (fClientSocket != -1)
289 {
290 if (fDebugMode) {
291 std::cerr << "TestRunnerClient: Closing connection to CppUnit sever at "
292 << fHost << ":" << fPort << std::endl;
293 }
294
295#ifdef _WIN32 // Bugzilla 40710
296 // TODO: std:err output for error return codes
297 closesocket(fClientSocket);
298 WSACleanup();
299#else
300 int result = close(fClientSocket);
301 if (result != 0)
302 {
303 std::cerr << "TestRunnerClient: Close connection error: " << errno << std::endl;
304 }
305#endif
306
307 fClientSocket = -1;
308 }
309}
310
311void TestRunnerClient::Stop()
312{
313 if (fTestResult != NULL)
314 {
315 fTestResult->stop();
316 }
317}
318
319void TestRunnerClient::SendTestTree(CppUnit::Test *test)
320{
321 if (typeid(*test) == typeid(CppUnit::TestDecorator))
322 {
323 class TmpClass : public CppUnit::TestDecorator {
324
325 public:
326 TmpClass(Test *t):CppUnit::TestDecorator(t)
327 {
328 // nothing to do
329 }
330
331 ~TmpClass() // Bugzilla 39894
332 {
333 // nothing to do
334 }
335
336 CppUnit::Test *getTest()
337 {
338 return m_test;
339 }
340 };
341
342 TmpClass *t = (TmpClass *)test;
343 SendTestTree(t->getTest());
344 }
345 else if (typeid(*test) == typeid(CppUnit::TestSuite))
346 {
347 CppUnit::TestSuite *suite = (CppUnit::TestSuite *)test;
348 const std::vector<CppUnit::Test *> &x = suite->getTests();
349
350 std::ostringstream os;
351 os << suite->getName() << ",true," << x.size();
352 NotifyTestTreeEntry(os.str());
353
354 for(unsigned int i=0; i < x.size(); i++)
355 {
356 SendTestTree(x[i]);
357 }
358 }
359 else
360 {
361 std::ostringstream os;
362 os << test->getName() << ",false," << test->countTestCases();
363 NotifyTestTreeEntry(os.str());
364 }
365}
366
367void TestRunnerClient::SendMessage(std::string msg)
368{
369 if (fClientSocket == -1)
370 {
371 return;
372 }
373
374#ifdef _WIN32 // Bugzilla 40710
375 send (fClientSocket, msg.c_str(), msg.length(), 0);
376 send (fClientSocket, "\n", 1, 0);
377#else
378 write(fClientSocket, msg.c_str(), msg.length());
379 write(fClientSocket, "\n", 1);
380#endif
381
382 if (fDebugMode)
383 {
384 std::cerr << "TestRunnerClient: Sent message \"" << msg << "\""
385 << std::endl;
386 }
387}
388
389void TestRunnerClient::NotifyTestRunStarted(int testCount)
390{
391 std::ostringstream os;
392 os << TEST_RUN_START << testCount;
393 SendMessage(os.str());
394}
395
396void TestRunnerClient::NotifyTestRunEnded(long elapsedTime)
397{
398 std::ostringstream os;
399 os << TEST_RUN_END << elapsedTime;
400 SendMessage(os.str());
401}
402
403void TestRunnerClient::NotifyTestRunStopped(long elapsedTime)
404{
405 std::ostringstream os;
406 os << TEST_STOPPED << elapsedTime;
407 SendMessage(os.str());
408}
409
410void TestRunnerClient::NotifyTestTreeEntry(std::string treeEntry)
411{
412 SendMessage(TEST_TREE + treeEntry);
413}
414
415void TestRunnerClient::NotifyTestStarted(std::string testName)
416{
417 SendMessage(TEST_START + testName);
418}
419
420void TestRunnerClient::NotifyTestEnded(std::string testName)
421{
422 SendMessage(TEST_END + testName);
423}
424
425void TestRunnerClient::NotifyTestFailed(std::string status, std::string testName, std::string trace)
426{
427 SendMessage(status + testName);
428 SendMessage(TRACE_START);
429 SendMessage(trace);
430 SendMessage(TRACE_END);
431}
432
433// From TestListener
434void TestRunnerClient::startTest(CppUnit::Test *test)
435{
436 NotifyTestStarted(test->getName());
437}
438
439// From TestListener
440void TestRunnerClient::addFailure(const CppUnit::TestFailure &failure)
441{
442 if(failure.isError())
443 {
444 NotifyTestFailed(TEST_ERROR,failure.failedTestName(),GetTrace(failure));
445 }
446 else
447 {
448 NotifyTestFailed(TEST_FAILED,failure.failedTestName(),GetTrace(failure));
449 }
450}
451
452// From TestListener
453void TestRunnerClient::endTest(CppUnit::Test *test)
454{
455 NotifyTestEnded(test->getName());
456}
457
458std::string TestRunnerClient::GetTrace(const CppUnit::TestFailure &failure)
459{
460 std::ostringstream os;
461
462 CppUnit::Exception *e=failure.thrownException();
463 if(e->sourceLine().lineNumber()!=-1)
464 {
465 os << "File " << e->sourceLine().fileName() << ":" << e->sourceLine().lineNumber() << "\n";
466 }
467 else
468 {
469 os << "File Unknown:1\n";
470 }
471 /* TODO: expected, actual value implementation
472 if(typeid(*e)==typeid(CppUnit::NotEqualException))
473 {
474 CppUnit::NotEqualException *ne=(CppUnit::NotEqualException *)e;
475
476 os << "Expected Value: " << ne->expectedValue() << "\n";
477 os << "Actual Value: " << ne->expectedValue() << "\n";
478 os << "Additional Message: " << ne->additionalMessage() << "\n";
479 }
480 else
481 {
482 End */
483 os << "Message: " << std::string(e->what()) << "\n";
484 /* } */
485
486 return(os.str());
487}
488
489long TestRunnerClient::CurrentTimeMillis()
490{
491#ifdef _WIN32 // Bugzilla 40710
492 unsigned long long p;
493 __asm__ __volatile__ ("rdtsc" : "=A" (p));
494 return (unsigned long)p;
495#else
496 struct timeval tv;
497 gettimeofday(&tv, NULL);
498
499 return((long)(tv.tv_sec*1000) + (tv.tv_usec/1000));
500#endif
501}
502
503void TestRunnerClient::PrivateSleep(int millisecs)
504{
505 struct timeval delta;
506 delta.tv_sec = (millisecs * 1000L) / 1000000L;
507 delta.tv_usec = (millisecs * 1000L) % 1000000L;
508 select (0, NULL, NULL, NULL, &delta);
509}
510
511/*!
512 * This is the main routine. The TestRunnerClient is initialized and run. The
513 * CppUnit tests are created, executed, and sent to the CppUnitServer.
514 * If no connection to the CppUnitServer was established the CppUnit tests are
515 * displayed on the console.
516 *
517 * @return <code>0</code> if the results of the CppUnit tests were sent to the
518 * CppUnitServer successfully.
519 * <code>-1</code> if a connection could not be established to the
520 * CppUnitServer.
521 */
522int CPPUNIT_MAIN(int n, char *arg[])
523{
524 TestRunnerClient client;
525
526 client.Init(n, arg);
527 int ret = client.Run();
528 if (ret == -1)
529 {
530 CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
531 CppUnit::Test *suite = registry.makeTest();
532
533 CppUnit::TextUi::TestRunner *runner = NULL;
534 runner = new CppUnit::TextUi::TestRunner();
535 runner->addTest(suite);
536 runner->run();
537 }
538
539 exit(ret);
540}
541
542#endif /*CPPUNIT_MAIN*/
Note: See TracBrowser for help on using the repository browser.