diff --git a/server/modules/filter/test/CMakeLists.txt b/server/modules/filter/test/CMakeLists.txt index 1813a5a26..9c87ee926 100644 --- a/server/modules/filter/test/CMakeLists.txt +++ b/server/modules/filter/test/CMakeLists.txt @@ -10,4 +10,7 @@ add_executable(harness_ui harness_ui.c harness_common.c) add_executable(harness harness_util.c harness_common.c ${CORE}) target_link_libraries(harness_ui fullcore log_manager utils) target_link_libraries(harness fullcore) -add_test(TestHintfilter /bin/sh -c "MAXSCALE_HOME=\"${CMAKE_BINARY_DIR}\" ${CMAKE_CURRENT_BINARY_DIR}/harness -i ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.input -o ${CMAKE_CURRENT_BINARY_DIR}/hint_testing.output -c ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.cnf -t 1 -s 1 && diff ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.expected ${CMAKE_CURRENT_BINARY_DIR}/hint_testing.output;exit $?") \ No newline at end of file +execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${ERRMSG} ${CMAKE_CURRENT_BINARY_DIR}) +add_test(TestHintfilter /bin/sh -c "MAXSCALE_HOME=\"${CMAKE_BINARY_DIR}\" ${CMAKE_CURRENT_BINARY_DIR}/harness -i ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.input -o ${CMAKE_CURRENT_BINARY_DIR}/hint_testing.output -c ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.cnf -t 1 -s 1 -e ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.expected") + +add_test(TestRegexfilter /bin/sh -c "MAXSCALE_HOME=\"${CMAKE_BINARY_DIR}\" ${CMAKE_CURRENT_BINARY_DIR}/harness -i ${CMAKE_CURRENT_SOURCE_DIR}/regextest.input -o ${CMAKE_CURRENT_BINARY_DIR}/regextest.output -c ${CMAKE_CURRENT_SOURCE_DIR}/regextest.cnf -t 1 -s 1 -e ${CMAKE_CURRENT_SOURCE_DIR}/regextest.expected") \ No newline at end of file diff --git a/server/modules/filter/test/harness.h b/server/modules/filter/test/harness.h index c30c266c2..85713d07a 100644 --- a/server/modules/filter/test/harness.h +++ b/server/modules/filter/test/harness.h @@ -69,6 +69,9 @@ #include #include #include +#include +#include + /** * A single name-value pair and a link to the next item in the * configuration. @@ -117,6 +120,7 @@ typedef struct int running; int verbose; /**Whether to print to stdout*/ int infile; /**A file where the queries are loaded from*/ + int expected; int error; char* mod_dir; /**Module directory absolute path*/ char* infile_name; @@ -125,6 +129,7 @@ typedef struct FILTERCHAIN* head; /**The head of the filter chain*/ FILTERCHAIN* tail; /**The tail of the filter chain*/ GWBUF** buffer; /**Buffers that are fed to the filter chain*/ + SESSION* session; int buffer_count; int session_count; DOWNSTREAM dummyrouter; /**Dummy downstream router for data extraction*/ @@ -172,7 +177,7 @@ typedef packet_t PACKET; /** * Initialize the static instance. */ -int harness_init(int argc,char** argv); +int harness_init(int argc,char** argv,HARNESS_INSTANCE** inst); /** * Frees all the query buffers @@ -359,4 +364,14 @@ GWBUF* gen_packet(PACKET pkt); */ int process_opts(int argc, char** argv); +/** + * Compares the contents of two files. + * This function resets the offsets of the file descriptors and leaves them in an + * undefined state. + * @param a The first file + * @param b The second file + * @return 0 if the files do not differ and 1 if they do or an error occurred. + */ +int compare_files(int a, int b); + #endif diff --git a/server/modules/filter/test/harness_common.c b/server/modules/filter/test/harness_common.c index c12989259..03338a0d5 100644 --- a/server/modules/filter/test/harness_common.c +++ b/server/modules/filter/test/harness_common.c @@ -1,7 +1,22 @@ #include -int harness_init(int argc, char** argv){ + +int dcbfun(struct dcb* dcb, GWBUF * buffer) +{ + printf("Data was written to client DCB.\n"); + return 1; +} + +int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){ + + int i = 0; + MYSQL_session* mysqlsess; + DCB* dcb; + char cwd[1024]; + char tmp[2048]; + char** optstr; + if(!(argc == 2 && strcmp(argv[1],"-h") == 0)){ skygw_logmanager_init(0,NULL); } @@ -14,13 +29,37 @@ int harness_init(int argc, char** argv){ return 1; } + *inst = &instance; instance.running = 1; instance.infile = -1; instance.outfile = -1; + instance.expected = -1; instance.buff_ind = -1; instance.last_ind = -1; instance.sess_ind = -1; + instance.session = calloc(1,sizeof(SESSION)); + dcb = calloc(1,sizeof(DCB)); + mysqlsess = calloc(1,sizeof(MYSQL_session)); + sprintf(mysqlsess->user,"dummyuser"); + sprintf(mysqlsess->db,"dummydb"); + dcb->func.write = dcbfun; + dcb->remote = strdup("0.0.0.0"); + dcb->user = strdup("user"); + instance.session->client = (void*)dcb; + instance.session->data = (void*)mysqlsess; + + getcwd(cwd,sizeof(cwd)); + sprintf(tmp,"%s",cwd); + + optstr = (char**)malloc(sizeof(char*)*4); + optstr[0] = strdup("log_manager"); + optstr[1] = strdup("-j"); + optstr[2] = strdup(tmp); + optstr[3] = NULL; + skygw_logmanager_init( 3, optstr); + free(optstr); + process_opts(argc,argv); if(!(instance.thrpool = malloc(instance.thrcount * sizeof(pthread_t)))){ @@ -84,15 +123,17 @@ void free_buffers() } int open_file(char* str, unsigned int write) { - int mode; + int mode,fd; if(write){ mode = O_RDWR|O_CREAT; }else{ mode = O_RDONLY; } - - return open(str,mode,S_IRWXU|S_IRGRP|S_IXGRP|S_IXOTH); + if((fd = open(str,mode,S_IRWXU|S_IRGRP|S_IXGRP|S_IXOTH)) < 0){ + printf("Error %d: %s\n",errno,strerror(errno)); + } + return fd; } @@ -608,6 +649,8 @@ int load_filter(FILTERCHAIN* fc, CONFIG* cnf) { FILTER_PARAMETER** fparams = NULL; int i, paramc = -1; + int sess_err = 0; + int x; if(cnf == NULL){ fparams = read_params(¶mc); @@ -672,16 +715,19 @@ int load_filter(FILTERCHAIN* fc, CONFIG* cnf) } } - int sess_err = 0; if(cnf && fc && fc->instance){ fc->filter = (FILTER*)fc->instance->createInstance(NULL,fparams); - + if(fc->filter == NULL){ + printf("Error loading filter:%s: createInstance returned NULL.\n",fc->name); + sess_err = 1; + goto error; + } for(i = 0;isession[i] = fc->instance->newSession(fc->filter, fc->session[i])) && + if((fc->session[i] = fc->instance->newSession(fc->filter, instance.session)) && (fc->down[i] = calloc(1,sizeof(DOWNSTREAM))) && (fc->up[i] = calloc(1,sizeof(UPSTREAM)))){ @@ -693,7 +739,7 @@ int load_filter(FILTERCHAIN* fc, CONFIG* cnf) fc->instance->setUpstream(fc->filter, fc->session[i], fc->up[i]); }else{ skygw_log_write(LOGFILE_MESSAGE, - "Warning: The filter %s does not support client relies.\n",fc->name); + "Warning: The filter %s does not support client replies.\n",fc->name); } if(fc->next && fc->next->next){ @@ -746,8 +792,8 @@ int load_filter(FILTERCHAIN* fc, CONFIG* cnf) } } - - int x; + error: + if(fparams){ for(x = 0;xinstance->routeQuery(instance.head->filter, + + if(instance.head->instance->routeQuery(instance.head->filter, + instance.head->session[index], - instance.buffer[instance.buff_ind]); + instance.buffer[instance.buff_ind]) == 0){ + if(instance.outfile > 0){ + const char* msg = "Query returned 0.\n"; + write(instance.outfile,msg,strlen(msg)); + } + } if(instance.tail->instance->clientReply){ instance.tail->instance->clientReply(instance.tail->filter, instance.tail->session[index], @@ -939,7 +991,7 @@ GWBUF* gen_packet(PACKET pkt) int process_opts(int argc, char** argv) { int fd, buffsize = 1024; - int rd,rdsz, rval; + int rd,rdsz, rval = 0; size_t fsize; char *buff = calloc(buffsize,sizeof(char)), *tok = NULL; @@ -992,10 +1044,18 @@ int process_opts(int argc, char** argv) close(fd); return 1; } + char* conf_name = NULL; - while((rd = getopt(argc,argv,"m:c:i:o:s:t:d:qh")) > 0){ + rval = 0; + + while((rd = getopt(argc,argv,"e:m:c:i:o:s:t:d:qh")) > 0){ switch(rd){ + case 'e': + instance.expected = open_file(optarg,0); + printf("Expected output is read from: %s\n",optarg); + break; + case 'o': instance.outfile = open_file(optarg,1); printf("Output is written to: %s\n",optarg); @@ -1060,6 +1120,7 @@ int process_opts(int argc, char** argv) } } printf("\n"); + if(conf_name && load_config(conf_name)){ load_query(); }else{ @@ -1068,5 +1129,30 @@ int process_opts(int argc, char** argv) free(conf_name); close(fd); + return rval; +} + +int compare_files(int a,int b) +{ + char in[4098]; + char exp[4098]; + int line = 1; + + if(a < 1 || b < 1){ + return 1; + } + + if(lseek(a,0,SEEK_SET) < 0 || + lseek(b,0,SEEK_SET) < 0){ + return 1; + } + + while(fdgets(a,in,4098) && fdgets(b,exp,4098)){ + if(strcmp(in,exp)){ + printf("The files differ at line %d:\n%s\n-------------------------------------\n%s\n",line,in,exp); + return 1; + } + line++; + } return 0; } diff --git a/server/modules/filter/test/harness_ui.c b/server/modules/filter/test/harness_ui.c index 9b38f648c..8921a88bc 100755 --- a/server/modules/filter/test/harness_ui.c +++ b/server/modules/filter/test/harness_ui.c @@ -6,9 +6,9 @@ int main(int argc, char** argv){ char* tk; FILTERCHAIN* tmp_chn; FILTERCHAIN* del_chn; - + HARNESS_INSTANCE* hinstance; - if(harness_init(argc,argv)){ + if(harness_init(argc,argv,&hinstance)){ printf("Error: Initialization failed.\n"); skygw_log_write(LOGFILE_ERROR,"Error: Initialization failed.\n"); skygw_logmanager_done(); diff --git a/server/modules/filter/test/harness_util.c b/server/modules/filter/test/harness_util.c index fb6905445..04b7e1b9b 100644 --- a/server/modules/filter/test/harness_util.c +++ b/server/modules/filter/test/harness_util.c @@ -1,7 +1,38 @@ +#include +#include #include + int main(int argc,char** argv) { - if(harness_init(argc,argv) || instance.error){ + + static char* server_options[] = { + "MariaDB Corporation MaxScale", + "--datadir=./", + "--language=./", + "--skip-innodb", + "--default-storage-engine=myisam", + NULL + }; + + const int num_elements = (sizeof(server_options) / sizeof(char *)) - 1; + + static char* server_groups[] = { + "embedded", + "server", + "server", + NULL + }; + + + HARNESS_INSTANCE* inst; + + if(mysql_library_init(num_elements, server_options, server_groups)){ + printf("Embedded server init failed.\n"); + return 1; + } + + + if(harness_init(argc,argv,&inst) || inst->error){ printf("Error: Initialization failed.\n"); skygw_log_write(LOGFILE_ERROR,"Error: Initialization failed.\n"); skygw_logmanager_done(); @@ -10,5 +41,8 @@ int main(int argc,char** argv) } route_buffers(); + if(inst->expected){ + return compare_files(inst->outfile,inst->expected); + } return 0; } diff --git a/server/modules/filter/test/hint_testing.cnf b/server/modules/filter/test/hint_testing.cnf index 347d9c6a6..5d4319bb8 100755 --- a/server/modules/filter/test/hint_testing.cnf +++ b/server/modules/filter/test/hint_testing.cnf @@ -1,165 +1,3 @@ -# -# Example MaxScale.cnf configuration file -# -# -# -# Number of server threads -# Valid options are: -# threads= - -[maxscale] -threads=1 - -# Define a monitor that can be used to determine the state and role of -# the servers. -# -# Valid options are: -# -# module= -# servers=,,... -# user = -# passwd= -# monitor_interval= - -[MySQL Monitor] -type=monitor -module=mysqlmon -servers=server1,server2,server3,server4 -user=maxuser -passwd=maxpwd - -# A series of service definition -# -# Valid options are: -# -# router= -# servers=,,... -# user= -# passwd= -# enable_root_user=<0 or 1, default is 0> -# version_string= -# -# Valid router modules currently are: -# readwritesplit, readconnroute and debugcli - - -[RW Split Router] -type=service -router=readwritesplit -servers=server1,server2,server3,server4 -max_slave_connections=90% -user=maxuser -passwd=maxpwd -#filters=MQ - -[RW Split Hint Router] -type=service -router=readwritesplit -servers=server1,server2,server3,server4 -max_slave_connections=90% -user=maxuser -passwd=maxpwd -filters=Hint - - -[Read Connection Router] -type=service -router=readconnroute -router_options=master -servers=server1 -user=maxuser -passwd=maxpwd - - -[HTTPD Router] -type=service -router=testroute -servers=server1,server2,server3 - -[Debug Interface] -type=service -router=debugcli - - [Hint] type=filter module=hintfilter - -#[MQ] -#type=filter -#module=mqfilter -#exchange=x1 -#key=k1 -#queue=q1 -#port=5673 - -# Listener definitions for the services -# -# Valid options are: -# -# service= -# protocol= -# port= -# address=
-# socket= - -[RW Split Listener] -type=listener -service=RW Split Router -protocol=MySQLClient -port=4006 - -[RW Split Hint Listener] -type=listener -service=RW Split Hint Router -protocol=MySQLClient -port=4009 - -[Read Connection Listener] -type=listener -service=Read Connection Router -protocol=MySQLClient -port=4008 -#socket=/tmp/readconn.sock - -[Debug Listener] -type=listener -service=Debug Interface -protocol=telnetd -port=4442 -#address=127.0.0.1 - -[HTTPD Listener] -type=listener -service=HTTPD Router -protocol=HTTPD -port=6444 - -# Definition of the servers - -[server1] -type=server -address=127.0.0.1 -port=3000 -protocol=MySQLBackend - -[server2] -type=server -address=127.0.0.1 -port=3001 -protocol=MySQLBackend - -[server3] -type=server -address=127.0.0.1 -port=3002 -protocol=MySQLBackend - -[server4] -type=server -address=127.0.0.1 -port=3003 -protocol=MySQLBackend diff --git a/server/modules/filter/test/regextest.cnf b/server/modules/filter/test/regextest.cnf new file mode 100644 index 000000000..1033a8696 --- /dev/null +++ b/server/modules/filter/test/regextest.cnf @@ -0,0 +1,5 @@ +[Regex] +type=filter +module=regexfilter +match=wrong +replace=right diff --git a/server/modules/filter/test/regextest.expected b/server/modules/filter/test/regextest.expected new file mode 100755 index 000000000..609b3393e --- /dev/null +++ b/server/modules/filter/test/regextest.expected @@ -0,0 +1,3 @@ +select * from mysql.right; +select right from test.table; +select * from test.table where name='right'; diff --git a/server/modules/filter/test/regextest.input b/server/modules/filter/test/regextest.input new file mode 100644 index 000000000..ab31b0ad3 --- /dev/null +++ b/server/modules/filter/test/regextest.input @@ -0,0 +1,3 @@ +select * from mysql.wrong; +select wrong from test.table; +select * from test.table where name='wrong'; \ No newline at end of file