From: Eduardo Ramos Testillano (ert) Date: Mon, 22 Nov 2021 21:57:05 +0000 (+0100) Subject: Allow to clear an specific test case X-Git-Url: https://git.teslayout.com/public/public/public/?p=anna.git;a=commitdiff_plain;h=f34b8069233e9e09208339bb79d8576c1ff962e1 Allow to clear an specific test case --- diff --git a/CMakeLists.txt b/CMakeLists.txt index fd3d498..ad56e32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ enable_language(C CXX) # Project version set(VERSION_MAJOR 1) set(VERSION_MINOR 0) -set(VERSION_PATCH 3) +set(VERSION_PATCH 4) # Dynamic libraries not linked to build tree: set(CMAKE_SKIP_RPATH TRUE) diff --git a/example/diameter/launcher/EventOperation.cpp b/example/diameter/launcher/EventOperation.cpp index 2b42486..8b45e61 100644 --- a/example/diameter/launcher/EventOperation.cpp +++ b/example/diameter/launcher/EventOperation.cpp @@ -1105,12 +1105,23 @@ bool EventOperation::test__finished(std::string &response) { return true; // OK } -bool EventOperation::test__clear(std::string &response) { +bool EventOperation::test__clear(std::string &response, int id) { Launcher& my_app = static_cast (anna::app::functions::getApp()); anna::testing::TestManager &testManager = anna::testing::TestManager::instantiate(); - return testManager.clearPool(response); + if (id == -1) { + return testManager.clearPool(response); + } + + if (!testManager.findTestCase(id)) { + response += "cannot found test id ("; + response += anna::functions::asString(id); + response += ")"; + return false; + } + + return testManager.clearTestCase(response, id); } bool EventOperation::test__junit(std::string &response, const std::string & targetFile) { diff --git a/example/diameter/launcher/EventOperation.hpp b/example/diameter/launcher/EventOperation.hpp index dd54020..c88cb3c 100644 --- a/example/diameter/launcher/EventOperation.hpp +++ b/example/diameter/launcher/EventOperation.hpp @@ -110,7 +110,7 @@ public: bool test__auto_reset(std::string &response, bool soft_hard); bool test__initialized(std::string &response); bool test__finished(std::string &response); - bool test__clear(std::string &response); + bool test__clear(std::string &response, int id = -1 /* all */); bool test__junit(std::string &response, const std::string & targetFile); bool test__summary_counts(std::string &response); bool test__summary_states(std::string &response); diff --git a/example/diameter/launcher/MyHandler.cpp b/example/diameter/launcher/MyHandler.cpp index dfc29bd..1a7fdc5 100644 --- a/example/diameter/launcher/MyHandler.cpp +++ b/example/diameter/launcher/MyHandler.cpp @@ -490,7 +490,9 @@ bool MyHandler::doPOST(const std::string &uri, const nlohmann::json &j, std::str result = eop.test__finished(response); } else if (opType == "/test-clear") { - result = eop.test__clear(response); + auto it = j.find("id"); + int id = (it != j.end() && it->is_number_integer()) ? it->get() : -1; // default is: all + result = eop.test__clear(response, id); } else if (opType == "/test-junit") { auto it = j.find("targetFile"); diff --git a/example/diameter/launcher/resources/HELP.md b/example/diameter/launcher/resources/HELP.md index 8429ef4..7a50b52 100644 --- a/example/diameter/launcher/resources/HELP.md +++ b/example/diameter/launcher/resources/HELP.md @@ -1793,7 +1793,13 @@ Makes interactive a specific test case id. The amount of 0, implies no execution #### POST /test-clear -**Request body**: none +**Request body**: + +``` +{ + ["id":[test identifier (integer: all by default (-1))]] +} +``` **Response body**: diff --git a/include/anna/testing/TestCase.hpp b/include/anna/testing/TestCase.hpp index 6eab8df..d17a9f8 100644 --- a/include/anna/testing/TestCase.hpp +++ b/include/anna/testing/TestCase.hpp @@ -42,7 +42,7 @@ namespace testing { class TestCase { void assertInitialized() const noexcept(false); - void assertMessage(const anna::DataBlock &db, bool toEntity) noexcept(false); + std::string assertMessage(const anna::DataBlock &db, bool toEntity) noexcept(false); public: @@ -124,6 +124,7 @@ public: // getters const unsigned int &getId() const { return a_id; } + const std::string &getKey() const { return a_key; } const std::string &getDescription() const { return a_description; } // setters @@ -145,6 +146,7 @@ public: private: // private members: unsigned int a_id; + std::string a_key; std::string a_description; std::vector a_steps; std::vector::const_iterator a_stepsIt; diff --git a/include/anna/testing/TestManager.hpp b/include/anna/testing/TestManager.hpp index a6b0c21..4b2fd23 100644 --- a/include/anna/testing/TestManager.hpp +++ b/include/anna/testing/TestManager.hpp @@ -158,6 +158,7 @@ class TestManager : public anna::timex::TimeEventObserver, public anna::Singleto // 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) ; + bool clearTestCase(std::string &result, unsigned int id) ; bool clearPool(std::string &result) ; bool resetPool(bool hard /* hard reset includes in-progress test cases */) ; void setPoolRepeats(int repeats) { a_poolRepeats = repeats; } diff --git a/source/testing/TestCase.cpp b/source/testing/TestCase.cpp index 991a254..c357e93 100644 --- a/source/testing/TestCase.cpp +++ b/source/testing/TestCase.cpp @@ -73,6 +73,7 @@ std::string TestCase::DebugSummary::asString() const { TestCase::TestCase(unsigned int id, const std::string &description) : a_id(id), + a_key(""), a_description((description != "") ? description : (anna::functions::asString("Testcase_%d", id))), a_state(State::Initialized), a_startTimestamp(0), @@ -107,6 +108,7 @@ anna::xml::Node* TestCase::asXML(anna::xml::Node* parent) const anna::xml::Node* result = parent->createChild("TestCase"); result->createAttribute("Id", a_id); + if (a_key != "") result->createAttribute("Key", a_key); result->createAttribute("Description", a_description); result->createAttribute("State", asText(a_state)); result->createAttribute("StartTimestamp", a_startTimestamp.asString()); @@ -311,7 +313,9 @@ void TestCase::assertInitialized() const noexcept(false) { 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); } -void TestCase::assertMessage(const anna::DataBlock &db, bool toEntity) noexcept(false) { +std::string TestCase::assertMessage(const anna::DataBlock &db, bool toEntity) noexcept(false) { + + std::string key; bool isRequest = anna::diameter::codec::functions::isRequest(db); bool registerKeys = ((isRequest && toEntity) || (!isRequest && !toEntity) /* (*) */); @@ -330,16 +334,19 @@ void TestCase::assertMessage(const anna::DataBlock &db, bool toEntity) noexcept( if (registerKeys) { TestManager &testManager = TestManager::instantiate(); - testManager.registerKey1(anna::diameter::helpers::base::functions::getSessionId(db), this); + key = anna::diameter::helpers::base::functions::getSessionId(db); + testManager.registerKey1(key, this); - std::string subscriberId = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(db, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_E164); - if (subscriberId == "") // try with IMSI - subscriberId = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(db, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_IMSI); + key = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(db, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_E164); + if (key == "") // try with IMSI + key = anna::diameter::helpers::dcca::functions::getSubscriptionIdData(db, anna::diameter::helpers::dcca::AVPVALUES__Subscription_Id_Type::END_USER_IMSI); - if (subscriberId != "") - testManager.registerKey2(subscriberId, this); + if (key != "") + testManager.registerKey2(key, this); } + + return key; } void TestCase::addTimeout(const anna::Millisecond &timeout) noexcept(false) { @@ -351,7 +358,7 @@ void TestCase::addTimeout(const anna::Millisecond &timeout) noexcept(false) { void TestCase::addSendDiameterXml2e(const anna::DataBlock &db, anna::diameter::comm::OriginHost *host, int stepNumber) noexcept(false) { assertInitialized(); - assertMessage(db, true /* to entity */); + a_key = assertMessage(db, true /* to entity */); if (stepNumber != -1) { const TestStep *stepReferred = getStep(stepNumber); @@ -376,7 +383,7 @@ void TestCase::addSendDiameterXml2e(const anna::DataBlock &db, anna::diameter::c void TestCase::addSendDiameterXml2c(const anna::DataBlock &db, anna::diameter::comm::OriginHost *host, int stepNumber) noexcept(false) { assertInitialized(); - assertMessage(db, false /* to client */); + a_key = assertMessage(db, false /* to client */); if (stepNumber != -1) { const TestStep *stepReferred = getStep(stepNumber); diff --git a/source/testing/TestManager.cpp b/source/testing/TestManager.cpp index e90d20d..b83f8d4 100644 --- a/source/testing/TestManager.cpp +++ b/source/testing/TestManager.cpp @@ -299,6 +299,36 @@ TestCase *TestManager::getTestCase(unsigned int id, const std::string &descripti return result; } +bool TestManager::clearTestCase(std::string &result, unsigned int id) { + result = ""; + + if (!tests()) { + result = "There are not programmed test cases to be removed"; + return false; + } + + test_pool_it it = ((id != -1) ? a_testPool.find(id) : a_currentTestIt); + if (it == a_testPool.end()) { + result = "Test case id provided not found"; + return false; + } + + if (!it->second->safeToClear()) { + result = "Test case id provided has running-thread steps. Check for stuck external procedures or try later."; + return false; + } + + a_testPool.erase(it); + + auto key1_it = a_key1TestCaseMap.find(it->second->getKey()); + if (key1_it != a_key1TestCaseMap.end()) a_key1TestCaseMap.erase(key1_it); + auto key2_it = a_key2TestCaseMap.find(it->second->getKey()); + if (key2_it != a_key2TestCaseMap.end()) a_key2TestCaseMap.erase(key2_it); + + result = "Provided test case has been dropped"; + return true; +} + bool TestManager::clearPool(std::string &result) { result = "";