Improvements from anna fork
[anna.git] / include / anna / testing / TestStep.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #ifndef anna_testing_TestStep_hpp
10 #define anna_testing_TestStep_hpp
11
12 // Standard
13 #include <string>
14 #include <vector>
15 #include <thread>
16
17 // Project
18 #include <anna/core/DataBlock.hpp>
19 #include <anna/testing/TestDiameterCondition.hpp>
20 #include <anna/core/util/Millisecond.hpp>
21
22
23 namespace anna {
24   class Millisecond;
25
26   namespace xml {
27     class Node;
28   }
29   namespace diameter {
30     namespace codec {
31       class Message;
32     }
33     namespace comm {
34       class OriginHost;
35       class ClientSession;
36       class ServerSession;
37     }
38   }
39
40 namespace testing {
41
42 class TestCase;
43 class TestTimer;
44
45 class TestStep {
46
47     int a_number; // step number used for xml (informational)
48     anna::Millisecond a_beginTimestamp; // unix time
49     anna::Millisecond a_endTimestamp; // unix time
50     bool a_executed; // used for interactive mode in order to not repeat a execution step if before completing, the user add interactive amount
51
52     void setBeginTimestamp(const anna::Millisecond &t) throw() { a_beginTimestamp = t; }
53     const anna::Millisecond &getBeginTimestamp() const throw() { return a_beginTimestamp; }
54     void setEndTimestamp(const anna::Millisecond &t) throw() { a_endTimestamp = t; }
55     const anna::Millisecond &getEndTimestamp() const throw() { return a_endTimestamp; }
56
57     void initialize(TestCase *testCase);
58
59   public:
60     struct Type { enum _v { Unconfigured, Timeout, Sendxml2e, Sendxml2c, Delay, Wait, Cmd, IpLimit }; };
61     static const char* asText(const Type::_v type) throw();
62
63     TestStep(TestCase *testCase) : a_message(true), a_messageCodec(NULL), a_executed(false) { initialize(testCase); }
64     virtual ~TestStep() {;}
65
66     // setter & getters
67     const Type::_v &getType() const throw() { return a_type; }
68     const int &getNumber() const throw() { return a_number; }
69     bool isCompleted() const throw() { return a_completed; }
70     anna::Millisecond getLapseMs() const throw() { return a_endTimestamp - a_beginTimestamp; }
71
72     bool execute() throw();
73     void complete() throw();
74     void reset() throw();
75     void next() throw();
76     virtual anna::xml::Node* asXML(anna::xml::Node* parent) throw();
77     std::string asXMLString() throw();
78
79   protected:
80     TestCase *a_testCase;
81     bool a_completed;
82     Type::_v a_type;
83
84     // Message (not for all step types)
85     anna::DataBlock a_message;
86     anna::diameter::codec::Message *a_messageCodec; // used as helper and for traffic logs
87     bool decodeMessage(bool trust = false) throw(); // If trust=true: decoding the previously encoded message (sendxml sentences).
88                                                     // The only error would be validation ones, and we are going to ignore them here.
89
90     virtual bool do_execute() throw() = 0; // returns true if next step must be executed
91     virtual void do_complete() throw() = 0; // end of transaction (delay/timeout expired, wait condition fulfilled, sending done)
92                                             // In all cases, the next step will be executed except 'timeout' which is asynchronous
93                                             //  and will move to the next step just after timer creation (no complete waited)
94     virtual void do_reset() throw() = 0;
95 };
96
97
98 class TestStepTimeout : public TestStep {
99
100     anna::Millisecond a_timeout;
101     TestTimer *a_timer; // just in case i would need to cancel
102
103   public:
104     TestStepTimeout(TestCase *testCase) : TestStep(testCase), a_timeout(0), a_timer(NULL) { a_type = Type::Timeout; }
105
106     // setter & getters
107     void setTimeout(const anna::Millisecond &t) throw() { a_timeout = t; }
108     const anna::Millisecond &getTimeout() const throw() { return a_timeout; }
109
110     // virtuals
111     bool do_execute() throw();
112     void do_complete() throw(); // timeout reached, test case failed
113     void do_reset() throw();
114     void cancelTimer() throw();
115     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
116 };
117
118
119 class TestStepSendDiameterXml : public TestStep {
120
121   protected:
122     // possible end points:
123     anna::diameter::comm::OriginHost *a_originHost;
124
125     // Step number reference ('wait for request' step)
126     int a_waitForRequestStepNumber;
127
128     // Expired ?
129     bool a_expired; // a_endTimestamp will be the expiration reception timestamp
130
131   public:
132     TestStepSendDiameterXml(TestCase *testCase) : TestStep(testCase),
133       a_expired(false),
134       a_originHost(NULL),
135       a_waitForRequestStepNumber(-1) {;}
136     ~TestStepSendDiameterXml() {;}
137
138     // setter & getters
139     void setOriginHost(anna::diameter::comm::OriginHost *host) throw() { a_originHost = host; }
140     anna::diameter::comm::OriginHost *getOriginHost() const throw() { return a_originHost; }
141     void setWaitForRequestStepNumber(int stepNumber) throw() { a_waitForRequestStepNumber = stepNumber; }
142     int getWaitForRequestStepNumber() const throw() { return a_waitForRequestStepNumber; }
143     void setMsgDataBlock(const anna::DataBlock &db) throw() { a_message = db; }
144     const anna::DataBlock &getMsgDataBlock() const throw() { return a_message; }
145
146     // virtuals
147     bool do_execute() throw();
148     void do_complete() throw() {;}
149     void do_reset() throw();
150     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
151 };
152
153 class TestStepSendDiameterXml2e : public TestStepSendDiameterXml {
154   public:
155     TestStepSendDiameterXml2e(TestCase *testCase) : TestStepSendDiameterXml(testCase) { a_type = Type::Sendxml2e; }
156 };
157
158 class TestStepSendDiameterXml2c : public TestStepSendDiameterXml {
159   public:
160     TestStepSendDiameterXml2c(TestCase *testCase) : TestStepSendDiameterXml(testCase) { a_type = Type::Sendxml2c; }
161 };
162
163
164 class TestStepDelay : public TestStep {
165     anna::Millisecond a_delay;
166     TestTimer *a_timer; // just in case i would need to cancel
167
168   public:
169     TestStepDelay(TestCase *testCase) : TestStep(testCase), a_delay(0), a_timer(NULL) { a_type = Type::Delay; }
170
171     // setter & getters
172     void setDelay(const anna::Millisecond &d) throw() { a_delay = d; }
173     const anna::Millisecond &getDelay() const throw() { return a_delay; }
174
175     // virtuals
176     bool do_execute() throw();
177     void do_complete() throw(); // delay reached
178     void do_reset() throw();
179     void cancelTimer() throw();
180     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
181 };
182
183
184 class TestStepWaitDiameter : public TestStep {
185
186     TestDiameterCondition a_condition;
187     anna::diameter::comm::ClientSession *a_clientSession;
188     anna::diameter::comm::ServerSession *a_serverSession;
189
190   public:
191     TestStepWaitDiameter(TestCase *testCase) : TestStep(testCase) {
192       a_type = Type::Wait;
193       a_clientSession = NULL;
194       a_serverSession = NULL;
195     }
196     ~TestStepWaitDiameter() {;}
197
198     // setter & getters
199     void setCondition(bool fromEntity,
200                         const std::string &code, const std::string &bitR, const std::string &hopByHop, const std::string &applicationId,
201                         const std::string &sessionId, const std::string &resultCode,
202                         const std::string &msisdn, const std::string &imsi, const std::string &serviceContextId) throw();
203     void setConditionRegexpXml(bool fromEntity, const std::string &regexp) throw();
204     void setConditionRegexpHex(bool fromEntity, const std::string &regexp) throw();
205
206     void setClientSession(anna::diameter::comm::ClientSession *cs) throw() { a_clientSession = cs; }
207     void setServerSession(anna::diameter::comm::ServerSession *ss) throw() { a_serverSession = ss; }
208     anna::diameter::comm::ClientSession *getClientSession() const throw() { return a_clientSession; }
209     anna::diameter::comm::ServerSession *getServerSession() const throw() { return a_serverSession; }
210
211     const TestDiameterCondition &getCondition() const throw() { return a_condition; }
212     //void setMsgDataBlock(const anna::DataBlock &db) throw() { a_message = db; }
213     bool fulfilled(const anna::DataBlock &db/*, bool matchSessionId = true*/) throw();
214     const anna::DataBlock &getMsgDataBlock() const throw() { return a_message; }
215
216
217     // virtuals
218     bool do_execute() throw(); // this will be executed when test case starts (at least we could measure the time until condition is fulfilled)
219     void do_complete() throw(); // condition fulfilled
220     void do_reset() throw();
221     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
222 };
223
224
225 class TestStepCmd : public TestStep {
226
227   std::string a_script;
228   std::thread a_thread;
229   bool a_threadRunning;
230   bool a_threadDeprecated;
231   int a_resultCode;
232   std::string a_errorMsg;
233   //std::string a_output; // for POPEN
234
235   pid_t a_childPid;
236
237   public:
238     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; }
239
240     // setter & getters
241     void setThreadRunning(bool running) throw() { a_threadRunning = running; }
242
243     void setResultCode(int rc) throw() { a_resultCode = rc; }
244     int getResultCode() const throw() { return a_resultCode; }
245     void setErrorMsg(const std::string &em) throw() { a_errorMsg = em; }
246     const std::string &getErrorMsg() const throw() { return a_errorMsg; }
247     //void appendOutput(const std::string &output) throw() { a_output += output; }
248     //const std::string &getOutput() const throw() { return a_output; }
249     void setChildPid(pid_t pid) throw() { a_childPid = pid; }
250     const pid_t &getChildPid() const throw() { return a_childPid; }
251
252     void setScript(const std::string &script) throw() { a_script = script; }
253     const std::string &getScript() const throw() { return a_script; }
254
255     // virtuals
256     bool do_execute() throw();
257     void do_complete() throw();
258     void do_reset() throw();
259     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
260 };
261
262
263 class TestStepIpLimit : public TestStep {
264
265     unsigned int a_ipLimit;
266
267   public:
268     TestStepIpLimit(TestCase *testCase) : TestStep(testCase), a_ipLimit(1) { a_type = Type::IpLimit; }
269
270     // setter & getters
271     void setIpLimit(unsigned int limit) throw() { a_ipLimit = limit; }
272     unsigned int getIpLimit() const throw() { return a_ipLimit; }
273
274     // virtuals
275     bool do_execute() throw();
276     void do_complete() throw();
277     void do_reset() throw() {;}
278     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
279 };
280
281 }
282 }
283
284 #endif
285