}
}
+void Procedure::execute(const nlohmann::json &args, std::string &response) throw(anna::RuntimeException) {
+ execute(args.dump(), response);
+}
// Project
#include <anna/comm/comm.hpp>
+#include <anna/json/json.hpp>
class Procedure {
Procedure(anna::comm::Application *app) : a_app(app) {;}
virtual void execute(const std::string &args, std::string &response) throw(anna::RuntimeException);
+ virtual void execute(const nlohmann::json &args, std::string &response) throw(anna::RuntimeException);
};
#endif
void usage (std::string &response) {
response += "\n\nInvalid arguments. Provide these ones:";
response += "\n";
+ response += "\nSIGUSR2 Interface:";
response += "\n<initial sequence>|<final sequence>|<test timeout ms (0: no timeout step)>|<digits>|<CCR-I xml file>[|CCR-T xml file]";
response += "\n";
+ response += "\nREST Interface:";
+ response += "\n{";
+ response += "\n \"seqI\":\"<initial sequence>\"";
+ response += "\n ,\"seqF\":\"<final sequence>\"";
+ response += "\n ,\"msecsTimeout\":\"<test timeout ms (0: no timeout step)>\"";
+ response += "\n ,\"digits\":\"<digits>\"";
+ response += "\n ,\"ccrI\":\"<CCR-I xml file>\"";
+ response += "\n [,\"ccrT\":\"<CCR-T xml file>\"]";
+ response += "\n}";
+ response += "\n";
response += "\nSequences are parsed when needed, over AVPs or internal values:";
response += "\n";
response += "\nSession-Id: <DiameterIdentity>;<high 32 bits>;<low 32 bits>[;<optional value>]";
}
} // loop
- response = "Completed provision for pid "; response += anna::functions::asString(a_app->getPid()); response += "; range [";
+ response = "Completed provision: range [";
response += seq_i; response += ", "; response += seq_f; response += "]; scenary: ";
response += "CCR-Initial"; if (haveTermination) response += " + CCR-Termination";
}
+void Procedure::execute(const nlohmann::json &args, std::string &response) throw(anna::RuntimeException) {
+
+ // Build the arguments string and call the previous centralized logic procedure execution:
+ // <initial sequence>|<final sequence>|<test timeout ms (0: no timeout step)>|<digits>|<CCR-I xml file>[|CCR-T xml file]
+ const char *arg_names[6] = { "seqI", "seqF", "msecsTimeout", "digits", "ccrI", "ccrT" };
+ std::string args_string, arg, pipe("|");
+
+ for (int i = 0; i < 6; i++)
+ {
+ auto it = args.find(arg_names[i]);
+ arg = (it != args.end() && it->is_string()) ? *it : "";
+ if (arg != "") args_string += arg + pipe;
+ }
+
+ // Remove last 'pipe':
+ if (args_string != "")
+ args_string = args_string.substr(0, args_string.size()-1);
+
+ execute(args_string, response);
+}
+
+
// Project
#include <anna/comm/comm.hpp>
+#include <anna/json/json.hpp>
class Procedure {
Procedure(anna::comm::Application *app) : a_app(app) {;}
virtual void execute(const std::string &args, std::string &response) throw(anna::RuntimeException);
+ virtual void execute(const nlohmann::json &args, std::string &response) throw(anna::RuntimeException);
};
#endif
// Process
#include <EventOperation.hpp>
#include <Launcher.hpp>
+#include <Procedure.hpp>
+#include <MyDiameterEngine.hpp>
+#include <MyLocalServer.hpp>
+#include <anna/testing/TestManager.hpp>
-// Project
-#include <anna/diameter.comm/OriginHost.hpp>
-
-
-//// Standard
-//#include <sstream> // std::istringstream
-//#include <iostream> // std::cout
+// Standard
#include <fstream>
-//#include <math.h> // ceil
-//#include <climits>
#include <unistd.h> // chdir
-//#include <stdio.h>
-//
-//// Project
+
+// Project
+#include <anna/diameter.comm/OriginHost.hpp>
#include <anna/json/functions.hpp>
#include <anna/diameter/codec/Message.hpp>
-//#include <anna/timex/Engine.hpp>
-//#include <anna/statistics/Engine.hpp>
-//#include <anna/diameter/codec/functions.hpp>
-//#include <anna/diameter/codec/Engine.hpp>
-//#include <anna/diameter/codec/EngineManager.hpp>
-//#include <anna/http/Transport.hpp>
-//#include <anna/diameter/stack/Engine.hpp>
#include <anna/diameter/helpers/base/functions.hpp>
#include <anna/time/functions.hpp>
#include <anna/core/functions.hpp>
-//#include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
-//#include <anna/testing/defines.hpp>
#include <anna/xml/xml.hpp>
-//#include <anna/diameter.comm/OriginHost.hpp>
-//#include <anna/diameter.comm/OriginHostManager.hpp>
#include <anna/diameter.comm/Message.hpp>
-//
-//// Process
-//#include <Launcher.hpp>
-//#include <Procedure.hpp>
-//#include <EventOperation.hpp>
-#include <MyDiameterEngine.hpp>
-#include <MyLocalServer.hpp>
-#include <anna/testing/TestManager.hpp>
-//#include <anna/testing/TestCase.hpp>
/////////////////////
return true; // OK
}
+bool EventOperation::test__dynamic(std::string &response, const nlohmann::json &arguments) {
+
+ Launcher& my_app = static_cast <Launcher&>(anna::app::functions::getApp());
+
+ Procedure p(&my_app);
+ try {
+ p.execute(arguments, response);
+ }
+ catch(anna::RuntimeException &ex) {
+ ex.trace();
+ response += ex.asString();
+ return false;
+ }
+
+ return true; // OK
+}
+
+
#ifndef example_diameter_launcher_EventOperation_hpp
#define example_diameter_launcher_EventOperation_hpp
-// Project
-
// STL
#include <string>
-//// Standard
-//#include <sstream> // std::istringstream
-//#include <iostream> // std::cout
-//#include <math.h> // ceil
-//#include <climits>
-//#include <unistd.h> // chdir
-//#include <stdio.h>
-//
// Project
-//#include <anna/timex/Engine.hpp>
-//#include <anna/statistics/Engine.hpp>
-//#include <anna/diameter/codec/functions.hpp>
-//#include <anna/diameter/codec/Engine.hpp>
-//#include <anna/diameter/codec/EngineManager.hpp>
-//#include <anna/http/Transport.hpp>
-//#include <anna/diameter/stack/Engine.hpp>
-//#include <anna/diameter/helpers/base/functions.hpp>
-//#include <anna/time/functions.hpp>
-//#include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
-//#include <anna/testing/defines.hpp>
-//#include <anna/xml/xml.hpp>
-//#include <anna/diameter.comm/OriginHost.hpp>
-//#include <anna/diameter.comm/OriginHostManager.hpp>
-//
-//// Process
-//#include <Launcher.hpp>
-//#include <Procedure.hpp>
-//#include <EventOperation.hpp>
-//#include <MyDiameterEngine.hpp>
-//#include <anna/testing/TestManager.hpp>
-//#include <anna/testing/TestCase.hpp>
+#include <anna/json/json.hpp>
class EventOperation {
const std::string & state = "all" /* initialized|in-progress|failed|success|[all]|none */, bool enable = true);
bool test__report_hex(std::string &response, bool enable = true);
bool test__dump_stdout(std::string &response, bool enable = true);
+
+ // Dynamic procedure
+ bool test__dynamic(std::string &response, const nlohmann::json &arguments);
};
#endif
auto it = j.find("condition");
if (it != j.end() && it->is_object()) {
-/*
- auto j2 = it->get<nlohmann::json::object_t>();
-
- // [code]|[bitR]|[hopByHop]|[applicationId]|[sessionId]|[resultCode]|[msisdn]|[imsi]|[serviceContextId]
- auto it_code = j2.find("code");
- auto it_bitR = j2.find("bitR");
- auto it_hopByHop = j2.find("hopByHop");
- auto it_applicationId = j2.find("applicationId");
- auto it_sessionId = j2.find("sessionId");
- auto it_resultCode = j2.find("resultCode");
- auto it_msisdn = j2.find("msisdn");
- auto it_imsi = j2.find("imsi");
- auto it_serviceContextId = j2.find("serviceContextId");
-
- std::string p1 = (it_code != j2.end() && it_code->is_string()) ? *it_code : "";
- std::string p2 = (it_bitR != j2.end() && it_bitR->is_string()) ? *it_bitR : "";
- std::string p3 = (it_hopByHop != it->end() && it_hopByHop->is_string()) ? *it_hopByHop : "";
- std::string p4 = (it_applicationId != it->end() && it_applicationId->is_string()) ? *it_applicationId : "";
- std::string p5 = (it_sessionId != it->end() && it_sessionId->is_string()) ? *it_sessionId : "";
- std::string p6 = (it_resultCode != it->end() && it_resultCode->is_string()) ? *it_resultCode : "";
- std::string p7 = (it_msisdn != it->end() && it_msisdn->is_string()) ? *it_msisdn : "";
- std::string p8 = (it_imsi != it->end() && it_imsi->is_string()) ? *it_imsi : "";
- std::string p9 = (it_serviceContextId != it->end() && it_serviceContextId->is_string()) ? *it_serviceContextId : "";
-*/
-
// [code]|[bitR]|[hopByHop]|[applicationId]|[sessionId]|[resultCode]|[msisdn]|[imsi]|[serviceContextId]
auto it_code = it->find("code");
auto it_bitR = it->find("bitR");
response += "invalid 'action' string field (allowed: enable|disable)";
}
+ // Dynamic procedure
+ else if ((opType == "/dynamic")) {
+ auto it = j.find("arguments");
+ if (it != j.end() && it->is_object()) {
+ result = eop.test__dynamic(response, *it);
+ }
+ else
+ response += "missing 'arguments' object field";
+ }
+
return result;
}
}
```
-### EXECUTION ACTIONS
+### FSM TESTING EXECUTION ACTIONS
#### POST /test-ttps
}
```
+### DYNAMIC PROCEDURE
+Used for system test. Arguments are determined by the way in a specific dynamic library is designed/documented.
+
+#### POST /dynamic
+
+**Request body**:
+
+```
+{
+ "dynamic": <diameter arguments json object>
+}
+```
+
+**Response body**:
+
+```
+{
+ "result":"<true or false>",
+ "response":"<response>"
+}
+```
REPO_DIR="$(git rev-parse --show-toplevel 2>/dev/null)"
[ -z "$REPO_DIR" ] && { echo "You must execute under a valid git repository !" ; exit 1 ; }
-SERVICES=${REPO_DIR}/example/diameter/launcher/resources/rest_api/ct/resources/servicesJson-request.json
+SERVICES=${REPO_DIR}/example/diameter/launcher/resources/rest_api/ct/resources/servicesRxJson-request.json
ENDPOINT=http://localhost:8074
PORT=$(echo ${ENDPOINT} | cut -d: -f3)
-C_NAME=anna-adml-http
+SVC_NAME=anna-adml-http
# Entrypoint arguments (ft/st):
EXTRA_ARGUMENTS= # default is ft (function test: debug traces and traffic logs)
-EXTRA_ARGUMENTS=st
VARIANT=${1:-Release}
echo "Requirement found !"
echo
-echo "Rebuild ADML HTTP service image (y/n) [n]:"
+echo "Rebuild ADML HTTP service image (y/n) [y]:"
read opt
-[ -z "${opt}" ] && opt=n
+[ -z "${opt}" ] && opt=y
if [ "${opt}" = "y" ]
then
${REPO_DIR}/tools/build-anna-adml-http ${VARIANT}
fi
version=$(${REPO_DIR}/tools/version)
-[ "${VARIANT}" = "Debug" ] && { version=${version}-debug ; C_NAME=${C_NAME}-debug ; }
-echo "Restart ADML HTTP service image (version '${version}') ..."
-docker kill ${C_NAME} &>/dev/null
-cid=$(docker run --rm -d -p ${PORT}:${PORT} --name ${C_NAME} anna-adml-http:${version} ${EXTRA_ARGUMENTS} >/dev/null)
-[ $? -ne 0 ] && exit 1
-
-echo "Container id: ${cid} (deployed as '${C_NAME}')"
+cname=${SVC_NAME}
+[ "${VARIANT}" = "Debug" ] && { version=${version}-debug ; cname=${cname}-debug ; }
+echo "Restart ADML HTTP service image (version '${version}') (y/n) [y]:"
+read opt
+[ -z "${opt}" ] && opt=y
+if [ "${opt}" = "y" ]
+then
+ docker kill ${SVC_NAME} &>/dev/null
+ docker kill ${SVC_NAME}-debug &>/dev/null
+ cid=$(docker run --rm -d -p ${PORT}:${PORT} --name ${cname} anna-adml-http:${version} ${EXTRA_ARGUMENTS} >/dev/null)
+ [ $? -ne 0 ] && exit 1
+ echo "Container id: ${cid} (deployed as '${cname}')"
+fi
echo
echo "Configuring services (${SERVICES}) ..."
echo -n "Waiting for server-client connection ..."
while true
do
- docker exec -it ${C_NAME} bash -c "netstat -p \$(pgrep ADML) --numeric-ports | grep -w 3868 | grep -w ESTABLISHED" >/dev/null
+ docker exec -it ${cname} bash -c "netstat -p \$(pgrep ADML) --numeric-ports | grep -w 3868 | grep -w ESTABLISHED" >/dev/null
[ $? -eq 0 ] && break
echo -n .
sleep 1
--- /dev/null
+import pytest
+
+
+@pytest.mark.dynamic
+@pytest.mark.xfail(reason="This will fail if already provisioned (if you want success here, restart the ADML HTTP Service)")
+def test_001_given_servicesGx_json_representation_i_want_to_load_it_through_adml_service(resources, admlc):
+
+ # Load services for Gx interface (client/server nodes & Gx dictionary):
+ requestBody = resources("servicesGxJson-request.json")
+ responseBodyRef = { "success":"true", "response":"loaded services correctly" }
+
+ # Send POST
+ response = admlc.post("/services", requestBody)
+
+ ### Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
+@pytest.mark.dynamic
+def test_002_provision_dynamic_operation_for_gx_at_adml(resources, admlc):
+
+ # Dynamic procedure:
+ requestBody = resources("arguments-request.json")
+ responseBodyRef = { "success":"true", "response":"Completed provision: range [0000, 9000]; scenary: CCR-Initial + CCR-Termination" }
+
+ # Send POST
+ response = admlc.post("/dynamic", requestBody)
+
+ # Verify response
+ admlc.assert_response__status_body_headers(response, 200, responseBodyRef)
+
@pytest.mark.xfail(reason="This will fail if already provisioned (if you want success here, restart the ADML HTTP Service)")
def test_001_given_services_json_representation_i_want_to_load_it_through_adml_service(resources, admlc):
- requestBody = resources("servicesJson-request.json")
+ # Load services for Rx interface (client/server nodes & Gx dictionary):
+ requestBody = resources("servicesRxJson-request.json")
responseBodyRef = { "success":"true", "response":"loaded services correctly" }
# Send POST
[pytest]
-addopts = -v --junitxml=/tmp/junit.xml -n 0
+addopts = -v --junitxml=/tmp/junit.xml -n 0 -m "not dynamic"
log_format=%(asctime)s|%(name)s|%(filename)s:%(lineno)d|%(levelname)s|%(message)s
log_date_format = %Y-%m-%d %H:%M:%S
junit_suite_name = "ADML REST API"
junit_logging = out-err
junit_family = xunit1
+
+# Naming conventions
+#python_files = check_*.py
+#python_classes = Check
+#python_functions = *_check
+
+# Markers
+markers =
+ dynamic: this test requires ADML dynamic test library enabled (/opt/adml/dynlibs)
--- /dev/null
+{
+ "arguments": {
+ "seqI":"0000",
+ "seqF":"9000",
+ "msecsTimeout":"5000",
+ "digits":"4",
+ "ccrI":"/opt/adml/dynlibs/gx/00001/CCR-I.xml",
+ "ccrT":"/opt/adml/dynlibs/gx/00001/CCR-T.xml"
+ }
+}
--- /dev/null
+{
+ "servicesJson": {
+ "services": {
+ "node": [
+ {
+ "@applicationId": "16777238",
+ "@entity": "localhost:3869",
+ "@originHost": "ggsnNodeHostname.nodeHostRealm.com"
+ },
+ {
+ "@applicationId": "16777238",
+ "@diameterServer": "localhost:3869",
+ "@diameterServerSessions": "1",
+ "@originHost": "ownHostIdGx.operatorRealm.com"
+ }
+ ],
+ "stack": {
+ "@dictionary": "stacks/DictionaryGx.16777238.xml",
+ "@fixMode": "Always",
+ "@id": "16777238",
+ "@ignoreFlagsOnValidation": "yes"
+ }
+ }
+ }
+}
+++ /dev/null
-{
- "servicesJson": {
- "services": {
- "node": [
- {
- "@applicationId": "16777236",
- "@entity": "localhost:3868",
- "@originHost": "afHost.afRealm.com"
- },
- {
- "@applicationId": "16777236",
- "@diameterServer": "localhost:3868",
- "@diameterServerSessions": "1",
- "@originHost": "ownHostId.operatorRealm.com"
- }
- ],
- "stack": {
- "@dictionary": "stacks/DictionaryRx.16777236.xml",
- "@fixMode": "Always",
- "@id": "16777236",
- "@ignoreFlagsOnValidation": "yes"
- }
- }
- }
-}
--- /dev/null
+{
+ "servicesJson": {
+ "services": {
+ "node": [
+ {
+ "@applicationId": "16777236",
+ "@entity": "localhost:3868",
+ "@originHost": "afHost.afRealm.com"
+ },
+ {
+ "@applicationId": "16777236",
+ "@diameterServer": "localhost:3868",
+ "@diameterServerSessions": "1",
+ "@originHost": "ownHostId.operatorRealm.com"
+ }
+ ],
+ "stack": {
+ "@dictionary": "stacks/DictionaryRx.16777236.xml",
+ "@fixMode": "Always",
+ "@id": "16777236",
+ "@ignoreFlagsOnValidation": "yes"
+ }
+ }
+ }
+}