// Reset test case and underlaying information (steps context)
bool reset(bool hard /* hard reset includes in-progress test cases */) throw();
+ // Check for clear (destroy steps)
+ bool safeToClear(); // false if something pending (running threads steps)
+
// getters
const unsigned int &getId() const throw() { return a_id; }
const std::string &getDescription() const throw() { return a_description; }
// through the time manager. The first call to this method will start the time trigger system and check for new test cases to be launched.
bool configureTTPS(int testTicksPerSecond) throw();
- bool clearPool() throw();
+ bool clearPool(std::string &result) throw();
bool resetPool(bool hard /* hard reset includes in-progress test cases */) throw();
void setPoolRepeats(int repeats) throw() { a_poolRepeats = repeats; }
int getPoolRepeats() const throw() { return a_poolRepeats; }
#include <string>
#include <vector>
#include <thread>
+#include <atomic>
// Project
#include <anna/core/DataBlock.hpp>
public:
TestStepTimeout(TestCase *testCase) : TestStep(testCase), a_timeout(0), a_timer(NULL) { a_type = Type::Timeout; }
+ ~TestStepTimeout() { do_reset(); }
// setter & getters
void setTimeout(const anna::Millisecond &t) throw() { a_timeout = t; }
a_expired(false),
a_originHost(NULL),
a_waitForRequestStepNumber(-1) {;}
- ~TestStepSendDiameterXml() {;}
+ ~TestStepSendDiameterXml() { do_reset(); }
// setter & getters
void setOriginHost(anna::diameter::comm::OriginHost *host) throw() { a_originHost = host; }
public:
TestStepDelay(TestCase *testCase) : TestStep(testCase), a_delay(0), a_timer(NULL) { a_type = Type::Delay; }
+ ~TestStepDelay() { do_reset(); }
// setter & getters
void setDelay(const anna::Millisecond &d) throw() { a_delay = d; }
a_clientSession = NULL;
a_serverSession = NULL;
}
- ~TestStepWaitDiameter() {;}
+ ~TestStepWaitDiameter() { do_reset(); }
// setter & getters
void setCondition(bool fromEntity,
std::string a_script;
std::thread a_thread;
- bool a_threadRunning;
+ std::atomic<bool> a_threadRunning;
bool a_threadDeprecated;
int a_resultCode;
std::string a_errorMsg;
public:
TestStepCmd(TestCase *testCase) : TestStep(testCase), a_threadRunning(false), a_threadDeprecated(false), a_resultCode(-2)/*, a_output("")*/, a_errorMsg(""), a_childPid(-1) { a_type = Type::Cmd; }
+ ~TestStepCmd() { do_reset(); }
// setter & getters
- void setThreadRunning(bool running) throw() { a_threadRunning = running; }
+ void setThreadRunning() throw() { a_threadRunning = true; }
+ void setThreadNotRunning() throw() { a_threadRunning = false; }
+ bool threadRunning() const throw() { return a_threadRunning; }
+ bool threadNotRunning() const throw() { return !a_threadRunning; }
void setResultCode(int rc) throw() { a_resultCode = rc; }
int getResultCode() const throw() { return a_resultCode; }
public:
TestStepIpLimit(TestCase *testCase) : TestStep(testCase), a_ipLimit(1) { a_type = Type::IpLimit; }
+ ~TestStepIpLimit() { do_reset(); }
// setter & getters
void setIpLimit(unsigned int limit) throw() { a_ipLimit = limit; }
}
TestCase::~TestCase() {
+ // TestCase should not be deleted until is safeToClear()
reset(true); // hard reset
std::vector<TestStep*>::const_iterator it;
for (it = a_steps.begin(); it != a_steps.end(); it++) delete (*it);
}
+
const char* TestCase::asText(const State::_v state)
throw() {
static const char* text [] = { "Initialized", "InProgress", "Failed", "Success" };
return true;
}
+bool TestCase::safeToClear() {
+
+ // Check if any step is running (command steps):
+ std::vector<TestStep*>::const_iterator it;
+ for (it = a_steps.begin(); it != a_steps.end(); it++) {
+ if ((*it)->getType() == TestStep::Type::Cmd) {
+ const TestStepCmd *tscmd = static_cast<const TestStepCmd*>(*it);
+ if(tscmd->threadRunning())
+ return false;
+ }
+ }
+
+ return true;
+}
+
void TestCase::assertInitialized() const throw(anna::RuntimeException) {
if (isFinished())
throw anna::RuntimeException(anna::functions::asString("Cannot program anymore. The test case %llu (%s) has finished. You must reset it to append new steps (or do it during execution, which is also allowed).", a_id, a_description.c_str()), ANNA_FILE_LOCATION);
return result;
}
-bool TestManager::clearPool() throw() {
- if (!tests()) return false;
- for (test_pool_it it = a_testPool.begin(); it != a_testPool.end(); it++) delete it->second;
- // TODO: stop the possible command threads or there will be a core dump
+bool TestManager::clearPool(std::string &result) throw() {
+
+ result = "";
+
+ if (!tests()) {
+ result = "there are not programmed test cases to be removed";
+ return false;
+ }
+
+ int total = a_testPool.size();
+ int unsafe = 0;
+
+ test_pool_it it;
+ for (it = a_testPool.begin(); it != a_testPool.end(); it++) {
+ if (!it->second->safeToClear()) { // Check that non pending threads are running (command steps):
+ unsafe++;
+ }
+ }
+
+ if (unsafe > 0) {
+ result = "some test cases cannot be removed (";
+ result += anna::functions::asString(unsafe);
+ result += "/";
+ result += anna::functions::asString(total);
+ result += "), mainly those having running-thread steps. Check for stuck external procedures or try later.";
+ return false;
+ }
+
+ // Here is safe to clear:
+ for (it = a_testPool.begin(); it != a_testPool.end(); it++) {
+ delete it->second;
+ }
a_testPool.clear();
a_key1TestCaseMap.clear();
a_poolCycle = 1;
configureTTPS(0); // stop
a_statSummary.clear();
+
return true;
}
if (a_clock) {
result->createAttribute("AsynchronousSendings", a_synchronousAmount);
int ticksPerSecond = (a_synchronousAmount * 1000) / a_clock->getTimeout();
- result->createAttribute("TicksPerSecond", ticksPerSecond);
+ result->createAttribute("TicksPerSecond", a_clock->isActive() ? ticksPerSecond : 0);
}
if (a_currentTestIt != a_testPool.end()) {
result->createAttribute("CurrentTestCaseId", (*a_currentTestIt).first);
void cmdRunOnThread (TestStepCmd *step, const std::string &cmd) {
- // Thread running:
- step->setThreadRunning(true);
+ // Thread running (will be set to false at complete()):
+ step->setThreadRunning();
int status = -2;
std::cout << "Executed Command Test Step (" << a_script << ") [rc=" << a_resultCode << "]" << std::endl;
}
- a_threadRunning = false;
+ setThreadNotRunning();
if (a_threadDeprecated) {
a_threadDeprecated = false;
do_reset();