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 <time.h>
00027 #include <stdio.h>
00028 #include <errno.h>
00029 #include <string.h>
00030 #include <libxml/xmlwriter.h>
00031 #include "testresultlogger.h"
00032 #include "log.h"
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 LOCAL xmlTextWriterPtr writer;
00061 LOCAL FILE *ofile;
00062
00063
00064
00065
00066
00067
00068 struct
00069 {
00070 int (*write_pre_suite_tag) (td_suite *);
00071 int (*write_post_suite_tag) (void);
00072 int (*write_pre_set_tag) (td_set *);
00073 int (*write_post_set_tag) (td_set *);
00074 } out_cbs;
00075
00076
00077
00078 LOCAL int xml_write_pre_suite_tag (td_suite *);
00079
00080 LOCAL int xml_write_pre_set_tag (td_set *);
00081
00082 LOCAL int xml_write_step (const void *, const void *);
00083
00084 LOCAL int xml_write_case (const void *, const void *);
00085
00086 LOCAL int xml_write_post_set_tag (td_set *);
00087
00088 LOCAL int txt_write_pre_suite_tag (td_suite *);
00089
00090 LOCAL int txt_write_post_suite_tag ();
00091
00092 LOCAL int txt_write_pre_set_tag (td_set *);
00093
00094 LOCAL int txt_write_post_set_tag (td_set *);
00095
00096 LOCAL int txt_write_case (const void *, const void *);
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00111 LOCAL int xml_write_pre_suite_tag (td_suite *suite)
00112 {
00113
00114 if (xmlTextWriterStartElement (writer, BAD_CAST "suite") < 0)
00115 goto err_out;
00116
00117 if (xmlTextWriterWriteAttribute (writer, BAD_CAST "name",
00118 suite->gen.name) < 0)
00119 goto err_out;
00120
00121 if (suite->domain && xmlTextWriterWriteAttribute (writer,
00122 BAD_CAST "domain",
00123 suite->domain) < 0)
00124 goto err_out;
00125
00126 return 0;
00127 err_out:
00128 return 1;
00129 }
00130
00135 LOCAL int xml_write_pre_set_tag (td_set *set)
00136 {
00137 if (xmlTextWriterStartElement (writer, BAD_CAST "set") < 0)
00138 goto err_out;
00139
00140 if (xmlTextWriterWriteAttribute (writer,
00141 BAD_CAST "name",
00142 set->gen.name) < 0)
00143 goto err_out;
00144
00145 if (set->gen.description)
00146 if (xmlTextWriterWriteAttribute (writer,
00147 BAD_CAST "description",
00148 set->gen.description) < 0)
00149 goto err_out;
00150
00151 if (set->feature)
00152 if (xmlTextWriterWriteAttribute (writer,
00153 BAD_CAST "feature",
00154 set->feature) < 0)
00155 goto err_out;
00156
00157 if (set->environment)
00158 if (xmlTextWriterWriteAttribute (writer,
00159 BAD_CAST "environment",
00160 set->environment) < 0)
00161 goto err_out;
00162 return 0;
00163 err_out:
00164 return 1;
00165 }
00166
00172 LOCAL int xml_write_step (const void *data, const void *user)
00173 {
00174 td_step *step = (td_step *)data;
00175 struct tm *tm;
00176
00177 if (xmlTextWriterStartElement (writer, BAD_CAST "step") < 0)
00178 goto err_out;
00179
00180 if (xmlTextWriterWriteAttribute (writer,
00181 BAD_CAST "command",
00182 step->step) < 0)
00183 goto err_out;
00184
00185 if (step->has_result == 0) {
00186 if (xmlTextWriterWriteAttribute (writer,
00187 BAD_CAST "result",
00188 BAD_CAST "N/A") < 0)
00189 goto err_out;
00190
00191
00192 } else if (xmlTextWriterWriteAttribute (writer,
00193 BAD_CAST "result",
00194 step->expected_result ==
00195 step->return_code ?
00196 BAD_CAST "PASS" :
00197 BAD_CAST "FAIL") < 0)
00198 goto err_out;
00199
00200 if (step->failure_info) {
00201 if (strlen ((char *)step->failure_info) >= FAILURE_INFO_MAX)
00202 step->failure_info[FAILURE_INFO_MAX - 1] = '\0';
00203 if (xmlTextWriterWriteAttribute (writer,
00204 BAD_CAST "failure_info",
00205 step->failure_info) < 0)
00206 goto err_out;
00207 }
00208
00209 if (xmlTextWriterWriteFormatElement (writer,
00210 BAD_CAST "expected_result",
00211 "%d", step->expected_result) < 0)
00212 goto err_out;
00213
00214 if (xmlTextWriterWriteFormatElement (writer,
00215 BAD_CAST "return_code",
00216 "%d", step->return_code) < 0)
00217 goto err_out;
00218
00219 tm = localtime (&step->start);
00220 if (xmlTextWriterWriteFormatElement (writer,
00221 BAD_CAST "start",
00222 "%02d-%02d-%02d %02d:%02d:%02d",
00223 tm->tm_year+1900,
00224 tm->tm_mon+1,
00225 tm->tm_mday,
00226 tm->tm_hour,
00227 tm->tm_min,
00228 tm->tm_sec) < 0)
00229 goto err_out;
00230
00231 tm = localtime (&step->end);
00232 if (xmlTextWriterWriteFormatElement (writer,
00233 BAD_CAST "end",
00234 "%02d-%02d-%02d %02d:%02d:%02d",
00235 tm->tm_year+1900,
00236 tm->tm_mon+1,
00237 tm->tm_mday,
00238 tm->tm_hour,
00239 tm->tm_min,
00240 tm->tm_sec) < 0)
00241 goto err_out;
00242
00243 if (step->stdout_)
00244 if (xmlTextWriterWriteFormatElement (writer,
00245 BAD_CAST "stdout",
00246 "%s",
00247 step->stdout_) < 0)
00248 goto err_out;
00249
00250 if (step->stderr_)
00251 if (xmlTextWriterWriteFormatElement (writer,
00252 BAD_CAST "stderr",
00253 "%s",
00254 step->stderr_) < 0)
00255 goto err_out;
00256
00257
00258 xml_end_element();
00259
00260
00261 return 1;
00262
00263 err_out:
00264 return 0;
00265 }
00266
00272 LOCAL int xml_write_case (const void *data, const void *user)
00273 {
00274 td_case *c = (td_case *)data;
00275
00276 if (c->filtered)
00277 return 1;
00278
00279 if (xmlTextWriterStartElement (writer, BAD_CAST "case") < 0)
00280 goto err_out;
00281
00282 if (xmlTextWriterWriteAttribute (writer,
00283 BAD_CAST "name",
00284 c->gen.name) < 0)
00285 goto err_out;
00286
00287 if (c->gen.description)
00288 if (xmlTextWriterWriteAttribute (writer,
00289 BAD_CAST "description",
00290 c->gen.description) < 0)
00291 goto err_out;
00292
00293 if (xmlTextWriterWriteAttribute (writer,
00294 BAD_CAST "manual",
00295 BAD_CAST (c->gen.manual ? "true" :
00296 "false")) < 0)
00297 goto err_out;
00298
00299 if (xmlTextWriterWriteAttribute (writer,
00300 BAD_CAST "insignificant",
00301 BAD_CAST (c->gen.insignificant ?
00302 "true" :
00303 "false")) < 0)
00304 goto err_out;
00305
00306
00307 if (xmlTextWriterWriteAttribute (writer,
00308 BAD_CAST "result",
00309 BAD_CAST (case_result_str
00310 (c->case_res))) < 0)
00311
00312 goto err_out;
00313
00314 if (c->failure_info) {
00315 if (strlen ((char *)c->failure_info) >= FAILURE_INFO_MAX)
00316 c->failure_info[FAILURE_INFO_MAX - 1] = '\0';
00317 if (xmlTextWriterWriteAttribute (writer,
00318 BAD_CAST "failure_info",
00319 c->failure_info) < 0)
00320 goto err_out;
00321 }
00322
00323 if (c->subfeature)
00324 if (xmlTextWriterWriteAttribute (writer,
00325 BAD_CAST "subfeature",
00326 c->subfeature) < 0)
00327 goto err_out;
00328
00329 if (c->gen.requirement)
00330 if (xmlTextWriterWriteAttribute (writer,
00331 BAD_CAST "requirement",
00332 c->gen.requirement) < 0)
00333 goto err_out;
00334
00335 if (c->gen.level)
00336 if (xmlTextWriterWriteAttribute (writer,
00337 BAD_CAST "level",
00338 c->gen.level) < 0)
00339 goto err_out;
00340
00341 if (c->gen.manual && c->comment)
00342 if (xmlTextWriterWriteAttribute (writer,
00343 BAD_CAST "comment",
00344 c->comment) < 0)
00345 goto err_out;
00346
00347
00348 xmlListWalk (c->steps, xml_write_step, NULL);
00349
00350 xml_end_element ();
00351
00352 return 1;
00353
00354 err_out:
00355 LOG_MSG (LOG_ERR, "%s:%s: error\n", PROGNAME, __FUNCTION__);
00356
00357 return 0;
00358 }
00359
00364 LOCAL int xml_write_post_set_tag (td_set *set)
00365 {
00366
00367
00368 xmlListWalk (set->cases, xml_write_case, NULL);
00369
00370 return 0;
00371 }
00372
00373
00374
00380 LOCAL int txt_write_step (const void *data, const void *user)
00381 {
00382 td_step *step = (td_step *)data;
00383 struct tm *tm;
00384 fprintf (ofile, "----------------------------------"
00385 "----------------------------------\n");
00386 fprintf (ofile, " Test step : %s\n", step->step);
00387 tm = localtime (&step->start);
00388
00389 fprintf (ofile, " start : %02d-%02d-%02d"
00390 " %02d:%02d:%02d\n",
00391 tm->tm_year+1900,
00392 tm->tm_mon+1,
00393 tm->tm_mday,
00394 tm->tm_hour,
00395 tm->tm_min,
00396 tm->tm_sec);
00397 tm = localtime (&step->end);
00398 fprintf (ofile, " end : %02d-%02d-%02d"
00399 " %02d:%02d:%02d\n",
00400 tm->tm_year+1900,
00401 tm->tm_mon+1,
00402 tm->tm_mday,
00403 tm->tm_hour,
00404 tm->tm_min,
00405 tm->tm_sec);
00406 fprintf (ofile, " expected code : %d\n", step->expected_result);
00407 fprintf (ofile, " return code : %d\n", step->return_code);
00408 fprintf (ofile, " result : %s %s\n",
00409 (step->return_code == step->expected_result ? "PASS" : "FAIL"),
00410 (step->failure_info ? (char *)step->failure_info : " "));
00411 fprintf (ofile, " stdout : %s\n",
00412 step->stdout_ ? (char *)step->stdout_ : " ");
00413 fprintf (ofile, " stderr : %s\n",
00414 step->stderr_ ? (char *)step->stderr_ : " ");
00415 fflush (ofile);
00416
00417 return 1;
00418 }
00419
00425 LOCAL int txt_write_case (const void *data, const void *user)
00426 {
00427 td_case *c = (td_case *)data;
00428
00429 if (c->filtered)
00430 return 1;
00431
00432 fprintf (ofile, "----------------------------------"
00433 "----------------------------------\n");
00434 fprintf (ofile, " Test case name : %s\n", c->gen.name);
00435 fprintf (ofile, " description : %s\n", c->gen.description ?
00436 (char *)c->gen.description : "");
00437 fprintf (ofile, " manual : %s\n", c->gen.manual ?
00438 "true" : "false");
00439 fprintf (ofile, " result : %s",
00440 case_result_str(c->case_res));
00441 if (c->failure_info) {
00442 fprintf (ofile, " (%s)", c->failure_info);
00443 }
00444 fprintf (ofile, "\n");
00445
00446 if (c->gen.requirement)
00447 fprintf (ofile, " requirement : %s\n", c->gen.requirement);
00448 if (c->subfeature)
00449 fprintf (ofile, " subfeature : %s\n", c->subfeature);
00450 #if 0
00451 if (c->gen.type)
00452 fprintf (ofile, " type : %s\n", c->gen.type);
00453 #endif
00454 if (c->gen.level)
00455 fprintf (ofile, " level : %s\n", c->gen.level);
00456
00457 fprintf (ofile, " insignificant : %s\n", c->gen.insignificant ?
00458 "true" : "false");
00459
00460
00461 if (c->gen.manual && c->comment)
00462 fprintf (ofile, " comment : %s\n", c->comment);
00463
00464 fflush (ofile);
00465
00466 xmlListWalk (c->steps, txt_write_step, NULL);
00467
00468
00469 return 1;
00470 }
00475 LOCAL int txt_write_pre_suite_tag (td_suite *suite)
00476 {
00477 fprintf (ofile, "----------------------------------"
00478 "----------------------------------\n");
00479
00480 fprintf (ofile, "Test suite name : %s\n", suite->gen.name);
00481 fprintf (ofile, " description : %s\n", suite->gen.description ?
00482 (char *)suite->gen.description : " ");
00483 if (suite->domain)
00484 fprintf (ofile, " domain : %s\n", suite->domain);
00485
00486 fflush (ofile);
00487
00488 return 0;
00489 }
00490
00494 LOCAL int txt_write_post_suite_tag ()
00495 {
00496 return 0;
00497
00498 }
00499
00504 LOCAL int txt_write_pre_set_tag (td_set *set)
00505 {
00506 fprintf (ofile, "----------------------------------"
00507 "----------------------------------\n");
00508
00509 fprintf (ofile, " Test set name : %s\n", set->gen.name);
00510 fprintf (ofile, " description : %s\n", set->gen.description ?
00511 (char *)set->gen.description : "");
00512 if (set->feature)
00513 fprintf (ofile, " feature : %s\n", set->feature);
00514
00515 fprintf (ofile, " environment : %s\n", set->environment ?
00516 (char *)set->environment : "");
00517
00518 fflush (ofile);
00519 return 0;
00520
00521 }
00522
00527 LOCAL int txt_write_post_set_tag (td_set *set)
00528 {
00529
00530 xmlListWalk (set->cases, txt_write_case, NULL);
00531 fflush (ofile);
00532
00533 return 0;
00534 }
00535
00536
00537
00543 int init_result_logger (testrunner_lite_options *opts, hw_info *hwinfo)
00544 {
00545
00546 switch (opts->output_type) {
00547 case OUTPUT_TYPE_XML:
00548
00549
00550
00551 writer = xmlNewTextWriterFilename(opts->output_filename, 0);
00552 if (!writer) {
00553 LOG_MSG (LOG_ERR, "%s:%s:failed to create writer for %s\n",
00554 PROGNAME, __FUNCTION__, opts->output_filename);
00555 return 1;
00556 }
00557 xmlTextWriterSetIndent (writer, 1);
00558 if (xmlTextWriterStartDocument(writer,
00559 "1.0",
00560 "UTF-8",
00561 NULL) < 0) {
00562 LOG_MSG (LOG_ERR, "%s:%s:failed to write document start\n",
00563 PROGNAME, __FUNCTION__);
00564 return 1;
00565 }
00566
00567 if (xmlTextWriterStartElement (writer, BAD_CAST "testresults")
00568 < 0) {
00569 LOG_MSG (LOG_ERR, "%s:%s:failed to write testsresults tag\n",
00570 PROGNAME, __FUNCTION__);
00571 return 1;
00572 }
00573 if (xmlTextWriterWriteAttribute (writer,
00574 BAD_CAST "version",
00575 BAD_CAST "1.0") < 0)
00576 return 1;
00577
00578 if (xmlTextWriterWriteAttribute (writer,
00579 BAD_CAST "environment",
00580 BAD_CAST (opts->environment ?
00581 opts->environment :
00582 "unknown")) < 0)
00583 return 1;
00584
00585
00586 if (xmlTextWriterWriteAttribute (writer,
00587 BAD_CAST "hwproduct",
00588 (hwinfo->product ?
00589 hwinfo->product :
00590 BAD_CAST "unknown")) < 0)
00591 return 1;
00592
00593
00594
00595 if (xmlTextWriterWriteAttribute (writer,
00596 BAD_CAST "hwbuild",
00597 (hwinfo->hw_build ?
00598 hwinfo->hw_build :
00599 BAD_CAST "unknown")) < 0)
00600 return 1;
00601
00602
00603
00604
00605
00606 out_cbs.write_pre_suite_tag = xml_write_pre_suite_tag;
00607 out_cbs.write_post_suite_tag = xml_end_element;
00608 out_cbs.write_pre_set_tag = xml_write_pre_set_tag;
00609 out_cbs.write_post_set_tag = xml_write_post_set_tag;
00610
00611
00612 break;
00613
00614 case OUTPUT_TYPE_TXT:
00615
00616
00617
00618 ofile = fopen (opts->output_filename, "w+");
00619 if (!ofile) {
00620 LOG_MSG (LOG_ERR, "%s:%s:failed to open file %s %s\n",
00621 PROGNAME, __FUNCTION__, opts->output_filename,
00622 strerror(errno));
00623 return 1;
00624 }
00625 fprintf (ofile,"Test results:\n");
00626 fprintf (ofile, " environment : %s\n", opts->environment);
00627
00628 fprintf (ofile, " hwproduct : %s\n",
00629 (char *)(hwinfo->product ? hwinfo->product :
00630 (unsigned char *)"unknown"));
00631
00632 fprintf (ofile, " hwbuild : %s\n",
00633 (char *)(hwinfo->hw_build ? hwinfo->hw_build :
00634 (unsigned char *)"unknown"));
00635
00636
00637
00638
00639
00640 out_cbs.write_pre_suite_tag = txt_write_pre_suite_tag;
00641 out_cbs.write_post_suite_tag = txt_write_post_suite_tag;
00642 out_cbs.write_pre_set_tag = txt_write_pre_set_tag;
00643 out_cbs.write_post_set_tag = txt_write_post_set_tag;
00644
00645 break;
00646
00647 default:
00648 LOG_MSG (LOG_ERR, "%s:%s:invalid output type %d\n",
00649 PROGNAME, __FUNCTION__, opts->output_type);
00650 return 1;
00651 }
00652
00653 return 0;
00654 }
00655
00660 int write_pre_suite_tag (td_suite *suite)
00661 {
00662 return out_cbs.write_pre_suite_tag (suite);
00663 }
00664
00669 int write_post_suite_tag (td_suite *suite)
00670 {
00671
00672 return out_cbs.write_post_suite_tag ();
00673 }
00674
00679 int write_pre_set_tag (td_set *set)
00680 {
00681 return out_cbs.write_pre_set_tag (set);
00682 }
00683
00688 int write_post_set_tag (td_set *set)
00689 {
00690
00691 return out_cbs.write_post_set_tag (set);
00692 }
00693
00697 int xml_end_element ()
00698 {
00699
00700 if (xmlTextWriterFullEndElement (writer) < 0)
00701 goto err_out;
00702 return 0;
00703 err_out:
00704 return 1;
00705 }
00706
00709 void close_result_logger (void)
00710 {
00711 if (writer) {
00712 xml_end_element();
00713 xmlTextWriterFlush (writer);
00714 xmlFreeTextWriter (writer);
00715 writer = NULL;
00716 } else if (ofile) {
00717 fprintf (ofile, "----------------------------------"
00718 "----------------------------------\n");
00719 fprintf (ofile, "End of test results.\n");
00720 fflush (ofile);
00721 fclose (ofile);
00722 ofile = NULL;
00723 } else {
00724 LOG_MSG (LOG_ERR, "%s:%s: Result logger not open?\n",
00725 PROGNAME, __FUNCTION__);
00726 }
00727
00728 return;
00729 }
00730
00731
00732
00733
00734