New unit test and corrections of issues it has already discovered
authorZdeněk Šustr <sustr4@cesnet.cz>
Thu, 9 Aug 2012 14:46:18 +0000 (14:46 +0000)
committerZdeněk Šustr <sustr4@cesnet.cz>
Thu, 9 Aug 2012 14:46:18 +0000 (14:46 +0000)
org.glite.lb.server/Makefile
org.glite.lb.server/src/lb_proto.c
org.glite.lb.server/src/lb_proto.h
org.glite.lb.server/test/test_query_parse.c [new file with mode: 0644]

index 3e33d30..e01b1f6 100644 (file)
@@ -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}
index 59a73f3..8779cb3 100644 (file)
@@ -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:
index b56410d..8e8fe4d 100644 (file)
@@ -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 (file)
index 0000000..74b985a
--- /dev/null
@@ -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 <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+#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;
+}