782ce55ccafbdb0d6f16a62ad997fa60ceb07200
[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/TestCondition.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 }; };
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
71     bool execute() throw();
72     void complete() throw();
73     void reset() throw();
74     void next() throw();
75     virtual anna::xml::Node* asXML(anna::xml::Node* parent) throw();
76     std::string asXMLString() throw();
77
78   protected:
79     TestCase *a_testCase;
80     bool a_completed;
81     Type::_v a_type;
82
83     // Message (not for all step types)
84     anna::DataBlock a_message;
85     anna::diameter::codec::Message *a_messageCodec; // used as helper and for traffic logs
86     bool decodeMessage(bool trust = false) throw(); // If trust=true: decoding the previously encoded message (sendxml sentences).
87                                                     // The only error would be validation ones, and we are going to ignore them here.
88
89     virtual bool do_execute() throw() = 0; // returns true if next step must be executed
90     virtual void do_complete() throw() = 0; // end of transaction (delay/timeout expired, wait condition fulfilled, sending done)
91                                             // In all cases, the next step will be executed except 'timeout' which is asynchronous
92                                             //  and will move to the next step just after timer creation (no complete waited)
93     virtual void do_reset() throw() = 0;
94 };
95
96
97 class TestStepTimeout : public TestStep {
98
99     anna::Millisecond a_timeout;
100     TestTimer *a_timer; // just in case i would need to cancel
101
102   public:
103     TestStepTimeout(TestCase *testCase) : TestStep(testCase), a_timeout(0), a_timer(NULL) { a_type = Type::Timeout; }
104
105     // setter & getters
106     void setTimeout(const anna::Millisecond &t) throw() { a_timeout = t; }
107     const anna::Millisecond &getTimeout() const throw() { return a_timeout; }
108
109     // virtuals
110     bool do_execute() throw();
111     void do_complete() throw(); // timeout reached, test case failed
112     void do_reset() throw();
113     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
114 };
115
116
117 class TestStepSendxml : public TestStep {
118
119   protected:
120     // possible end points:
121     anna::diameter::comm::OriginHost *a_originHost;
122
123     // Step number reference ('wait for request' step)
124     int a_waitForRequestStepNumber;
125
126     // Expired ?
127     bool a_expired; // a_endTimestamp will be the expiration reception timestamp
128
129   public:
130     TestStepSendxml(TestCase *testCase) : TestStep(testCase),
131       a_expired(false),
132       a_originHost(NULL),
133       a_waitForRequestStepNumber(-1) {;}
134     ~TestStepSendxml() {;}
135
136     // setter & getters
137     void setOriginHost(anna::diameter::comm::OriginHost *host) throw() { a_originHost = host; }
138     anna::diameter::comm::OriginHost *getOriginHost() const throw() { return a_originHost; }
139     void setWaitForRequestStepNumber(int stepNumber) throw() { a_waitForRequestStepNumber = stepNumber; }
140     int getWaitForRequestStepNumber() const throw() { return a_waitForRequestStepNumber; }
141     void setMsgDataBlock(const anna::DataBlock &db) throw() { a_message = db; }
142     const anna::DataBlock &getMsgDataBlock() const throw() { return a_message; }
143
144     // virtuals
145     bool do_execute() throw();
146     void do_complete() throw() {;}
147     void do_reset() throw();
148     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
149 };
150
151 class TestStepSendxml2e : public TestStepSendxml {
152   public:
153     TestStepSendxml2e(TestCase *testCase) : TestStepSendxml(testCase) { a_type = Type::Sendxml2e; }
154 };
155
156 class TestStepSendxml2c : public TestStepSendxml {
157   public:
158     TestStepSendxml2c(TestCase *testCase) : TestStepSendxml(testCase) { a_type = Type::Sendxml2c; }
159 };
160
161
162 class TestStepDelay : public TestStep {
163     anna::Millisecond a_delay;
164     TestTimer *a_timer; // just in case i would need to cancel
165
166   public:
167     TestStepDelay(TestCase *testCase) : TestStep(testCase), a_delay(0), a_timer(NULL) { a_type = Type::Delay; }
168
169     // setter & getters
170     void setDelay(const anna::Millisecond &d) throw() { a_delay = d; }
171     const anna::Millisecond &getDelay() const throw() { return a_delay; }
172
173     // virtuals
174     bool do_execute() throw();
175     void do_complete() throw(); // delay reached
176     void do_reset() throw();
177     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
178 };
179
180
181 class TestStepWait : public TestStep {
182
183     TestCondition a_condition;
184     anna::diameter::comm::ClientSession *a_clientSession;
185     anna::diameter::comm::ServerSession *a_serverSession;
186
187   public:
188     TestStepWait(TestCase *testCase) : TestStep(testCase) {
189       a_type = Type::Wait;
190       a_clientSession = NULL;
191       a_serverSession = NULL;
192     }
193     ~TestStepWait() {;}
194
195     // setter & getters
196     void setCondition(bool fromEntity,
197                         const std::string &code, const std::string &bitR, const std::string &hopByHop, const std::string &applicationId,
198                         const std::string &sessionId, const std::string &resultCode,
199                         const std::string &msisdn, const std::string &imsi, const std::string &serviceContextId) throw();
200     void setConditionRegexpXml(bool fromEntity, const std::string &regexp) throw();
201     void setConditionRegexpHex(bool fromEntity, const std::string &regexp) throw();
202
203     void setClientSession(anna::diameter::comm::ClientSession *cs) throw() { a_clientSession = cs; }
204     void setServerSession(anna::diameter::comm::ServerSession *ss) throw() { a_serverSession = ss; }
205     anna::diameter::comm::ClientSession *getClientSession() const throw() { return a_clientSession; }
206     anna::diameter::comm::ServerSession *getServerSession() const throw() { return a_serverSession; }
207
208     const TestCondition &getCondition() const throw() { return a_condition; }
209     //void setMsgDataBlock(const anna::DataBlock &db) throw() { a_message = db; }
210     bool fulfilled(const anna::DataBlock &db/*, bool matchSessionId = true*/) throw();
211     const anna::DataBlock &getMsgDataBlock() const throw() { return a_message; }
212
213
214     // virtuals
215     bool do_execute() throw(); // this will be executed when test case starts (at least we could measure the time until condition is fulfilled)
216     void do_complete() throw(); // condition fulfilled
217     void do_reset() throw();
218     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
219 };
220
221
222 class TestStepCmd : public TestStep {
223
224   std::string a_script;
225   std::thread a_thread;
226   bool a_threadRunning;
227   bool a_threadDeprecated;
228   int a_resultCode;
229   std::string a_errorMsg;
230   //std::string a_output; // for POPEN
231
232   pid_t a_childPid;
233
234   public:
235     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; }
236
237     // setter & getters
238     void setThreadRunning(bool running) throw() { a_threadRunning = running; }
239
240     void setResultCode(int rc) throw() { a_resultCode = rc; }
241     int getResultCode() const throw() { return a_resultCode; }
242     void setErrorMsg(const std::string &em) throw() { a_errorMsg = em; }
243     const std::string &getErrorMsg() const throw() { return a_errorMsg; }
244     //void appendOutput(const std::string &output) throw() { a_output += output; }
245     //const std::string &getOutput() const throw() { return a_output; }
246     void setChildPid(pid_t pid) throw() { a_childPid = pid; }
247     const pid_t &getChildPid() const throw() { return a_childPid; }
248
249     void setScript(const std::string &script) throw() { a_script = script; }
250     const std::string &getScript() const throw() { return a_script; }
251
252     // virtuals
253     bool do_execute() throw();
254     void do_complete() throw();
255     void do_reset() throw();
256     anna::xml::Node* asXML(anna::xml::Node* parent) throw();
257 };
258
259 }
260 }
261
262 #endif
263