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
00032 #include <libxml/xmlreader.h>
00033 #include <libxml/xmlschemas.h>
00034
00035 #include "testrunnerlite.h"
00036 #include "testdefinitiondatatypes.h"
00037 #include "testdefinitionparser.h"
00038 #include "log.h"
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 LOCAL td_parser_callbacks *cbs;
00066 LOCAL xmlTextReaderPtr reader;
00067 LOCAL xmlSchemaParserCtxtPtr schema_context = NULL;
00068 LOCAL xmlSchemaPtr schema = NULL;
00069 LOCAL td_suite *current_suite;
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 LOCAL int td_parse_gen_attribs (td_gen_attribs *,td_gen_attribs *);
00083
00084 LOCAL int td_parse_suite (void);
00085
00086 LOCAL int td_parse_steps (xmlListPtr, const char *);
00087
00088 LOCAL td_step *td_parse_step (void);
00089
00090 LOCAL int td_parse_case (td_set *s);
00091
00092 LOCAL int td_parse_environments(xmlListPtr);
00093
00094 LOCAL int td_parse_gets(xmlListPtr);
00095
00096 LOCAL int td_parse_set ();
00097
00098
00099
00100
00101
00102
00103
00104 LOCAL int td_parse_gen_attribs (td_gen_attribs *attr,
00105 td_gen_attribs *defaults)
00106 {
00107 const xmlChar *name;
00108
00109 if (defaults) {
00110 attr->timeout = defaults->timeout;
00111 attr->manual = defaults->manual;
00112 attr->insignificant = defaults->insignificant;
00113 if (defaults->requirement)
00114 attr->requirement = xmlStrdup(defaults->requirement);
00115 if (defaults->level)
00116 attr->level = xmlStrdup(defaults->level);
00117 if (defaults->type)
00118 attr->type = xmlStrdup(defaults->type);
00119 }
00120
00121 while (xmlTextReaderMoveToNextAttribute(reader)) {
00122 name = xmlTextReaderConstName(reader);
00123 if (!xmlStrcmp (name, BAD_CAST "name")) {
00124 attr->name = xmlTextReaderValue(reader);
00125 continue;
00126 }
00127 if (!xmlStrcmp (name, BAD_CAST "timeout")) {
00128 attr->timeout = strtoul((char *)
00129 xmlTextReaderConstValue(reader),
00130 NULL, 10);
00131 continue;
00132 }
00133 if (!xmlStrcmp (name, BAD_CAST "description")) {
00134 attr->description = xmlTextReaderValue(reader);
00135 continue;
00136 }
00137 if (!xmlStrcmp (name, BAD_CAST "requirement")) {
00138 if (attr->requirement) free (attr->requirement);
00139 attr->requirement = xmlTextReaderValue(reader);
00140 continue;
00141 }
00142 if (!xmlStrcmp (name, BAD_CAST "type")) {
00143 if (attr->type) free (attr->type);
00144 attr->type = xmlTextReaderValue(reader);
00145 continue;
00146 }
00147 if (!xmlStrcmp (name, BAD_CAST "level")) {
00148 if (attr->level) free (attr->level);
00149 attr->level = xmlTextReaderValue(reader);
00150 continue;
00151 }
00152
00153 if (!xmlStrcmp (name, BAD_CAST "manual")) {
00154 attr->manual = !xmlStrcmp (xmlTextReaderConstValue
00155 (reader), BAD_CAST "true");
00156 continue;
00157 }
00158 if (!xmlStrcmp (name, BAD_CAST "insignificant")) {
00159 attr->insignificant =
00160 !xmlStrcmp (xmlTextReaderConstValue (reader),
00161 BAD_CAST "true");
00162 continue;
00163 }
00164 }
00165 return 0;
00166 }
00167
00171 LOCAL td_step *td_parse_step()
00172 {
00173 const xmlChar *name;
00174 td_step *step = NULL;
00175 xmlNodePtr node;
00176 int ret;
00177
00178 step = td_step_create();
00179 if (xmlTextReaderMoveToAttribute (reader,
00180 BAD_CAST "expected_result") == 1) {
00181 step->expected_result = strtoul((char *)
00182 xmlTextReaderConstValue(reader),
00183 NULL, 10);
00184 step->has_expected_result = 1;
00185 }
00186
00187 do {
00188 ret = xmlTextReaderRead(reader);
00189 if (!ret) {
00190 LOG_MSG (LOG_ERR, "%s:%s: ReaderRead() fail\n",
00191 PROGNAME, __FUNCTION__);
00192
00193 goto ERROUT;
00194 }
00195 name = xmlTextReaderConstName(reader);
00196 if (!name) {
00197 LOG_MSG (LOG_ERR, "%s: ReaderName() fail\n",
00198 PROGNAME);
00199 goto ERROUT;
00200 }
00201
00202 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) {
00203 if (step->step)
00204 step->step = xmlStrcat
00205 (step->step,
00206 xmlTextReaderReadString (reader));
00207 else
00208 step->step = xmlTextReaderReadString (reader);
00209 }
00210
00211 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_CDATA) {
00212 node = xmlTextReaderCurrentNode (reader);
00213 if (step->step)
00214 step->step = xmlStrcat
00215 (step->step,
00216 node->content);
00217 else
00218 step->step = xmlStrdup(node->content);
00219
00220 }
00221
00222 } while (!(xmlTextReaderNodeType(reader) ==
00223 XML_READER_TYPE_END_ELEMENT &&
00224 !xmlStrcmp (name, BAD_CAST "step")));
00225
00226 return step;
00227 ERROUT:
00228 LOG_MSG (LOG_ERR, "%s:%s: Exiting with error\n",
00229 PROGNAME, __FUNCTION__);
00230 free (step);
00231
00232 return NULL;
00233 }
00234
00240 LOCAL int td_parse_steps(xmlListPtr list, const char *tag)
00241 {
00242 const xmlChar *name;
00243 td_steps *steps = NULL;
00244 td_step *step = NULL;
00245 int ret;
00246
00247 steps = td_steps_create();
00248
00249 if (!steps) {
00250 goto ERROUT;
00251 }
00252
00253 if (xmlTextReaderMoveToAttribute (reader, BAD_CAST "timeout") == 1) {
00254 steps->timeout = strtoul((char *)
00255 xmlTextReaderConstValue(reader),
00256 NULL, 10);
00257 }
00258
00259 do {
00260 ret = xmlTextReaderRead(reader);
00261 if (!ret) {
00262 LOG_MSG (LOG_ERR, "%s: ReaderRead() fail\n",
00263 PROGNAME);
00264 goto ERROUT;
00265 }
00266
00267 name = xmlTextReaderConstName(reader);
00268 if (!name) {
00269 LOG_MSG (LOG_ERR, "%s: ReaderName() fail\n",
00270 PROGNAME);
00271 goto ERROUT;
00272 }
00273
00274 if (xmlTextReaderNodeType(reader) ==
00275 XML_READER_TYPE_ELEMENT &&
00276 !xmlStrcmp (name, BAD_CAST "step")) {
00277 step = td_parse_step();
00278 if (!step)
00279 goto ERROUT;
00280 if (xmlListAppend (steps->steps, step)) {
00281 LOG_MSG (LOG_ERR, "%s: list insert failed\n",
00282 PROGNAME);
00283 goto ERROUT;
00284 }
00285 }
00286 } while (!(xmlTextReaderNodeType(reader) ==
00287 XML_READER_TYPE_END_ELEMENT &&
00288 !xmlStrcmp (name, BAD_CAST tag)));
00289
00290 xmlListAppend (list, steps);
00291
00292 return 0;
00293 ERROUT:
00294 LOG_MSG (LOG_ERR, "%s:%s: Exiting with error\n",
00295 PROGNAME, __FUNCTION__);
00296 xmlListDelete (steps->steps);
00297 free(steps);
00298 return 1;
00299 }
00300
00305 LOCAL int td_parse_case(td_set *s)
00306 {
00307 const xmlChar *name;
00308 td_step *step = NULL;
00309 td_case *c = NULL;
00310 int ret;
00311
00312 c = td_case_create();
00313 if (!c)
00314 goto ERROUT;
00315
00316 if (td_parse_gen_attribs (&c->gen, &s->gen))
00317 goto ERROUT;
00318
00319 if (xmlTextReaderMoveToAttribute (reader,
00320 BAD_CAST "subfeature") == 1) {
00321 c->subfeature = xmlTextReaderValue(reader);
00322 }
00323
00324 do {
00325 ret = xmlTextReaderRead(reader);
00326 if (!ret) {
00327 LOG_MSG (LOG_ERR, "%s: ReaderRead() fail\n",
00328 PROGNAME);
00329
00330 goto ERROUT;
00331 }
00332 name = xmlTextReaderConstName(reader);
00333 if (!name) {
00334 LOG_MSG (LOG_ERR, "%s: ReaderName() fail\n",
00335 PROGNAME);
00336 goto ERROUT;
00337 }
00338 if (xmlTextReaderNodeType(reader) ==
00339 XML_READER_TYPE_ELEMENT &&
00340 !xmlStrcmp (name, BAD_CAST "step")) {
00341 step = td_parse_step();
00342 if (!step)
00343 goto ERROUT;
00344 if (xmlListAppend (c->steps, step)) {
00345 LOG_MSG (LOG_ERR, "%s: list insert failed\n",
00346 PROGNAME);
00347 goto ERROUT;
00348 }
00349 }
00350
00351 } while (!(xmlTextReaderNodeType(reader) ==
00352 XML_READER_TYPE_END_ELEMENT &&
00353 !xmlStrcmp (name, BAD_CAST "case")));
00354
00355 xmlListAppend (s->cases, c);
00356
00357 return 0;
00358 ERROUT:
00359 LOG_MSG (LOG_ERR, "%s:%s: Exiting with error\n",
00360 PROGNAME, __FUNCTION__);
00361 xmlListDelete (c->steps);
00362 if (c->gen.name) free (c->gen.name);
00363 if (c->gen.description) free (c->gen.description);
00364 free (c);
00365 return 1;
00366 }
00367
00372 LOCAL int td_parse_environments(xmlListPtr list)
00373 {
00374 int ret;
00375 const xmlChar *name;
00376 xmlChar *value;
00377
00378 do {
00379 ret = xmlTextReaderRead(reader);
00380 if (!ret) {
00381 LOG_MSG (LOG_ERR, "%s:%s: ReaderRead() fail\n",
00382 PROGNAME, __FUNCTION__);
00383
00384 goto ERROUT;
00385 }
00386
00387 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
00388 name = xmlTextReaderConstName(reader);
00389 if (!name) {
00390 LOG_MSG (LOG_ERR, "%s:%s: ReaderName() "
00391 "fail\n",
00392 PROGNAME, __FUNCTION__);
00393 goto ERROUT;
00394 }
00395 }
00396
00397 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) {
00398 value = xmlTextReaderReadString (reader);
00399 if (!xmlStrcmp (value, BAD_CAST "false")) {
00400 xmlListRemoveAll (list, (void *)name);
00401 }
00402 free (value);
00403 }
00404 } while (!(xmlTextReaderNodeType(reader) ==
00405 XML_READER_TYPE_END_ELEMENT &&
00406 !xmlStrcmp (xmlTextReaderConstName(reader),
00407 BAD_CAST "environments")));
00408
00409 return 0;
00410 ERROUT:
00411 LOG_MSG (LOG_ERR, "%s:%s: Exiting with error\n",
00412 PROGNAME, __FUNCTION__);
00413 return 1;
00414 }
00415
00420 LOCAL int td_parse_gets(xmlListPtr list)
00421 {
00422 int ret;
00423 int delete_after = 0;
00424 td_file *file;
00425
00426 do {
00427
00428 ret = xmlTextReaderRead(reader);
00429 if (!ret) {
00430 LOG_MSG (LOG_ERR, "%s:%s: ReaderRead() fail\n",
00431 PROGNAME, __FUNCTION__);
00432
00433 goto ERROUT;
00434 }
00435
00436 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT &&
00437 xmlTextReaderMoveToNextAttribute(reader) == 1) {
00438 delete_after = !xmlStrcmp (xmlTextReaderConstValue
00439 (reader),
00440 BAD_CAST "true");
00441 }
00442
00443
00444 if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_TEXT) {
00445 file = (td_file *)malloc (sizeof (td_file));
00446 file->filename = xmlTextReaderReadString (reader);
00447 file->delete_after = delete_after;
00448 delete_after = 0;
00449 if (xmlListAppend (list, file)) {
00450 LOG_MSG (LOG_ERR,
00451 "%s:%s list insert failed\n",
00452 PROGNAME, __FUNCTION__);
00453 goto ERROUT;
00454 }
00455
00456 }
00457 } while (!(xmlTextReaderNodeType(reader) ==
00458 XML_READER_TYPE_END_ELEMENT &&
00459 !xmlStrcmp (xmlTextReaderConstName(reader),
00460 BAD_CAST "get")));
00461
00462 return 0;
00463 ERROUT:
00464 LOG_MSG (LOG_ERR, "%s:%s: Exiting with error\n",
00465 PROGNAME, __FUNCTION__);
00466 return 1;
00467 }
00468
00472 LOCAL int td_parse_suite ()
00473 {
00474 td_suite *s;
00475
00476 if (!cbs->test_suite)
00477 return 1;
00478
00479 s = td_suite_create();
00480 if (!s) return 1;
00481
00482 current_suite = s;
00483
00484 td_parse_gen_attribs (&s->gen, NULL);
00485 if (xmlTextReaderMoveToAttribute (reader,
00486 BAD_CAST "domain") == 1) {
00487 s->domain = xmlTextReaderValue(reader);
00488 }
00489 cbs->test_suite(s);
00490
00491 return 0;
00492 }
00493
00497 LOCAL int td_parse_set ()
00498 {
00499 int ret = 0;
00500 td_set *s;
00501 const xmlChar *name;
00502
00503 if (!cbs->test_set)
00504 return 1;
00505 s = td_set_create ();
00506
00507 if (td_parse_gen_attribs(&s->gen, ¤t_suite->gen))
00508 goto ERROUT;
00509
00510 if (xmlTextReaderMoveToAttribute (reader,
00511 BAD_CAST "feature") == 1) {
00512 s->feature = xmlTextReaderValue(reader);
00513 }
00514
00515 do {
00516 ret = xmlTextReaderRead(reader);
00517 if (!ret) {
00518 LOG_MSG (LOG_ERR, "%s:%s: ReaderRead() fail\n",
00519 PROGNAME, __FUNCTION__);
00520
00521 goto ERROUT;
00522 }
00523 name = xmlTextReaderConstName(reader);
00524 if (!name) {
00525 LOG_MSG (LOG_ERR, "%s: ReaderName() fail\n",
00526 PROGNAME);
00527 goto ERROUT;
00528 }
00529 if (!xmlStrcmp (name, BAD_CAST "pre_steps"))
00530 ret = !td_parse_steps(s->pre_steps, "pre_steps");
00531 if (!xmlStrcmp (name, BAD_CAST "post_steps"))
00532 ret = !td_parse_steps(s->post_steps, "post_steps");
00533 if (!xmlStrcmp (name, BAD_CAST "case"))
00534 ret = !td_parse_case(s);
00535 if (!xmlStrcmp (name, BAD_CAST "environments"))
00536 ret = !td_parse_environments(s->environments);
00537 if (!xmlStrcmp (name, BAD_CAST "get"))
00538 ret = !td_parse_gets(s->gets);
00539
00540 if (!ret)
00541 goto ERROUT;
00542 } while (!(xmlTextReaderNodeType(reader) ==
00543 XML_READER_TYPE_END_ELEMENT &&
00544 !xmlStrcmp (name, BAD_CAST "set")));
00545 cbs->test_set(s);
00546
00547 return 0;
00548 ERROUT:
00549 LOG_MSG (LOG_ERR, "%s:%s: Exiting with error\n",
00550 PROGNAME, __FUNCTION__);
00551
00552 return 1;
00553 }
00554
00555
00556
00557
00562 int parse_test_definition (testrunner_lite_options *opts)
00563 {
00564 int ret = TESTRUNNER_LITE_XML_PARSE_FAIL;
00565 xmlDocPtr doc = NULL;
00566 xmlParserCtxtPtr ctxt = NULL;
00567 xmlSchemaPtr sch = NULL;
00568 xmlSchemaValidCtxtPtr valid_ctxt = NULL;
00569 xmlSchemaParserCtxtPtr schema_ctxt = NULL;
00570
00571 xmlSubstituteEntitiesDefault(1);
00572
00573
00574
00575
00576 ctxt = xmlNewParserCtxt();
00577 if (ctxt == NULL) {
00578 LOG_MSG (LOG_ERR, "%s: Failed to allocate parser context\n",
00579 PROGNAME);
00580 goto out;
00581 }
00582
00583 doc = xmlCtxtReadFile(ctxt, opts->input_filename, NULL, XML_PARSE_NOENT);
00584 if (doc == NULL) {
00585 LOG_MSG (LOG_ERR, "%s: Failed to parse %s\n", PROGNAME,
00586 opts->input_filename);
00587 goto out;
00588 } else if (!ctxt->valid) {
00589 LOG_MSG (LOG_ERR, "%s: Failed to validate %s\n", PROGNAME,
00590 opts->input_filename);
00591 xmlFreeDoc(doc);
00592 doc = NULL;
00593 goto out;
00594 }
00595
00596 if (opts->disable_schema) {
00597 ret = 0;
00598 goto out;
00599 }
00600
00601
00602
00603 if (opts->semantic_schema)
00604 schema_ctxt = xmlSchemaNewParserCtxt("/usr/share/test-definition/"
00605 "testdefinition-tm_terms.xsd");
00606 else
00607 schema_ctxt = xmlSchemaNewParserCtxt("/usr/share/test-definition/"
00608 "testdefinition-syntax.xsd");
00609
00610 if (schema_ctxt == NULL) {
00611 LOG_MSG (LOG_ERR, "%s: Failed to allocate schema context\n",
00612 PROGNAME);
00613 goto out;
00614 }
00615
00616 sch = xmlSchemaParse(schema_ctxt);
00617 if (sch == NULL) {
00618 LOG_MSG (LOG_ERR, "%s: Failed to parse schema\n",
00619 PROGNAME);
00620 goto out;
00621 }
00622
00623 valid_ctxt = xmlSchemaNewValidCtxt(sch);
00624 if (valid_ctxt == NULL) {
00625 LOG_MSG (LOG_ERR, "%s: Failed to create schema validation "
00626 "context\n", PROGNAME);
00627 goto out;
00628
00629 }
00630
00631 ret = xmlSchemaValidateDoc(valid_ctxt, doc);
00632 if (ret)
00633 ret = TESTRUNNER_LITE_XML_VALIDATION_FAIL;
00634 out:
00635
00636
00637
00638 if (doc) xmlFreeDoc(doc);
00639 if (ctxt) xmlFreeParserCtxt(ctxt);
00640 if (sch) xmlSchemaFree(sch);
00641 if (valid_ctxt) xmlSchemaFreeValidCtxt(valid_ctxt);
00642 if (schema_ctxt) xmlSchemaFreeParserCtxt(schema_ctxt);
00643
00644 return ret;
00645 }
00646
00651 int td_reader_init (testrunner_lite_options *opts)
00652 {
00653
00654 reader = xmlNewTextReaderFilename(opts->input_filename);
00655 if (!reader) {
00656 LOG_MSG (LOG_ERR, "%s: failed to create xml reader for %s\n",
00657 PROGNAME, opts->input_filename);
00658
00659 }
00660
00661 if (opts->disable_schema)
00662 return 0;
00663
00664 if (opts->semantic_schema)
00665 schema_context = xmlSchemaNewParserCtxt
00666 ("/usr/share/test-definition/"
00667 "testdefinition-tm_terms.xsd");
00668 else
00669 schema_context = xmlSchemaNewParserCtxt
00670 ("/usr/share/test-definition/"
00671 "testdefinition-syntax.xsd");
00672 if (schema_context == NULL) {
00673 LOG_MSG (LOG_ERR, "%s: Failed to allocate schema context\n",
00674 PROGNAME);
00675 goto err_out;
00676 }
00677
00678 schema = xmlSchemaParse(schema_context);
00679 if (schema == NULL) {
00680 LOG_MSG (LOG_ERR, "%s: Failed to parse schema\n",
00681 PROGNAME);
00682 goto err_out;
00683 }
00684
00685 if (xmlTextReaderSetSchema (reader, schema)) {
00686 LOG_MSG (LOG_ERR, "%s: Failed to set schema for xml reader\n",
00687 PROGNAME);
00688 goto err_out;
00689 }
00690
00691
00692 return 0;
00693 err_out:
00694 LOG_MSG (LOG_ERR, "%s:%s: Exiting with error\n",
00695 PROGNAME, __FUNCTION__);
00696 td_reader_close ();
00697 return 1;
00698
00699 }
00700
00703 void td_reader_close ()
00704 {
00705 if (reader) xmlFreeTextReader (reader);
00706 if (schema) xmlSchemaFree(schema);
00707 if (schema_context) xmlSchemaFreeParserCtxt(schema_context);
00708 }
00709
00713 int td_next_node (void) {
00714 int ret;
00715 const xmlChar *name;
00716 xmlReaderTypes type;
00717
00718 ret = xmlTextReaderRead(reader);
00719
00720 if (!ret)
00721 return !ret;
00722
00723 name = xmlTextReaderConstName(reader);
00724 type = xmlTextReaderNodeType(reader);
00725
00726 if (!name)
00727 return 1;
00728
00729 if (!xmlStrcmp (name, BAD_CAST "suite")) {
00730 if (type == XML_READER_TYPE_ELEMENT)
00731 return td_parse_suite();
00732 else if (type == XML_READER_TYPE_END_ELEMENT) {
00733 if (cbs->test_suite_end) cbs->test_suite_end();
00734 return 0;
00735 }
00736 }
00737
00738 if (!xmlStrcmp (name, BAD_CAST "set") &&
00739 type == XML_READER_TYPE_ELEMENT)
00740 return td_parse_set();
00741
00742
00743
00744 return !ret;
00745 }
00746
00750 int td_register_callbacks(td_parser_callbacks *pcbs)
00751 {
00752 cbs = pcbs;
00753
00754 return 0;
00755 }
00756
00757
00758
00759
00760
00761
00762