From 3c7b677bc4f03f1944ac7065f2d759e7a478775f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zden=C4=9Bk=20=C5=A0ustr?= Date: Thu, 9 Aug 2012 14:46:18 +0000 Subject: [PATCH] New unit test and corrections of issues it has already discovered --- org.glite.lb.server/Makefile | 8 +- org.glite.lb.server/src/lb_proto.c | 25 +++- org.glite.lb.server/src/lb_proto.h | 2 + org.glite.lb.server/test/test_query_parse.c | 214 ++++++++++++++++++++++++++++ 4 files changed, 244 insertions(+), 5 deletions(-) create mode 100644 org.glite.lb.server/test/test_query_parse.c diff --git a/org.glite.lb.server/Makefile b/org.glite.lb.server/Makefile index 3e33d30..e01b1f6 100644 --- a/org.glite.lb.server/Makefile +++ b/org.glite.lb.server/Makefile @@ -324,7 +324,7 @@ ${SCRIPTS}: ${SCRIPTS_SRC} fi; \ sed -e 's:@glite_prefix@:${sysroot}${prefix}:' -e 's:@glite_etc@:${sysconfdir}:' -e "s:@glite_var@:$$glite_var:" ${top_srcdir}/config/$@ > $@ -check: compile test.xml test.query +check: compile test.xml test.query test.query_parse -echo check.query not complete yet test_coverage: @@ -376,6 +376,12 @@ test_soap_conv: test_soap_conv.cpp ${WS_CLIENT_OBJS} ${CXX} -c ${CFLAGS} ${CPPUNIT_CFLAGS} $< ${LINKXX} -o $@ test_soap_conv.o ${WS_CLIENT_OBJS} ${WS_CLIENT_LIBS} ${CPPUNIT_LIBS} +test.query_parse: test_query_parse + ./test_query_parse + +test_query_parse: test_query_parse.o + ${LINKXX} -o $@ ${COMMON_LIBS} ${LB_UTILS_DB_LIB} ${LB_MACHINE_LIB} lb_proto.o db_supp.o lb_authz.o lb_html.o authz_policy.o query.o lb_xml_parse_V21.o lb_xml_parse.o server_stats.o lb_rss.o lb_text.o srv_purge.o notification.o userjobs.o jobstat.o dump.o crypto.o load.o server_state.o get_events.o write2rgma.o stats.o db_store.o notif_match.o il_notification.o index.o store.o db_calls.o il_lbproxy.o cond_dump.o jobstat_supp.o openserver.o seqcode.o pretty_print_wrapper.o ${EXT_LIBS} ${CPPUNIT_LIBS} $+ + examples: ${EXAMPLES} ${STATIC_LIB_BK}: ${LIB_OBJS_BK} diff --git a/org.glite.lb.server/src/lb_proto.c b/org.glite.lb.server/src/lb_proto.c index 59a73f3..8779cb3 100644 --- a/org.glite.lb.server/src/lb_proto.c +++ b/org.glite.lb.server/src/lb_proto.c @@ -484,7 +484,7 @@ static char *glite_location() { return location; } -int parse_query_conditions(edg_wll_Context ctx, const char *query, edg_wll_QueryRec ***conditions, int *flags) { +int edg_wll_ParseQueryConditions(edg_wll_Context ctx, const char *query, edg_wll_QueryRec ***conditions) { edg_wll_QueryRec **conds = NULL; char *q = glite_lbu_UnescapeURL(query); char *vartok, *vartok2, *cond, *attribute, *op, *operator, *value, *orvals, *errmsg = NULL; @@ -498,7 +498,13 @@ int parse_query_conditions(edg_wll_Context ctx, const char *query, edg_wll_Query conds[i] = NULL; conds[i+1] = NULL; + len = strcspn(cond, "=<>"); + if (len == strlen(cond)) { + asprintf(&errmsg, "Missing operator in condition \"%s\"", cond); + err = edg_wll_SetError(ctx, EINVAL, errmsg); + goto err; + } attribute=(char*)calloc((len+1),sizeof(char)); strncpy(attribute, cond, len); orvals=cond+len; @@ -511,16 +517,28 @@ int parse_query_conditions(edg_wll_Context ctx, const char *query, edg_wll_Query } // No else here. Don't worry, attribute will be assigned to the query structure later j=0; - for( op = strtok_r(orvals, "|", &vartok2); op ; op = strtok_r(NULL, "&", &vartok2) ) { + for( op = strtok_r(orvals, "|", &vartok2); op ; op = strtok_r(NULL, "|", &vartok2) ) { + if (strlen(op) == 0) continue; conds[i]=(edg_wll_QueryRec*)realloc(conds[i], sizeof(edg_wll_QueryRec) * (j+2)); + conds[i][j].value.c = NULL; conds[i][j+1].attr = EDG_WLL_QUERY_ATTR_UNDEF; conds[i][j].attr = (edg_wll_QueryAttr)attr; len = strspn(op, "=<>"); + if (len == 0) { + asprintf(&errmsg, "Missing operator before \"%s\"", op); + err = edg_wll_SetError(ctx, EINVAL, errmsg); + goto err; + } operator = (char*)calloc((len+1),sizeof(char)); strncpy(operator, op, len); value=op+len; + if (strlen(value) == 0) { + asprintf(&errmsg, "No value given for attribute \"%s\"", attribute); + err = edg_wll_SetError(ctx, EINVAL, errmsg); + goto err; + } if (!strcmp(operator, "<")) conds[i][j].op = EDG_WLL_QUERY_OP_LESS; else if (!strcmp(operator, ">")) conds[i][j].op = EDG_WLL_QUERY_OP_GREATER; @@ -616,7 +634,6 @@ int parse_query_conditions(edg_wll_Context ctx, const char *query, edg_wll_Query err: if (err) { - *conds=NULL; if (conds) { for (j = 0; conds[j]; j++) { for (i = 0 ; (conds[j][i].attr != EDG_WLL_QUERY_ATTR_UNDEF); i++ ) @@ -895,7 +912,7 @@ edg_wll_ErrorCode edg_wll_Proto(edg_wll_Context ctx, queryconds = (char*)calloc((len+1),sizeof(char)); queryconds = strncpy(queryconds, querystr+strlen("?query="), len); - switch(parse_query_conditions(ctx, queryconds, &job_conditions, 0)) { + switch(edg_wll_ParseQueryConditions(ctx, queryconds, &job_conditions)) { case 0: break; case EINVAL: diff --git a/org.glite.lb.server/src/lb_proto.h b/org.glite.lb.server/src/lb_proto.h index b56410d..8e8fe4d 100644 --- a/org.glite.lb.server/src/lb_proto.h +++ b/org.glite.lb.server/src/lb_proto.h @@ -71,6 +71,8 @@ typedef enum _http_extra_option{ extern char *edg_wll_HTTPErrorMessage(int); +int edg_wll_ParseQueryConditions(edg_wll_Context ctx, const char *query, edg_wll_QueryRec ***conditions); + extern int edg_wll_UserJobsServer(edg_wll_Context ctx, int flags, edg_wlc_JobId **jobs, edg_wll_JobStat **states); extern int edg_wll_QuerySequenceCodeServer(edg_wll_Context ctx, edg_wlc_JobId jobid, const char *source, char **seqcode); diff --git a/org.glite.lb.server/test/test_query_parse.c b/org.glite.lb.server/test/test_query_parse.c new file mode 100644 index 0000000..74b985a --- /dev/null +++ b/org.glite.lb.server/test/test_query_parse.c @@ -0,0 +1,214 @@ +#ident "$Header:" +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include "glite/lb/context.h" +#include "glite/lb/consumer.h" +#include "lb_proto.h" +#include "authz_policy.h" + +/* Funny compatibility issue */ +int proxy_purge; +struct _edg_wll_authz_policy authz_policy; +char *policy_file = NULL; +int debug; + +int main() { + int round, retval, i, j; + char *query; + edg_wll_QueryRec **conds; + edg_wll_Context ctx; + + if (edg_wll_InitContext(&ctx) != 0) { + fprintf(stderr, "Couldn't create L&B context.\n"); + return 1; + } + + + for (round = 0; 1 ;round++) { + switch(round) { + case 0: + // Simple query + asprintf(&query,"status=running"); + break; + case 1: + // ANDed query + asprintf(&query,"status=running&owner=testowner"); + break; + case 2: + // ANDed and ORed query + asprintf(&query,"status=running|=submitted&jobtype<>simple"); + break; + case 3: + // Bad attribute name + asprintf(&query,"sXatus=running"); + break; + case 4: + // Bad attribute value + asprintf(&query,"status=ruXning"); + break; + case 5: + // Query Empty + query = strdup(""); + break; + case 6: + // No Operator + query = strdup("status=running&owner"); + break; + case 7: + // No Operator in ORed condition + query = strdup("status=running&owner=I|You"); + break; + case 8: + // No rval + query = strdup("status=running&owner="); + break; + case 9: + // Multiple operators + query = strdup("status=running=submitted"); + break; + case 10: + // Empty AND section + query = strdup("status=running&"); + break; + case 11: + // Empty AND section inbetween + asprintf(&query,"status=running&&owner=testowner"); + break; + case 12: + // Empty OR section inbetween + asprintf(&query,"status=running|||=submitted&jobtype<>simple"); + break; + case 13: + // Confused operator + asprintf(&query,"status==running"); + break; + + default: + goto done; + } + + retval = edg_wll_ParseQueryConditions(ctx, query, &conds); + + //fprintf(stderr, "%s\n", ctx->errDesc); + + switch(round) { + case 0: + case 10: + assert(conds[0] != NULL); + assert(conds[0][0].attr == EDG_WLL_QUERY_ATTR_STATUS); + assert(conds[0][0].op == EDG_WLL_QUERY_OP_EQUAL); + assert(conds[0][0].value.i == EDG_WLL_JOB_RUNNING); + assert(conds[0][1].attr == EDG_WLL_QUERY_ATTR_UNDEF); + assert(conds[1] == NULL); + assert(retval == 0); + assert(ctx->errDesc == NULL); + break; + case 1: + case 11: + assert(retval == 0); + assert(conds[0] != NULL); + assert(conds[0][0].attr == EDG_WLL_QUERY_ATTR_STATUS); + assert(conds[0][0].op == EDG_WLL_QUERY_OP_EQUAL); + assert(conds[0][0].value.i == EDG_WLL_JOB_RUNNING); + assert(conds[0][1].attr == EDG_WLL_QUERY_ATTR_UNDEF); + assert(conds[1] != NULL); + assert(conds[1][0].attr == EDG_WLL_QUERY_ATTR_OWNER); + assert(conds[1][0].op == EDG_WLL_QUERY_OP_EQUAL); + assert(!strcmp(conds[1][0].value.c, "testowner")); + assert(conds[1][1].attr == EDG_WLL_QUERY_ATTR_UNDEF); + assert(conds[2] == NULL); + assert(retval == 0); + assert(ctx->errDesc == NULL); + break; + case 2: + case 12: + assert(retval == 0); + assert(conds[0] != NULL); + assert(conds[0][0].attr == EDG_WLL_QUERY_ATTR_STATUS); + assert(conds[0][0].op == EDG_WLL_QUERY_OP_EQUAL); + assert(conds[0][0].value.i == EDG_WLL_JOB_RUNNING); + assert(conds[0][1].attr == EDG_WLL_QUERY_ATTR_STATUS); + assert(conds[0][1].op == EDG_WLL_QUERY_OP_EQUAL); + assert(conds[0][1].value.i == EDG_WLL_JOB_SUBMITTED); + assert(conds[0][2].attr == EDG_WLL_QUERY_ATTR_UNDEF); + assert(conds[1] != NULL); + assert(conds[1][0].attr == EDG_WLL_QUERY_ATTR_JOB_TYPE); + assert(conds[1][0].op == EDG_WLL_QUERY_OP_UNEQUAL); + assert(conds[1][0].value.i == EDG_WLL_STAT_SIMPLE); + assert(conds[1][1].attr == EDG_WLL_QUERY_ATTR_UNDEF); + assert(conds[2] == NULL); + assert(retval == 0); + assert(ctx->errDesc == NULL); + break; + case 3: + assert(retval == EINVAL); + assert(strstr(ctx->errDesc, "Unknown argument")); + break; + case 4: + assert(retval == EINVAL); + assert(strstr(ctx->errDesc, "Unknown job state")); + break; + case 5: + assert(retval == 0); + assert(conds == NULL); + break; + case 6: + assert(retval == EINVAL); + assert(strstr(ctx->errDesc, "Missing operator in condition")); + break; + case 7: + assert(retval == EINVAL); + assert(strstr(ctx->errDesc, "Missing operator before")); + break; + case 8: + assert(retval == EINVAL); + assert(strstr(ctx->errDesc, "No value given for attribute")); + break; + case 9: + assert(retval == EINVAL); + assert(strstr(ctx->errDesc, "Unknown job state")); + break; + case 13: + assert(retval == EINVAL); + assert(strstr(ctx->errDesc, "Unknown operator")); + break; + } + + edg_wll_ResetError(ctx); + free(query); query=NULL; + if (conds) { + for (j = 0; conds[j]; j++) { + for (i = 0 ; (conds[j][i].attr != EDG_WLL_QUERY_ATTR_UNDEF); i++ ) + edg_wll_QueryRecFree(&conds[j][i]); + free(conds[j]); + } + free(conds); conds = NULL; + } + } + + + +done: + edg_wll_FreeContext(ctx); + return 0; +} -- 1.8.2.3