#include <fstream>
#include <sstream>
#include <cmath>
-
+#include <iterator>
+#include <vector>
#include <iostream>
// Project
TestCase::~TestCase() {
reset(true); // hard reset
- std::vector<TestStep*>::const_iterator it;
- for (it = a_steps.begin(); it != a_steps.end(); it++) delete (*it);
+ std::map<int/* step number*/, TestStep*>::const_iterator it;
+ for (it = a_steps.begin(); it != a_steps.end(); it++) delete (it->second);
}
const char* TestCase::asText(const State::_v state)
int steps = a_steps.size();
if (steps != 0) {
result->createAttribute("NumberOfTestSteps", steps);
- std::vector<TestStep*>::const_iterator it;
+ std::map<int/* step number*/, TestStep*>::const_iterator it;
for (it = a_steps.begin(); it != a_steps.end(); it++) {
- (*it)->asXML(result);
+ it->second->asXML(result);
}
}
}
bool TestCase::hasSameCondition(const TestCondition &condition) const throw() {
- std::vector<TestStep*>::const_iterator it;
+ std::map<int/* step number*/, TestStep*>::const_iterator it;
TestStepWait *step;
for (it = a_steps.begin(); it != a_steps.end(); it++) {
- if ((*it)->getType() != TestStep::Type::Wait) continue;
- step = (TestStepWait *)(*it);
+ if (it->second->getType() != TestStep::Type::Wait) continue;
+ step = (TestStepWait *)(it->second);
if (step->getCondition() == condition) return true;
}
return false;
if (done()) return false;
bool somethingDone = false;
- while ((*a_stepsIt)->execute()) { // executes returns 'true' if the next step must be also executed (execute until can't stand no more)
+ while (a_stepsIt->second->execute()) { // executes returns 'true' if the next step must be also executed (execute until can't stand no more)
nextStep();
// Check end of the test case:
if (done()) return false;
// Clean stage ////////////////////////////
// id is kept
- std::vector<TestStep*>::iterator it;
+ std::map<int/* step number*/, TestStep*>::iterator it;
for (it = a_steps.begin(); it != a_steps.end(); it++)
- (*it)->reset();
+ it->second->reset();
a_debugSummary.clear();
a_startTime = 0;
assertInitialized();
TestStepTimeout *step = new TestStepTimeout(this);
step->setTimeout(timeout);
- a_steps.push_back(step);
+ addStep(step);
}
void TestCase::addSendxml2e(const anna::DataBlock &db, RealmNode *realm, int stepNumber) throw(anna::RuntimeException) {
assertMessage(db, true /* to entity */);
if (stepNumber != -1) {
- int steps = a_steps.size();
- int stepIndx = stepNumber - 1;
- if ((stepIndx < 0) || (stepIndx > (a_steps.size()-1)))
- throw anna::RuntimeException(anna::functions::asString("Step number (%d) out of range (test case %llu)", stepNumber, a_id), ANNA_FILE_LOCATION);
+ const TestStep *stepReferred = getStep(stepNumber);
+ if (!stepReferred)
+ throw anna::RuntimeException(anna::functions::asString("Step number (%d) do not exists (test case %llu)", stepNumber, a_id), ANNA_FILE_LOCATION);
- TestStep *stepReferred = a_steps[stepIndx];
if (stepReferred->getType() != TestStep::Type::Wait)
throw anna::RuntimeException(anna::functions::asString("Step number (%d) must refer to a 'wait' step (test case %llu)", stepNumber, a_id), ANNA_FILE_LOCATION);
- const TestCondition &tc = (static_cast<TestStepWait*>(stepReferred))->getCondition();
+ const TestCondition &tc = (static_cast<const TestStepWait*>(stepReferred))->getCondition();
if (tc.getCode() == "0") { // if regexp used, is not possible to detect this kind of errors
throw anna::RuntimeException(anna::functions::asString("Step number (%d) must refer to a 'wait for request' step (test case %llu)", stepNumber, a_id), ANNA_FILE_LOCATION);
}
step->setMsgDataBlock(db);
step->setRealmNode(realm);
step->setWaitForRequestStepNumber(stepNumber); // -1 means, no reference
- a_steps.push_back(step);
+ addStep(step);
}
void TestCase::addSendxml2c(const anna::DataBlock &db, RealmNode *realm, int stepNumber) throw(anna::RuntimeException) {
TestStepSendxml2c *step = new TestStepSendxml2c(this);
step->setMsgDataBlock(db);
step->setRealmNode(realm);
- a_steps.push_back(step);
+ addStep(step);
}
void TestCase::addDelay(const anna::Millisecond &delay) throw(anna::RuntimeException) {
assertInitialized();
TestStepDelay *step = new TestStepDelay(this);
step->setDelay(delay);
- a_steps.push_back(step);
+ addStep(step);
}
void TestCase::addWait(bool fromEntity,
else {
if (hopByHop != "") {
if (hopByHop[0] == '#') {
- int steps = a_steps.size();
- if (steps == 0)
+ if (steps() == 0)
throw anna::RuntimeException(anna::functions::asString("No steps has been programmed, step reference is nonsense (test case %llu)", a_id), ANNA_FILE_LOCATION);
int stepNumber = atoi(hopByHop.substr(1).c_str());
- int stepIndx = stepNumber - 1;
- if ((stepIndx < 0) || (stepIndx > (steps-1)))
- throw anna::RuntimeException(anna::functions::asString("Step reference number %d out of range [1-%d]", stepNumber, steps), ANNA_FILE_LOCATION);
- TestStep *stepReferred = a_steps[stepIndx];
+ const TestStep *stepReferred = getStep(stepNumber);
+ if (!stepReferred)
+ throw anna::RuntimeException(anna::functions::asString("Step reference number (%d) do not exists (test case %llu)", stepNumber, a_id), ANNA_FILE_LOCATION);
+
if (stepReferred->getType() != TestStep::Type::Sendxml2e && stepReferred->getType() != TestStep::Type::Sendxml2c)
throw anna::RuntimeException(anna::functions::asString("Step number must refer to a 'sendxml2e' or 'sendxml2c' step (test case %llu)", a_id), ANNA_FILE_LOCATION);
- const anna::DataBlock &db = (static_cast<TestStepSendxml*>(stepReferred))->getMsgDataBlock();
+ const anna::DataBlock &db = (static_cast<const TestStepSendxml*>(stepReferred))->getMsgDataBlock();
bool isAnswer = anna::diameter::codec::functions::isAnswer(db);
if (isAnswer)
throw anna::RuntimeException(anna::functions::asString("Step number must refer to a request message (test case %llu)", a_id), ANNA_FILE_LOCATION);
anna::Logger::warning(anna::functions::asString("The same wait condition has already been programmed in this test case (%llu). Are you sure ?", a_id), ANNA_FILE_LOCATION);
);
- a_steps.push_back(step);
+ addStep(step);
}
void TestCase::addWaitRegexp(bool fromEntity, const std::string ®exp) throw(anna::RuntimeException) {
anna::Logger::warning(anna::functions::asString("The same wait condition has already been programmed in this test case (%llu). Are you sure ?", a_id), ANNA_FILE_LOCATION);
);
- a_steps.push_back(step);
+ addStep(step);
}
void TestCase::addCommand(const std::string &cmd) throw(anna::RuntimeException) {
TestStepCmd *step = new TestStepCmd(this);
step->setScript(cmd);
- a_steps.push_back(step);
+ addStep(step);
}
TestStepWait *TestCase::searchNextWaitConditionFulfilled(const anna::DataBlock &message, bool waitFromEntity) throw() {
TestStepWait *result;
- for (std::vector<TestStep*>::const_iterator it = a_stepsIt /* current */; it != a_steps.end(); it++) {
- if ((*it)->getType() != TestStep::Type::Wait) continue;
- if ((*it)->isCompleted()) continue;
- result = (TestStepWait*)(*it);
+ for (std::map<int/* step number*/, TestStep*>::const_iterator it = a_stepsIt /* current */; it != a_steps.end(); it++) {
+ if (it->second->getType() != TestStep::Type::Wait) continue;
+ if (it->second->isCompleted()) continue;
+ result = (TestStepWait*)(it->second);
if ((result->getCondition().receivedFromEntity() == waitFromEntity) && (result->fulfilled(message)))
return result;
}
}
const TestStep *TestCase::getStep(int stepNumber) const throw() {
- int stepIndx = stepNumber - 1;
- if ((stepIndx < 0) || (stepIndx > (a_steps.size()-1))) return NULL;
- std::vector<TestStep*>::const_iterator it = (a_steps.begin() + stepNumber);
- return (*it);
+ std::map<int/* step number*/, TestStep*>::const_iterator it = a_steps.find(stepNumber);
+ if (it != a_steps.end()) return it->second;
+ return NULL;
}
if (a_executed) return false; // avoid repeating (this implies amount consumption)
}
- LOGDEBUG(anna::Logger::debug(anna::functions::asString("EXECUTING %s (step number %d) for Test Case %llu (%p) (%p)", asText(a_type), a_number, a_testCase->getId(), (TestCaseStep*)this, this), ANNA_FILE_LOCATION));
+ LOGDEBUG(anna::Logger::debug(anna::functions::asString("EXECUTING %s (step number %d) for Test Case %llu (%p)", asText(a_type), a_number, a_testCase->getId(), this), ANNA_FILE_LOCATION));
setBeginTimestamp(anna::functions::millisecond());
a_executed = true;
return do_execute();
}
void TestStep::complete() throw() {
- LOGDEBUG(anna::Logger::debug(anna::functions::asString("COMPLETE %s (step number %d) for Test Case %llu (%p) (%p)", asText(a_type), a_number, a_testCase->getId(), (TestCaseStep*)this, this), ANNA_FILE_LOCATION));
+ LOGDEBUG(anna::Logger::debug(anna::functions::asString("COMPLETE %s (step number %d) for Test Case %llu (%p)", asText(a_type), a_number, a_testCase->getId(), this), ANNA_FILE_LOCATION));
a_completed = true;
setEndTimestamp(anna::functions::millisecond());
do_complete();
}
void TestStep::reset() throw() {
- LOGDEBUG(anna::Logger::debug(anna::functions::asString("RESET %s (step number %d) for Test Case %llu (%p) (%p)", asText(a_type), a_number, a_testCase->getId(), (TestCaseStep*)this, this), ANNA_FILE_LOCATION));
+ LOGDEBUG(anna::Logger::debug(anna::functions::asString("RESET %s (step number %d) for Test Case %llu (%p)", asText(a_type), a_number, a_testCase->getId(), this), ANNA_FILE_LOCATION));
// type and testCase kept
a_completed = false;
a_executed = false;
}
void TestStepTimeout::do_reset() throw() {
- LOGDEBUG(anna::Logger::debug(anna::functions::asString("REXXXXXET %s for Test Case %llu (%p) (%p) (a_timer %p)", asText(a_type), a_testCase->getId(), (TestCaseStep*)this, this, a_timer), ANNA_FILE_LOCATION));
-
try {
TestManager::instantiate().cancelTimer(a_timer);
}
// Update sequence for answers:
if (a_waitForRequestStepNumber != -1) { // is an answer: try to copy sequence information; alert about Session-Id discrepance
// Request which was received:
- tsw = (const TestStepWait*)(a_testCase->getStep(a_waitForRequestStepNumber));
+ tsw = static_cast<const TestStepWait*>(a_testCase->getStep(a_waitForRequestStepNumber));
+
const anna::DataBlock &request = tsw->getMsgDataBlock();
anna::diameter::HopByHop hbh = anna::diameter::codec::functions::getHopByHop(request);
anna::diameter::EndToEnd ete = anna::diameter::codec::functions::getEndToEnd(request);
+
// Update sequence:
anna::diameter::codec::functions::setHopByHop(a_message, hbh);
anna::diameter::codec::functions::setEndToEnd(a_message, ete);
// Check Session-Id for warning ...
std::string sessionIdAnswer = anna::diameter::helpers::base::functions::getSessionId(a_message);
std::string sessionIdRequest = anna::diameter::helpers::base::functions::getSessionId(request);
+
if (sessionIdRequest != sessionIdAnswer) {
s_warn = anna::functions::asString("Sending an answer which Session-Id (%s) is different than supposed corresponding request (%s)", sessionIdAnswer.c_str(), sessionIdRequest.c_str());
LOGWARNING(anna::Logger::warning(s_warn, ANNA_FILE_LOCATION));
if (msg != "") result->createAttribute("MatchedMessage", msg);
if (xmlmsg != "") result->createAttribute("MatchedXMLMessage", xmlmsg);
+ if (a_clientSession) result->createAttribute("ClientSessionOrigin", anna::functions::asString("%p", a_clientSession));
+ if (a_serverSession) result->createAttribute("ServerSessionOrigin", anna::functions::asString("%p", a_serverSession));
return result;
}