Titan Core Initial Contribution
[deliverable/titan.core.git] / loggerplugins / TSTLogger / TSTLogger.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "ILoggerPlugin.hh"
9 #include "TSTLogger.hh"
10
11 #ifndef TITAN_RUNTIME_2
12 #include "RT1/TitanLoggerApi.hh"
13 #else
14 #include "RT2/TitanLoggerApi.hh"
15 #endif
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <string.h>
22 #include <netdb.h>
23 #include <sys/types.h>
24 #include <netinet/in.h>
25 #include <sys/socket.h>
26 #include <arpa/inet.h>
27 #include <sys/time.h>
28
29 #include <iostream>
30 #include <sstream>
31
32 #ifdef __cplusplus
33 extern "C"
34 {
35 ILoggerPlugin *create_plugin() { return new TSTLogger(); }
36 void destroy_plugin(ILoggerPlugin *plugin) { delete plugin; }
37 }
38 #endif
39
40 using namespace std;
41
42 ////////////////////////////////////////////////////////////////////////////////
43
44 class SocketException
45 {
46 string error_msg;
47 string reason;
48 public:
49 SocketException(const string p_error_msg, const string p_reason=""):error_msg(p_error_msg),reason(p_reason) {}
50 const string getMessage() const { return error_msg; }
51 const string getReason() const { return reason; }
52 };
53
54 class TimeoutException : public SocketException
55 {
56 public:
57 TimeoutException(const string p_error_msg): SocketException(p_error_msg) {}
58 };
59
60 ////////////////////////////////////////////////////////////////////////////////
61
62 class TCPClient
63 {
64 int socket_fd;
65 time_t timeout_time;
66
67 enum select_readwrite_t { SELECT_READ, SELECT_WRITE };
68 void wait_for_ready(time_t end_time, select_readwrite_t readwrite);
69 public:
70 TCPClient(): socket_fd(-1), timeout_time(30) {}
71 // opens connection and returns socket file descriptor, throws exception on error
72 void open_connection(const string host_name, const string service_name) throw(SocketException);
73 // send a string to a socket, don't return until the whole string is sent
74 void send_string(const string& str) throw(SocketException);
75 // receive available data to the end of the parameter string, blocks until at least wait_for_bytes chars have arrived,
76 // returns false if connection was closed
77 bool receive_string(string& str, const size_t wait_for_bytes) throw(SocketException);
78 // close connection
79 void close_connection() throw(SocketException);
80 time_t get_timeout() const { return timeout_time; }
81 void set_timeout(time_t t) { timeout_time = t; }
82 };
83
84 void TCPClient::open_connection(const string host_name, const string service_name) throw(SocketException)
85 {
86 if (socket_fd!=-1) {
87 close_connection();
88 }
89 struct addrinfo *res, *aip;
90 struct addrinfo hints;
91 memset(&hints, 0, sizeof(hints));
92 hints.ai_socktype = SOCK_STREAM;
93 int status = getaddrinfo(host_name.c_str(), service_name.c_str(), &hints, &res);
94 if (status!=0) {
95 throw SocketException("Cannot find host and service", gai_strerror(status));
96 }
97 for (aip = res; aip != NULL; aip = aip->ai_next) {
98 // create socket descriptor
99 socket_fd = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
100 if (socket_fd==-1) continue;
101 // try to connect
102 status = connect(socket_fd, aip->ai_addr, aip->ai_addrlen);
103 if (status==0) break; // connected
104 }
105 freeaddrinfo(res);
106 if (aip==NULL) {
107 socket_fd = -1;
108 throw SocketException("Cannot connect to host and service");
109 }
110 }
111
112 void TCPClient::close_connection() throw(SocketException)
113 {
114 if (socket_fd==-1) {
115 return;
116 }
117 int rv = close(socket_fd);
118 socket_fd = -1;
119 if (rv!=0) {
120 throw SocketException("Cannot close socket", strerror(errno));
121 }
122 }
123
124 // end_time - is time in seconds (from time(NULL)+timeout, when should we give up waiting
125 // readwrite - are we checking for read or write readyness on the file descriptor
126 void TCPClient::wait_for_ready(time_t end_time, select_readwrite_t readwrite)
127 {
128 struct timeval tv;
129 tv.tv_sec = end_time - time(NULL);
130 tv.tv_usec = 0;
131 fd_set fds;
132 wait_reset:
133 FD_ZERO(&fds);
134 FD_SET(socket_fd, &fds);
135 int status = select(socket_fd+1,
136 (readwrite==SELECT_READ) ? &fds : NULL,
137 (readwrite==SELECT_WRITE) ? &fds : NULL,
138 NULL, &tv);
139 if (status==-1) {
140 if (errno==EINTR) { // some signal
141 // update time
142 tv.tv_sec = end_time - time(NULL);
143 tv.tv_usec = 0;
144 goto wait_reset; // wait again
145 }
146 throw SocketException("Error while waiting on socket", strerror(errno));
147 }
148 if (FD_ISSET(socket_fd, &fds)==0) {
149 throw TimeoutException("Timeout while waiting on socket");
150 }
151 }
152
153 void TCPClient::send_string(const string& str) throw(SocketException)
154 {
155 if (socket_fd==-1) {
156 throw SocketException("Connection is not open");
157 }
158 time_t end_time = time(NULL) + timeout_time;
159 size_t sent_cnt = 0;
160 size_t str_len = str.size();
161 while (sent_cnt<str_len) {
162 wait_for_ready(end_time, SELECT_WRITE);
163 ssize_t n = send(socket_fd, str.c_str()+sent_cnt, str_len-sent_cnt, 0);
164 if (n==-1) {
165 throw SocketException("Cannot send data on socket", strerror(errno));
166 }
167 sent_cnt += n;
168 }
169 }
170
171 // wait_for_bytes - wait until at least so many bytes arrived or timeout or connection closed,
172 // if zero then wait until connection is closed
173 bool TCPClient::receive_string(string& str, const size_t wait_for_bytes) throw(SocketException)
174 {
175 if (socket_fd==-1) {
176 throw SocketException("Connection is not open");
177 }
178 time_t end_time = time(NULL) + timeout_time;
179 bool open = true;
180 char buff[1024];
181 size_t bytes_received = 0;
182 while (wait_for_bytes==0 || bytes_received<wait_for_bytes) {
183 wait_for_ready(end_time, SELECT_READ);
184 ssize_t recv_cnt = recv(socket_fd, buff, sizeof(buff), 0);
185 if (recv_cnt==-1) {
186 throw SocketException("Cannot read data from socket", strerror(errno));
187 }
188 if (recv_cnt==0) { // socket was closed by the other side
189 open = false;
190 close_connection();
191 break;
192 }
193 bytes_received += recv_cnt;
194 // store received data
195 str.append(buff, recv_cnt);
196 }
197 return open;
198 }
199
200 ////////////////////////////////////////////////////////////////////////////////
201
202 class HttpException : public SocketException
203 {
204 public:
205 HttpException(const string p_error_msg, const string p_reason=""):
206 SocketException(p_error_msg, p_reason) {}
207 };
208
209 typedef map<string,string> string_map;
210
211 class HTTPClient : public TCPClient
212 {
213 public:
214 HTTPClient(): TCPClient() {}
215 string url_encode(const string& str);
216 string post_request(const string& host, const string& uri, const string& user_agent, const string_map& req_params) throw(SocketException);
217 };
218
219 string HTTPClient::url_encode(const string& str)
220 {
221 static char hex[] = "0123456789abcdef";
222 stringstream ss;
223 for (size_t i=0; i<str.size(); i++) {
224 char c = str[i];
225 if (isalnum(c) || c=='-' || c=='_' || c=='.' || c=='~') {
226 ss << c;
227 } else if (c==' ') {
228 ss << '+';
229 } else {
230 ss << '%' << hex[(c>>4) & 15] << hex[(c&15) & 15];
231 }
232 }
233 return ss.str();
234 }
235
236 string HTTPClient::post_request(const string& host, const string& uri, const string& user_agent, const string_map& req_params) throw(SocketException)
237 {
238 // compose request message
239 stringstream req_ss;
240 req_ss << "POST " << uri << " HTTP/1.1\r\n" << // Host: must be added if HTTP/1.1 is used
241 "Host: " << host << "\r\n" <<
242 "User-Agent: " << user_agent << "\r\n" <<
243 "Connection: Close" << "\r\n" <<
244 "Content-Type: application/x-www-form-urlencoded" << "\r\n"; // as if it were post'ed from a web browser html form
245 stringstream req_body_ss;
246 for (string_map::const_iterator it = req_params.begin(); it!=req_params.end(); ++it) {
247 if (it!=req_params.begin()) req_body_ss << '&';
248 req_body_ss << url_encode(it->first) << '=' << url_encode(it->second);
249 }
250 req_ss << "Content-Length: " << req_body_ss.str().size() << "\r\n";
251 req_ss << "\r\n" << req_body_ss.str();
252 // send request
253 //cerr << "HTTP POST REQUEST:\n[" << req_ss.str() << "]\n";
254 send_string(req_ss.str());
255 // receive response, wait until the server closes the connection (doesn't work with Keep-Alive!)
256 string response;
257 receive_string(response, 0); // receive until connection is closed by the peer or timeout
258 //cerr << "HTTP POST RESPONSE:\n[" << response << "]\n";
259 // divide into header and body parts
260 size_t pos = response.find("\r\n\r\n");
261 if (pos==string::npos) {
262 throw HttpException("Invalid HTTP response", "Cannot find body part");
263 }
264 string head = response.substr(0, pos);
265 string body = response.substr(pos+4, string::npos);
266 if (head.find("Transfer-Encoding: chunked")!=string::npos) {
267 // remove chunked encoding stuff from body
268 // FIXME: this doesn't work if the chunks contain \r\n
269 string real_body;
270 string line;
271 bool chunk_line = false;
272 for (size_t idx = 0; idx<body.size()-1; idx++) {
273 if (body[idx]=='\r' && body[idx+1]=='\n') { // end of line
274 if (chunk_line) {
275 real_body += line;
276 } else {
277 if (line=="0") {
278 break;
279 }
280 }
281 chunk_line = !chunk_line;
282 line = "";
283 idx++;
284 } else {
285 line += body[idx];
286 }
287 }
288 body = real_body;
289 }
290 return body;
291 }
292
293 ////////////////////////////////////////////////////////////////////////////////
294
295
296 string TSTLogger::get_tst_time_str(const TitanLoggerApi::TimestampType& timestamp)
297 {
298 long long int t = timestamp.seconds().get_long_long_val() * 1000 + timestamp.microSeconds().get_long_long_val() / 1000;
299 stringstream s;
300 s << (long int)t;
301 return s.str();
302 }
303
304 string TSTLogger::get_host_name()
305 {
306 char name[257];
307 int status = gethostname(name, 256);
308 if (status!=0) return "DefaultExecutingHost";
309 return name;
310 }
311
312 string TSTLogger::get_user_name()
313 {
314 return getlogin();
315 }
316
317 TSTLogger::TSTLogger()
318 {
319 this->major_version_ = 1;
320 this->minor_version_ = 0;
321 this->name_ = mputstr(this->name_, "TSTLogger");
322 this->help_ = mputstr(this->help_, "TITAN Logger Plugin for TestStatistics");
323
324 // parameters of this plugin
325 parameters["tst_host_name"] = ParameterData("eta-teststatistics.rnd.ki.sw.ericsson.se", true, "TestStatistics web service host name");
326 parameters["tst_service_name"] = ParameterData("http", true, "TestStatistics web service name or port number");
327
328 parameters["tst_tcstart_url"] = ParameterData("/ts-rip/rip/tcstart");
329 parameters["tst_tcstop_url"] = ParameterData("/ts-rip/rip/tcstop");
330 parameters["tst_tsstart_url"] = ParameterData("/ts-rip/rip/tsstart");
331 parameters["tst_tsstop_url"] = ParameterData("/ts-rip/rip/tsstop");
332 parameters["tst_tcfailreason_url"] = ParameterData("/ts-rip/rip/tcfailreason");
333
334 parameters["dbsUrl"] = ParameterData("esekilx0007-sql5.rnd.ki.sw.ericsson.se:3314", true, "database URL");
335 parameters["dbUser"] = ParameterData("demo", true, "database user");
336 parameters["dbPass"] = ParameterData("demo", true, "plain text password of the user");
337 parameters["dbName"] = ParameterData("teststatistics_demo", true, "name of the database");
338
339 parameters["log_plugin_debug"] = ParameterData("0");
340
341 parameters["testConfigName"] = ParameterData("DefaultConfigName", false, "name of this specific configuration of the test suite");
342 parameters["suiteName"] = ParameterData("DefaultSuiteName", false, "name of test suite");
343 parameters["executingHost"] = ParameterData(get_host_name(), true, "host where the test was executed");
344 parameters["sutId"] = ParameterData("0.0.0.0", true, "IP address of SUT");
345 parameters["sutName"] = ParameterData("DefaultSUTName", true, "name of SUT");
346 parameters["lsvMajor"] = ParameterData("1", true, "major version number of SUT");
347 parameters["lsvMinor"] = ParameterData("0", true, "minor version number of SUT");
348 parameters["runByUser"] = ParameterData(get_user_name(), true, "name of user running the tests");
349 parameters["projectName"] = ParameterData("DefaultProjectname", true, "name of the project");
350 parameters["productName"] = ParameterData("DefaultProductName", true, "name of the product");
351 parameters["productVersion"] = ParameterData("0.0", true, "version of the product");
352 parameters["configType"] = ParameterData("configType", true, "");
353 parameters["configVersion"] = ParameterData("configVersion", true, "");
354 parameters["testType"] = ParameterData("testType", true, "");
355 parameters["logLink"] = ParameterData("default_log_location", false, "absolute location of log files");
356 parameters["logEnd"] = ParameterData("default_web_log_dir", false, "log directory relative to web server root");
357 parameters["reportEmail"] = ParameterData(get_user_name()+"@ericsson.com", false, "who is to be notified via email");
358 parameters["reportTelnum"] = ParameterData("0", false, "where to send the SMS notification");
359
360 stringstream ss;
361 ss << "TITAN " << this->name_ << ' ' << this->major_version_ << '.' << this->minor_version_;
362 user_agent = ss.str();
363
364 this->testcase_count_ = 0;
365 }
366
367 TSTLogger::~TSTLogger()
368 {
369 Free(this->name_);
370 Free(this->help_);
371 this->name_ = this->help_ = NULL;
372 }
373
374 bool TSTLogger::log_plugin_debug()
375 {
376 return parameters["log_plugin_debug"].get_value()!="0";
377 }
378
379 void TSTLogger::init(const char */*options*/)
380 {
381 cout << "Initializing `" << this->name_ << "' (v" << this->major_version_ << "." << this->minor_version_ << "): " << this->help_ << endl;
382 this->is_configured_ = true;
383 }
384
385 void TSTLogger::fini()
386 {
387 if (is_main_proc()) {
388 TitanLoggerApi::TimestampType timestamp;
389 struct timeval tm;
390 gettimeofday(&tm, NULL);
391 timestamp.seconds().set_long_long_val((long long int)tm.tv_sec);
392 timestamp.microSeconds().set_long_long_val((long long int)tm.tv_usec);
393 log_testsuite_stop(timestamp); // TODO: call this from log()
394 }
395 this->is_configured_ = false;
396 }
397
398 void TSTLogger::set_parameter(const char *parameter_name, const char *parameter_value)
399 {
400 map<string,ParameterData>::iterator it = parameters.find(parameter_name);
401 if (it!=parameters.end()) {
402 it->second.set_value(parameter_value);
403 } else {
404 cerr << this->name_ << ": " << "Unsupported parameter: `" << parameter_name << "' with value: `"
405 << parameter_value << "'" << endl;
406 }
407 }
408
409 void TSTLogger::add_database_params(std::map<std::string,std::string>& req_params)
410 {
411 req_params["dbsUrl"] = parameters["dbsUrl"].get_value();
412 req_params["dbUser"] = parameters["dbUser"].get_value();
413 req_params["dbPass"] = parameters["dbPass"].get_value();
414 req_params["dbName"] = parameters["dbName"].get_value();
415 }
416
417 string TSTLogger::post_message(std::map<std::string,std::string> req_params, const string& TST_service_uri)
418 {
419 add_database_params(req_params);
420 try {
421 HTTPClient client;
422 client.open_connection(parameters["tst_host_name"].get_value(), parameters["tst_service_name"].get_value());
423 string response = client.post_request(parameters["tst_host_name"].get_value(), TST_service_uri, user_agent, req_params);
424 client.close_connection();
425 return response;
426 }
427 catch (SocketException exc) {
428 cerr << this->name_ << ": " << "HTTP error: " << exc.getMessage() << " (" << exc.getReason() << ")\n";
429 }
430 return "";
431 }
432
433 // most of the message types should be sent only from one main process (MTC in parallel mode)
434 bool TSTLogger::is_main_proc() const
435 {
436 return TTCN_Runtime::is_mtc() || TTCN_Runtime::is_single();
437 }
438
439 void TSTLogger::log(const TitanLoggerApi::TitanLogEvent& event, bool log_buffered)
440 {
441 log(event, log_buffered, false, false);
442 }
443
444 void TSTLogger::log(const TitanLoggerApi::TitanLogEvent& event,
445 bool /*log_buffered*/, bool /*separate_file*/, bool /*use_emergency_mask*/)
446 {
447 const TitanLoggerApi::LogEventType_choice& choice = event.logEvent().choice();
448 switch (choice.get_selection()) {
449 case TitanLoggerApi::LogEventType_choice::ALT_testcaseOp: {
450 const TitanLoggerApi::TestcaseEvent_choice& tec = choice.testcaseOp().choice();
451 switch (tec.get_selection()) {
452 case TitanLoggerApi::TestcaseEvent_choice::ALT_testcaseStarted:
453 if (is_main_proc()) {
454 log_testcase_start(tec.testcaseStarted(), event.timestamp());
455 }
456 break;
457 case TitanLoggerApi::TestcaseEvent_choice::ALT_testcaseFinished:
458 if (is_main_proc()) {
459 log_testcase_stop(tec.testcaseFinished(), event.timestamp());
460 }
461 break;
462 default:
463 break;
464 }
465 break; }
466 case TitanLoggerApi::LogEventType_choice::ALT_verdictOp:
467 // allow these messages from PTCs
468 log_verdictop_reason(choice.verdictOp());
469 break;
470 default:
471 break;
472 }
473 }
474
475 void TSTLogger::log_testcase_start(const TitanLoggerApi::QualifiedName& testcaseStarted, const TitanLoggerApi::TimestampType& timestamp)
476 {
477 if (this->testcase_count_ == 0) {
478 log_testsuite_start(timestamp); // TODO: call this from log()
479 }
480 ++this->testcase_count_;
481
482 map<string,string> req_params;
483 req_params["suiteId"] = this->suite_id_;
484 req_params["tcId"] = (const char *)testcaseStarted.testcase__name();
485 req_params["tcHeader"] = req_params["tcId"];
486 req_params["tcStartTime"] = get_tst_time_str(timestamp);
487 req_params["tcState"] = "0";
488 //req_params["tcHtml"] = "";
489 req_params["tcClass"] = (const char *)testcaseStarted.module__name();
490 req_params["tcMethod"] = req_params["tcId"];
491
492 string resp = post_message(req_params, parameters["tst_tcstart_url"].get_value());
493
494 if ((resp.find("done") != string::npos) && (resp.find("tcaseId") != string::npos)) {
495 this->tcase_id_ = resp.substr(resp.find("=") + 1);
496 if (log_plugin_debug()) {
497 cout << this->name_ << ": " << "Operation `log_testcase_start' successful, returned tcaseId=" << this->tcase_id_ << endl;
498 }
499 } else {
500 cerr << this->name_ << ": " << "Operation `log_testcase_start' failed: " << resp << endl;
501 // Add better error handling.
502 return;
503 }
504 }
505
506 void TSTLogger::log_testcase_stop(const TitanLoggerApi::TestcaseType& testcaseFinished, const TitanLoggerApi::TimestampType& timestamp)
507 {
508 string tc_state;
509 switch (testcaseFinished.verdict()) {
510 case TitanLoggerApi::Verdict::v0none: // start (?)
511 tc_state = "0";
512 break;
513 case TitanLoggerApi::Verdict::v1pass: // pass
514 tc_state = "1";
515 break;
516 case TitanLoggerApi::Verdict::v2inconc: // inconclusive
517 tc_state = "7";
518 break;
519 case TitanLoggerApi::Verdict::v3fail: // fail
520 tc_state = "2";
521 break;
522 case TitanLoggerApi::Verdict::v4error: // error
523 tc_state = "3";
524 break;
525 default:
526 tc_state = "0";
527 }
528 map<string,string> req_params;
529 req_params["tcaseId"] = this->tcase_id_;
530 req_params["tcEndTime"] = get_tst_time_str(timestamp);
531 req_params["tcState"] = tc_state;
532 req_params["tcUndefined"] = "false"; //?
533 req_params["tcAssertion"] = "false"; //?
534 req_params["tcTrafficLoss"] = "false"; //?
535
536 string resp = post_message(req_params, parameters["tst_tcstop_url"].get_value());
537
538 if (!resp.compare("done")) {
539 if (log_plugin_debug()) {
540 cout << this->name_ << ": " << "Operation `log_testcase_stop' successful" << endl;
541 }
542 } else {
543 cerr << this->name_ << ": " << "Operation `log_testcase_stop' failed: " << resp << endl;
544 return;
545 }
546 }
547
548 void TSTLogger::log_testsuite_start(const TitanLoggerApi::TimestampType& timestamp)
549 {
550 map<string,string> req_params;
551 req_params["fwName"] = "TITAN";
552 stringstream titanver_ss;
553 titanver_ss << TTCN3_MAJOR << '.' << TTCN3_MINOR << ".pl" << TTCN3_PATCHLEVEL;
554 req_params["fwVersion"] = titanver_ss.str();
555 req_params["suiteStartTime"] = get_tst_time_str(timestamp);
556 req_params["testConfigName"] = parameters["testConfigName"].get_value();
557 req_params["suiteName"] = parameters["suiteName"].get_value();
558 req_params["executingHost"] = parameters["executingHost"].get_value();
559 req_params["sutId"] = parameters["sutId"].get_value();
560 req_params["sutName"] = parameters["sutName"].get_value();
561 req_params["lsvMajor"] = parameters["lsvMajor"].get_value();
562 req_params["lsvMinor"] = parameters["lsvMinor"].get_value();
563 req_params["runByUser"] = parameters["runByUser"].get_value();
564 req_params["projectName"] = parameters["projectName"].get_value();
565 req_params["productName"] = parameters["productName"].get_value();
566 req_params["productVersion"] = parameters["productVersion"].get_value();
567 req_params["notRun"] = "1"; // FIXME?
568 req_params["configType"] = parameters["configType"].get_value();
569 req_params["configVersion"] = parameters["configVersion"].get_value();
570 req_params["testType"] = parameters["testType"].get_value();
571 req_params["logLink"] = parameters["logLink"].get_value();
572 req_params["logEnd"] = parameters["logEnd"].get_value();
573 req_params["reportEmail"] = parameters["reportEmail"].get_value();
574 req_params["reportTelnum"] = parameters["reportTelnum"].get_value();
575
576 string resp = post_message(req_params, parameters["tst_tsstart_url"].get_value());
577
578 if ((resp.find("done") != string::npos) && (resp.find("suiteId") != string::npos)) {
579 this->suite_id_ = resp.substr(resp.find("=") + 1);
580 if (log_plugin_debug()) {
581 cout << this->name_ << ": " << "Operation `log_testsuite_start' successful, returned suiteId=" << this->suite_id_ << endl;
582 }
583 } else {
584 cerr << this->name_ << ": " << "Operation `log_testsuite_start' failed: " << resp << endl;
585 return;
586 }
587 }
588
589 void TSTLogger::log_testsuite_stop(const TitanLoggerApi::TimestampType& timestamp)
590 {
591 map<string,string> req_params;
592 req_params["suiteId"] = this->suite_id_;
593 req_params["tsEndTime"] = get_tst_time_str(timestamp);
594 req_params["reportEmail"] = parameters["reportEmail"].get_value();
595 req_params["reportTelnum"] = parameters["reportTelnum"].get_value();
596
597 string resp = post_message(req_params, parameters["tst_tsstop_url"].get_value());
598
599 if (!resp.compare("done")) {
600 if (log_plugin_debug()) {
601 cout << this->name_ << ": " << "Operation `log_testsuite_stop' successful" << endl;
602 }
603 } else {
604 cerr << this->name_ << ": " << "Operation `log_testsuite_stop' failed: " << resp << endl;
605 }
606 }
607
608 void TSTLogger::log_verdictop_reason(const TitanLoggerApi::VerdictOp& verdictOp)
609 {
610 if (verdictOp.choice().get_selection() == TitanLoggerApi::VerdictOp_choice::ALT_setVerdict) {
611 TitanLoggerApi::SetVerdictType setVerdict = verdictOp.choice().setVerdict();
612 if (setVerdict.newReason().ispresent() && setVerdict.newReason()().lengthof()>0) {
613 map<string,string> req_params;
614 req_params["tcaseId"] = this->tcase_id_;
615 req_params["tcFailType"] = "0"; //?
616 req_params["tcFailNum"] = "1";
617 req_params["tcFailReason"] = (const char *)setVerdict.newReason()();
618 string resp = post_message(req_params, parameters["tst_tcfailreason_url"].get_value());
619 if (!resp.compare("done")) {
620 if (log_plugin_debug()) {
621 cout << this->name_ << ": " << "Operation log_verdictop_reason' successful" << endl;
622 }
623 } else {
624 cerr << this->name_ << ": " << "Operation log_verdictop_reason' failed: " << resp << endl;
625 }
626 }
627 }
628 }
This page took 0.13946 seconds and 5 git commands to generate.