source: TestRunnerClient.cpp@ 327364

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 327364 was 861874, checked in by Frederik Heber <heber@…>, 14 years ago

libMolecuilderAction is now a shared lib via libtool.

This is all taken from the example available at http://www.openismus.com/documents/linux/building_libraries/building_libraries/building_libraries.shtml.

Necessary changes:

  • ValueStorage is now part of Actions, not of UIElements anymore (which is actually as it should have been right away, only Dialog uses ValueStorage and for all Actions ValueStorage is the simple adapter pattern to MapOfActions needed the relax (compilation) dependencies).
  • new files:
    • config/ltmain.sh (scipt for libtool)
    • libmolecuilder_config.h.in (extra config.h which is copied along with lib to contain how it has been compiled)
    • molecuilder.pc.in (package config information
  • BUGFIX: m4/gwqt4.m4 added -L$X_libraries, however $X_libraries was nowhere set and libtool admonished the empty "-L"
  • libMolecuilderUI now depends on libMolecuilderAction
  • all unit tests now have libMolecuilderAction and libMolecuilderUI due to non-interactive calls of actions
  • 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
47#define 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.