00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <getopt.h>
00029 #include <errno.h>
00030 #include <string.h>
00031 #include <fcntl.h>
00032 #include <unistd.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <libxml/parser.h>
00036 #include <libxml/tree.h>
00037 #include <signal.h>
00038 #include <ctype.h>
00039
00040 #include "testrunnerlite.h"
00041 #include "testdefinitionparser.h"
00042 #include "testresultlogger.h"
00043 #include "testfilters.h"
00044 #include "executor.h"
00045 #include "remote_executor.h"
00046 #include "manual_executor.h"
00047 #include "utils.h"
00048 #include "log.h"
00049
00050
00051
00052
00053
00054
00055
00056 extern char* optarg;
00057
00058
00059
00060
00061
00062
00063
00064 struct timeval created;
00065 testrunner_lite_options opts;
00066 char *global_failure = NULL;
00067 int bail_out = 0;
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 LOCAL td_suite *current_suite = NULL;
00079 LOCAL td_set *current_set = NULL;
00080 LOCAL xmlChar *cur_case_name = "";
00081 LOCAL int cur_step_num;
00082
00083 LOCAL int passcount = 0;
00084 LOCAL int casecount = 0;
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 LOCAL void process_suite(td_suite *);
00097
00098 LOCAL void process_set(td_set *);
00099
00100 LOCAL int process_case (const void *, const void *);
00101
00102 LOCAL int case_result_na (const void *, const void *);
00103
00104 LOCAL int process_get (const void *, const void *);
00105
00106 LOCAL int step_execute (const void *, const void *);
00107
00108 LOCAL int prepost_steps_execute (const void *, const void *);
00109
00110 LOCAL int step_result_na (const void *, const void *);
00111
00112 LOCAL int step_post_process (const void *, const void *);
00113
00114
00115
00116
00117
00118
00119
00125 LOCAL int step_execute (const void *data, const void *user)
00126 {
00127 int res = CASE_PASS;
00128 td_step *step = (td_step *)data;
00129 td_case *c = (td_case *)user;
00130 exec_data edata;
00131
00132 cur_step_num++;
00133
00134 memset (&edata, 0x0, sizeof (exec_data));
00135 if (bail_out) {
00136 res = CASE_FAIL;
00137 step->has_result = 1;
00138 step->return_code = bail_out;
00139 if (global_failure) {
00140 step->failure_info = xmlCharStrdup (global_failure);
00141 c->failure_info = xmlCharStrdup (global_failure);
00142 }
00143 goto out;
00144 }
00145
00146 if (c->gen.manual) {
00147 res = execute_manual (step);
00148 goto out;
00149 }
00150
00151 init_exec_data(&edata);
00152
00153 if (c->dummy) {
00154
00155 edata.redirect_output = DONT_REDIRECT_OUTPUT;
00156 } else {
00157 edata.redirect_output = REDIRECT_OUTPUT;
00158 }
00159 edata.soft_timeout = c->gen.timeout;
00160 edata.hard_timeout = COMMON_HARD_TIMEOUT;
00161
00162 if (step->step) {
00163 execute((char*)step->step, &edata);
00164
00165 if (step->stdout_) free (step->stdout_);
00166 if (step->stderr_) free (step->stderr_);
00167 if (step->failure_info) free (step->failure_info);
00168
00169 if (edata.stdout_data.buffer) {
00170 step->stdout_ = edata.stdout_data.buffer;
00171 }
00172 if (edata.stderr_data.buffer) {
00173 step->stderr_ = edata.stderr_data.buffer;
00174 }
00175 if (edata.failure_info.buffer) {
00176 step->failure_info = edata.failure_info.buffer;
00177 c->failure_info = xmlCharStrdup ((char *)
00178 step->failure_info);
00179
00180 LOG_MSG (LOG_INFO, "FAILURE INFO: %s",
00181 step->failure_info);
00182 }
00183
00184 step->pgid = edata.pgid;
00185 step->pid = edata.pid;
00186 step->has_result = 1;
00187 step->return_code = edata.result;
00188 step->start = edata.start_time;
00189 step->end = edata.end_time;
00190
00191
00192
00193
00194 if (c->dummy) {
00195 if (step->has_expected_result &&
00196 (step->return_code != step->expected_result)) {
00197 LOG_MSG (LOG_INFO,
00198 "STEP: %s return %d expected %d\n",
00199 step->step, step->return_code,
00200 step->expected_result);
00201 res = CASE_FAIL;
00202 }
00203 } else if (step->return_code != step->expected_result) {
00204 LOG_MSG (LOG_INFO, "STEP: %s return %d expected %d\n",
00205 step->step, step->return_code,
00206 step->expected_result);
00207 res = CASE_FAIL;
00208 }
00209 }
00210 out:
00211 if (res != CASE_PASS)
00212 c->case_res = res;
00213
00214
00215 return (res == CASE_PASS);
00216 }
00217
00218
00224 LOCAL int prepost_steps_execute (const void *data, const void *user)
00225 {
00226 td_steps *steps = (td_steps *)data;
00227 td_case *dummy = (td_case *)user;
00228
00229 if (steps->timeout == 0) {
00230 dummy->gen.timeout = 180;
00231 } else {
00232 dummy->gen.timeout = steps->timeout;
00233 }
00234
00235 if (xmlListSize(steps->steps) > 0) {
00236 xmlListWalk (steps->steps, step_execute, dummy);
00237 }
00238
00239 return 1;
00240 }
00241
00242
00248 LOCAL int step_result_na (const void *data, const void *user)
00249 {
00250 td_step *step = (td_step *)data;
00251 char *failure_info = (char *)user;
00252
00253 step->has_result = 1;
00254 step->return_code = step->expected_result + 255;
00255 step->failure_info = xmlCharStrdup (failure_info);
00256
00257 return 1;
00258 }
00259
00260
00267 LOCAL int step_post_process (const void *data, const void *user)
00268 {
00269 td_step *step = (td_step *)data;
00270 td_case *c = (td_case *)user;
00271
00272
00273 if (c->gen.manual)
00274 goto out;
00275
00276 if (c->filtered)
00277 goto out;
00278
00279
00280 if (!step->start)
00281 goto out;
00282
00283
00284 if (!step->pgid)
00285 goto out;
00286
00287 if (opts.target_address) {
00288 ssh_kill (opts.target_address, step->pid);
00289 }
00290 kill_pgroup(step->pgid, SIGKILL);
00291
00292 out:
00293 return 1;
00294 }
00295
00296
00302 LOCAL int process_case (const void *data, const void *user)
00303 {
00304
00305 td_case *c = (td_case *)data;
00306
00307 if (c->gen.manual && !opts.run_manual) {
00308 LOG_MSG(LOG_DEBUG, "Skipping manual case %s",
00309 c->gen.name);
00310 c->filtered = 1;
00311 return 1;
00312 }
00313 if (!c->gen.manual && !opts.run_automatic) {
00314 LOG_MSG(LOG_DEBUG, "Skipping automatic case %s",
00315 c->gen.name);
00316 c->filtered = 1;
00317 return 1;
00318 }
00319 if (filter_case (c)) {
00320 LOG_MSG (LOG_INFO, "Test case %s is filtered", c->gen.name);
00321 return 1;
00322 }
00323
00324 cur_case_name = c->gen.name;
00325 LOG_MSG (LOG_INFO, "Starting test case %s", c->gen.name);
00326 casecount++;
00327
00328 c->case_res = CASE_PASS;
00329 if (c->gen.timeout == 0)
00330 c->gen.timeout = COMMON_SOFT_TIMEOUT;
00331
00332 if (c->gen.manual && opts.run_manual)
00333 pre_manual (c);
00334 cur_step_num = 0;
00335 xmlListWalk (c->steps, step_execute, data);
00336 xmlListWalk (c->steps, step_post_process, data);
00337
00338 if (c->gen.manual && opts.run_manual)
00339 post_manual (c);
00340
00341 LOG_MSG (LOG_INFO, "Finished test case Result: %s",
00342 case_result_str(c->case_res));
00343 passcount += (c->case_res == CASE_PASS);
00344
00345 return 1;
00346 }
00347
00353 LOCAL int case_result_na (const void *data, const void *user)
00354 {
00355
00356 td_case *c = (td_case *)data;
00357 char *failure_info = (char *)user;
00358
00359 LOG_MSG (LOG_DEBUG, "Setting FAIL result for case %s", c->gen.name);
00360
00361 c->case_res = CASE_FAIL;
00362 c->failure_info = xmlCharStrdup (failure_info);
00363
00364 xmlListWalk (c->steps, step_result_na, user);
00365
00366 return 1;
00367 }
00368
00369
00375 LOCAL int process_get (const void *data, const void *user)
00376 {
00377
00378 td_file *file = (td_file *)data;
00379 xmlChar *command;
00380 char *fname;
00381 exec_data edata;
00382 char *remote = opts.target_address;
00383
00384 memset (&edata, 0x0, sizeof (exec_data));
00385 init_exec_data(&edata);
00386 edata.soft_timeout = COMMON_SOFT_TIMEOUT;
00387 edata.hard_timeout = COMMON_HARD_TIMEOUT;
00388
00389 fname = malloc (strlen((char *)file->filename) + 1);
00390 trim_string ((char *)file->filename, fname);
00391
00392
00393
00394
00395 if (remote) {
00396 opts.target_address = NULL;
00397 command = (xmlChar *)malloc (strlen ("scp ") +
00398 strlen (fname) +
00399 strlen (opts.output_folder) +
00400 strlen (remote) + 10);
00401 sprintf ((char *)command, "scp %s:\'%s\' %s", remote, fname,
00402 opts.output_folder);
00403
00404 } else {
00405 command = (xmlChar *)malloc (strlen ("cp ") +
00406 strlen (fname) +
00407 strlen (opts.output_folder) + 2);
00408 sprintf ((char *)command, "cp %s %s", fname,
00409 opts.output_folder);
00410 }
00411 LOG_MSG (LOG_DEBUG, "%s: Executing command: %s", PROGNAME,
00412 (char*)command);
00413
00414
00415
00416 execute((char*)command, &edata);
00417
00418 if (edata.result) {
00419 LOG_MSG (LOG_ERR, "%s: %s failed: %s\n", PROGNAME, command,
00420 (char *)(edata.stderr_data.buffer ?
00421 edata.stderr_data.buffer :
00422 BAD_CAST "no info available"));
00423 }
00424 opts.target_address = remote;
00425 if (edata.stdout_data.buffer) free (edata.stdout_data.buffer);
00426 if (edata.stderr_data.buffer) free (edata.stderr_data.buffer);
00427 if (edata.failure_info.buffer) free (edata.failure_info.buffer);
00428
00429 if (!file->delete_after)
00430 goto out;
00431
00432 memset (&edata, 0x0, sizeof (exec_data));
00433 init_exec_data(&edata);
00434 edata.soft_timeout = COMMON_SOFT_TIMEOUT;
00435 edata.hard_timeout = COMMON_HARD_TIMEOUT;
00436 sprintf ((char *)command, "rm -f %s", fname);
00437 LOG_MSG (LOG_DEBUG, "%s: Executing command: %s", PROGNAME,
00438 (char*)command);
00439 execute((char*)command, &edata);
00440 if (edata.result) {
00441 LOG_MSG (LOG_ERR, "%s: %s failed: %s\n", PROGNAME, command,
00442 (char *)(edata.stderr_data.buffer ?
00443 edata.stderr_data.buffer :
00444 BAD_CAST "no info available"));
00445 }
00446 if (edata.stdout_data.buffer) free (edata.stdout_data.buffer);
00447 if (edata.stderr_data.buffer) free (edata.stderr_data.buffer);
00448 if (edata.failure_info.buffer) free (edata.failure_info.buffer);
00449
00450 out:
00451 free (command);
00452 free (fname);
00453 return 1;
00454 }
00455
00459 LOCAL void process_suite (td_suite *s)
00460 {
00461 LOG_MSG (LOG_INFO, "Test suite: %s", s->gen.name);
00462
00463 write_pre_suite_tag (s);
00464 current_suite = s;
00465
00466 }
00467
00470 LOCAL void end_suite ()
00471 {
00472 write_post_suite_tag ();
00473 td_suite_delete (current_suite);
00474 current_suite = NULL;
00475 }
00476
00480 LOCAL void process_set (td_set *s)
00481 {
00482 td_case dummy;
00483
00484
00485
00486
00487 if (filter_set (s)) {
00488 LOG_MSG (LOG_INFO, "Test set %s is filtered", s->gen.name);
00489 goto skip_all;
00490 }
00491
00492
00493
00494
00495 s->environment = xmlCharStrdup (opts.environment);
00496 if (!xmlListSearch (s->environments, opts.environment)) {
00497 LOG_MSG (LOG_INFO, "Test set %s not run on "
00498 "environment: %s",
00499 s->gen.name, opts.environment);
00500 goto skip_all;
00501 }
00502 current_set = s;
00503 LOG_MSG (LOG_INFO, "Test set: %s", s->gen.name);
00504 write_pre_set_tag (s);
00505
00506 if (xmlListSize (s->pre_steps) > 0) {
00507 cur_case_name = (xmlChar *)"pre_steps";
00508 cur_step_num = 0;
00509 memset (&dummy, 0x0, sizeof (td_case));
00510 dummy.case_res = CASE_PASS;
00511 dummy.dummy = 1;
00512 LOG_MSG (LOG_INFO, "Executing pre steps");
00513 xmlListWalk (s->pre_steps, prepost_steps_execute, &dummy);
00514 if (dummy.case_res != CASE_PASS) {
00515 LOG_MSG (LOG_ERR, "Pre steps failed. "
00516 "Test set %s aborted.", s->gen.name);
00517 xmlListWalk (s->cases, case_result_na,
00518 global_failure ? global_failure :
00519 "pre_steps failed");
00520 goto short_circuit;
00521 }
00522 }
00523
00524 xmlListWalk (s->cases, process_case, s);
00525 if (xmlListSize (s->post_steps) > 0) {
00526 LOG_MSG (LOG_INFO, "Executing post steps");
00527 cur_case_name = (xmlChar *)"post_steps";
00528 cur_step_num = 0;
00529 memset (&dummy, 0x0, sizeof (td_case));
00530 dummy.case_res = CASE_PASS;
00531 dummy.dummy = 1;
00532 xmlListWalk (s->post_steps, prepost_steps_execute, &dummy);
00533 if (dummy.case_res == CASE_FAIL)
00534 LOG_MSG (LOG_ERR,
00535 "Post steps failed for %s.", s->gen.name);
00536 }
00537 xmlListWalk (s->gets, process_get, s);
00538
00539 short_circuit:
00540 write_post_set_tag (s);
00541 if (xmlListSize (s->pre_steps) > 0)
00542 xmlListWalk (s->pre_steps, step_post_process, &dummy);
00543 if (xmlListSize (s->post_steps) > 0)
00544 xmlListWalk (s->post_steps, step_post_process, &dummy);
00545 xml_end_element();
00546 skip_all:
00547 td_set_delete (s);
00548 return;
00549 }
00550
00551
00552
00556 void td_process () {
00557 int retval;
00558 td_parser_callbacks cbs;
00559
00560 memset (&cbs, 0x0, sizeof(td_parser_callbacks));
00561
00562
00563
00564 cbs.test_suite = process_suite;
00565 cbs.test_suite_end = end_suite;
00566 cbs.test_set = process_set;
00567
00568 retval = td_register_callbacks (&cbs);
00569
00570
00571
00572
00573 LOG_MSG (LOG_INFO, "Starting to run tests...");
00574
00575 while (td_next_node() == 0);
00576
00577 LOG_MSG (LOG_INFO, "Finished running tests.");
00578 LOG_MSG (LOG_INFO, "Executed %d cases. Passed %d Failed %d",
00579 casecount, passcount, casecount - passcount);
00580 return;
00581 }
00582
00586 const char *current_set_name ()
00587 {
00588 if (current_set)
00589 return (char *)current_set->gen.name;
00590 return "";
00591 }
00592
00596 const char *current_case_name ()
00597 {
00598 return (char *)cur_case_name;
00599 }
00600
00604 int current_step_num ()
00605 {
00606 return cur_step_num;
00607 }
00608
00609
00610
00611
00612
00613