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 <stdlib.h>
00027 #include <errno.h>
00028 #include <string.h>
00029 #include <libxml/list.h>
00030
00031 #include "testrunnerlite.h"
00032 #include "testfilters.h"
00033 #include "utils.h"
00034 #include "log.h"
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
00061
00062 LOCAL xmlListPtr suite_filter_list = NULL;
00063 LOCAL xmlListPtr set_filter_list = NULL;
00064 LOCAL xmlListPtr case_filter_list = NULL;
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 LOCAL void filter_delete (xmlLinkPtr lk);
00077
00078 LOCAL void filter_value_delete (xmlLinkPtr lk);
00079
00080 LOCAL int filter_list_compare (const void * data0, const void * data1);
00081
00082 LOCAL int validate_and_add_filter (char *key, char *values);
00083
00084 LOCAL int filter_exec (const void *data, const void *user) ;
00085
00086 LOCAL int filter_value_print (const void *data, const void *user) ;
00087
00088 LOCAL int manual_filter (test_filter *filter, const void *data);
00089
00090 LOCAL int test_case_filter (test_filter *filter, const void *data);
00091
00092 LOCAL int test_set_filter (test_filter *filter, const void *data);
00093
00094 LOCAL int feature_filter (test_filter *filter, const void *data);
00095
00096 LOCAL int type_filter (test_filter *filter, const void *data);
00097
00098 LOCAL int requirement_filter (test_filter *filter, const void *data);
00099
00100 LOCAL xmlListPtr string2valuelist (char *str);
00101
00102
00103
00104
00105
00106
00107
00108
00112 LOCAL void filter_delete (xmlLinkPtr lk)
00113 {
00114 test_filter *filter = xmlLinkGetData (lk);
00115 if (filter->key)
00116 free (filter->key);
00117 xmlListDelete (filter->value_list);
00118
00119 free (filter);
00120 }
00124 LOCAL void filter_value_delete (xmlLinkPtr lk)
00125 {
00126 xmlChar *val = xmlLinkGetData (lk);
00127 free (val);
00128 }
00129
00135 LOCAL int filter_list_compare (const void * data0,
00136 const void * data1)
00137 {
00138
00139 return 0;
00140 }
00141
00147 LOCAL int filter_value_list_compare (const void * data0,
00148 const void * data1)
00149 {
00150
00151 return xmlStrcmp (BAD_CAST data0, BAD_CAST data1);
00152 }
00153
00158 LOCAL int filter_add (test_filter *filter)
00159 {
00160
00161 if (!strcasecmp ((char *)filter->key, "environment")) {
00162 ;
00163 }
00164 else if (!strcasecmp ((char *)filter->key, "manual")) {
00165 filter->filter = manual_filter;
00166 return xmlListAppend (case_filter_list, filter);
00167 }
00168 else if (!strcasecmp ((char *)filter->key, "domain")) {
00169 ;
00170 }
00171 else if (!strcasecmp ((char *)filter->key, "feature")) {
00172 filter->filter = feature_filter;
00173 return xmlListAppend (set_filter_list, filter);
00174 }
00175 else if (!strcasecmp ((char *)filter->key, "requirement")) {
00176 filter->filter = requirement_filter;
00177 return xmlListAppend (case_filter_list, filter);
00178 }
00179 else if (!strcasecmp ((char *)filter->key, "type")) {
00180 filter->filter = type_filter;
00181 return xmlListAppend (case_filter_list, filter);
00182 }
00183 else if (!strcasecmp ((char *)filter->key, "insignificant")) {
00184 ;
00185 }
00186 else if (!strcasecmp ((char *)filter->key, "level")) {
00187 ;
00188 }
00189 else if (!strcasecmp ((char *)filter->key, "subfeature")) {
00190 ;
00191 }
00192 else if (!strcasecmp ((char *)filter->key, "testsuite")) {
00193 return xmlListAppend (suite_filter_list, filter);
00194 }
00195 else if (!strcasecmp ((char *)filter->key, "testset")) {
00196 filter->filter = test_set_filter;
00197 return xmlListAppend (set_filter_list, filter);
00198 }
00199 else if (!strcasecmp ((char *)filter->key, "testcase")) {
00200 filter->filter = test_case_filter;
00201 return xmlListAppend (case_filter_list, filter);
00202 } else {
00203 LOG_MSG (LOG_ERR, "Unknow filter type %s",
00204 filter->key);
00205 free (filter->key);
00206 xmlListDelete (filter->value_list);
00207 free (filter);
00208 return 1;
00209 }
00210
00211 return 0;
00212 }
00213
00218 LOCAL xmlListPtr string2valuelist (char *str)
00219 {
00220 char *p;
00221 xmlChar *val, *clean_val;
00222 xmlListPtr list = xmlListCreate (filter_value_delete,
00223 filter_value_list_compare);
00224 if (!list) {
00225 LOG_MSG (LOG_ERR, "OOM");
00226 return NULL;
00227 }
00228
00229 p = strtok (str, ",");
00230 if (!p) {
00231 LOG_MSG (LOG_ERR, "empty value");
00232 return NULL;
00233 }
00234 do {
00235
00236 if (p[0] == '"') {
00237 if (strlen (p) < 3) {
00238 LOG_MSG (LOG_ERR, "empty value");
00239 goto err_out;
00240 }
00241 if (p[strlen(p)-1] != '"') {
00242 LOG_MSG (LOG_ERR, "Mismatched \" %s", p);
00243 goto err_out;
00244 }
00245 val = xmlCharStrndup(&p[1], strlen(p)-2);
00246 } else
00247 val = xmlCharStrdup (p);
00248
00249 clean_val = xmlStrdup (val);
00250 trim_string ((char *)val, (char *)clean_val);
00251 free (val);
00252 xmlListAppend (list, clean_val);
00253 } while ((p = strtok (NULL, ",")));
00254
00255 return list;
00256 err_out:
00257 if (list) xmlListDelete (list);
00258 return NULL;
00259 }
00260
00266 LOCAL int validate_and_add_filter (char *key, char *values)
00267 {
00268 int exclude = 0, retval = 0;
00269 xmlChar *k = NULL;
00270 test_filter *filter = NULL;
00271
00272
00273 if (*key == '-') {
00274 exclude = 1;
00275 k = xmlCharStrdup (key + 1);
00276 } else if (*key == '+')
00277 k = xmlCharStrdup (key + 1);
00278 else
00279 k = xmlCharStrdup (key);
00280
00281 filter = (test_filter *)malloc (sizeof (test_filter));
00282 filter->exclude = exclude;
00283 filter->key = k;
00284 filter->value_list = string2valuelist (values);
00285 if (!filter->value_list) {
00286 retval = 1;
00287 goto out;
00288 }
00289 LOG_MSG (LOG_DEBUG, "FILTER: key=%s exclude=%d",
00290 filter->key, filter->exclude);
00291 LOG_MSG (LOG_DEBUG, "values:");
00292 xmlListWalk (filter->value_list, filter_value_print, NULL);
00293
00294 retval = filter_add (filter);
00295 out:
00296 return retval;
00297 }
00298
00304 LOCAL int filter_exec (const void *data, const void *user)
00305 {
00306 test_filter *filter = (test_filter *)data;
00307
00308 return !(filter->filter(filter, user));
00309 }
00310
00316 LOCAL int filter_value_print (const void *data, const void *user)
00317 {
00318 xmlChar *val = BAD_CAST data;
00319
00320 LOG_MSG (LOG_DEBUG, "%s", val);
00321
00322 return 1;
00323 }
00324
00330 LOCAL int manual_filter (test_filter *filter, const void *data)
00331 {
00332
00333
00334 return 0;
00335 }
00336
00342 LOCAL int test_case_filter (test_filter *filter, const void *data)
00343 {
00344 int found = 0;
00345 td_case *c = (td_case *)data;
00346
00347 if (xmlListSearch (filter->value_list, c->gen.name))
00348 found = 1;
00349
00350 c->filtered = filter->exclude ? found : !found;
00351
00352 return c->filtered;
00353 }
00354
00360 LOCAL int test_set_filter (test_filter *filter, const void *data)
00361 {
00362 int found = 0;
00363 td_set *s = (td_set *)data;
00364
00365 if (xmlListSearch (filter->value_list, s->gen.name))
00366 found = 1;
00367
00368 s->filtered = filter->exclude ? found : !found;
00369
00370 return s->filtered;
00371 }
00372
00378 LOCAL int feature_filter (test_filter *filter, const void *data)
00379 {
00380 int found = 0;
00381 td_set *s = (td_set *)data;
00382 xmlListPtr fea_list;
00383 xmlLinkPtr lk;
00384 xmlChar *fea, *feas;
00385
00386 if (!s->gen.feature)
00387 goto skip;
00388 feas = xmlStrdup (s->gen.feature);
00389 fea_list = string2valuelist ((char *)feas);
00390 while (xmlListSize (fea_list) > 0) {
00391 lk = xmlListFront (fea_list);
00392 fea = xmlLinkGetData (lk);
00393 if (xmlListSearch (filter->value_list, fea))
00394 found = 1;
00395 xmlListPopFront (fea_list);
00396 }
00397 free (feas);
00398 xmlListDelete (fea_list);
00399 skip:
00400 s->filtered = filter->exclude ? found : !found;
00401
00402 return s->filtered;
00403 }
00404
00410 LOCAL int type_filter (test_filter *filter, const void *data)
00411 {
00412 int found = 0;
00413 td_case *c = (td_case *)data;
00414
00415 if (c->gen.type && xmlListSearch (filter->value_list, c->gen.type))
00416 found = 1;
00417
00418 c->filtered = filter->exclude ? found : !found;
00419
00420 return c->filtered;
00421 }
00422
00428 LOCAL int requirement_filter (test_filter *filter, const void *data)
00429 {
00430 int found = 0;
00431 td_case *c = (td_case *)data;
00432 xmlListPtr req_list;
00433 xmlLinkPtr lk;
00434 xmlChar *req, *reqs;
00435
00436 if (!c->gen.requirement)
00437 goto skip;
00438 reqs = xmlStrdup (c->gen.requirement);
00439 req_list = string2valuelist ((char *)reqs);
00440 while (xmlListSize (req_list) > 0) {
00441 lk = xmlListFront (req_list);
00442 req = xmlLinkGetData (lk);
00443 if (xmlListSearch (filter->value_list, req))
00444 found = 1;
00445 xmlListPopFront (req_list);
00446 }
00447 free (reqs);
00448 xmlListDelete (req_list);
00449 skip:
00450 c->filtered = filter->exclude ? found : !found;
00451
00452 return c->filtered;
00453 }
00454
00455
00456
00457
00459 void init_filters()
00460 {
00461 suite_filter_list = xmlListCreate (filter_delete, filter_list_compare);
00462 set_filter_list = xmlListCreate (filter_delete, filter_list_compare);
00463 case_filter_list = xmlListCreate (filter_delete, filter_list_compare);
00464 }
00465
00471 int parse_filter_string (char *filters)
00472 {
00473 int in_quotes = 0, done = 0, retval = 0;
00474 char *p, *f, *key = NULL, *value = NULL, c;
00475
00476
00477 LOG_MSG (LOG_DEBUG, "string to parse %s", filters);
00478 f = (char *)malloc (strlen(filters) + 1);
00479 strcpy (f, filters);
00480 p = f;
00481 while (p && !done) {
00482
00483 key = p;
00484 p = strchr (p, '=');
00485 if (p) {
00486 *p = '\0';
00487 p++;
00488 } else {
00489 LOG_MSG (LOG_ERR, "failed to parse filter string - "
00490 "missing '='\n");
00491 goto err_out;
00492 }
00493
00494
00495 value = p;
00496 do {
00497 c = *p;
00498 switch (c) {
00499 case '"':
00500 in_quotes = !in_quotes;
00501 p ++;
00502 break;
00503 case ' ':
00504 if (!in_quotes)
00505 c = *p = '\0';
00506 p ++;
00507 break;
00508 case '\0':
00509 done = 1;
00510 break;
00511 default:
00512 p++;
00513 }
00514 } while (c != '\0');
00515 if (in_quotes) {
00516 LOG_MSG (LOG_ERR,
00517 "failed to parse filter string - "
00518 "mismatched \"");
00519 goto err_out;
00520 }
00521 retval = validate_and_add_filter (key, value);
00522 if (retval) {
00523 goto err_out;
00524 }
00525 }
00526 free (f);
00527 return retval;
00528 err_out:
00529 if (f) free (f);
00530 return 1;
00531 }
00532
00537 int filter_suite (td_suite *s)
00538 {
00539 xmlListWalk (suite_filter_list, filter_exec, s);
00540 return s->filtered;
00541 }
00542
00547 int filter_set (td_set *s)
00548 {
00549 xmlListWalk (set_filter_list, filter_exec, s);
00550 return s->filtered;
00551 }
00552
00557 int filter_case (td_case *c)
00558 {
00559 xmlListWalk (case_filter_list, filter_exec, c);
00560 return c->filtered;
00561 }
00562
00565 void cleanup_filters ()
00566 {
00567 if (suite_filter_list) xmlListDelete (suite_filter_list);
00568 if (set_filter_list) xmlListDelete (set_filter_list);
00569 if (case_filter_list) xmlListDelete (case_filter_list);
00570 }
00571
00572
00573
00574
00575
00576
00577