diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-11-11 21:11:37 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-11-12 00:10:27 +0200 |
commit | 5d91de768f4a5f75f6b663e7d80c94f47e45de23 (patch) | |
tree | 8d07950953625faa8c9852379c071c7ea454b8c9 | |
parent | 55e620d377854d7416ee63d8e2d91905e78b421b (diff) | |
download | vmod-dbrw-5d91de768f4a5f75f6b663e7d80c94f47e45de23.tar.gz vmod-dbrw-5d91de768f4a5f75f6b663e7d80c94f47e45de23.tar.bz2 |
Add test suite.
* Makefile.am: Add tests subdir
* configure.ac: Initialize testsuite.
(DBRW_TEST_PARAMS,DBRW_TEST_SERVER)
(DBRW_TEST_NAME,DBRW_TEST_USER)
(DBRW_TEST_PASS,DBRW_TEST_DEBUG): New variables.
* src/Makefile.am (noinst_LTLIBRARIES): New library libsql.la
* src/dbrw.h (dbrw_backend_select): New proto.
* src/be.c: New file.
* src/mysql.c (check_errno): Add default clause.
* src/vmod_dbrw.c (expand_backref): Fix memory deallocation error.
(dbrw_sethdr): New function.
(findmatch): Use dbrw_sethdr to set X-VMOD-DBRW-Status
* tests/.gitignore: New file.
* tests/initdb.c: New file.
* tests/Makefile.am: New file.
* tests/atlocal.in: New file.
* tests/exact01.at: New file.
* tests/initdb.at: New file.
* tests/rewrite01.at: New file.
* tests/rewrite02.at: New file.
* tests/rewrite03.at: New file.
* tests/rewrite04.at: New file.
* tests/rewrite05.at: New file.
* tests/rewrite06.at: New file.
* tests/testsuite.at: New file.
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | README | 135 | ||||
-rw-r--r-- | configure.ac | 28 | ||||
-rw-r--r-- | src/Makefile.am | 36 | ||||
-rw-r--r-- | src/be.c | 54 | ||||
-rw-r--r-- | src/dbrw.h | 4 | ||||
-rw-r--r-- | src/mysql.c | 3 | ||||
-rw-r--r-- | src/vmod_dbrw.c | 58 | ||||
-rw-r--r-- | tests/.gitignore | 7 | ||||
-rw-r--r-- | tests/Makefile.am | 82 | ||||
-rw-r--r-- | tests/atlocal.in | 102 | ||||
-rw-r--r-- | tests/exact01.at | 32 | ||||
-rw-r--r-- | tests/initdb.at | 60 | ||||
-rw-r--r-- | tests/initdb.c | 254 | ||||
-rw-r--r-- | tests/rewrite01.at | 34 | ||||
-rw-r--r-- | tests/rewrite02.at | 34 | ||||
-rw-r--r-- | tests/rewrite03.at | 33 | ||||
-rw-r--r-- | tests/rewrite04.at | 33 | ||||
-rw-r--r-- | tests/rewrite05.at | 33 | ||||
-rw-r--r-- | tests/rewrite06.at | 34 | ||||
-rw-r--r-- | tests/testsuite.at | 52 |
21 files changed, 992 insertions, 118 deletions
diff --git a/Makefile.am b/Makefile.am index 1802a93..7e6f24c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,7 +15,7 @@ # along with vmod-dbrw. If not, see <http://www.gnu.org/licenses/>. ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src doc #tests +SUBDIRS = src doc tests AM_DISTCHECK_CONFIGURE_FLAGS=--without-vmoddir @@ -20,84 +20,101 @@ This version supports MySQL and PostgreSQL databases. The redirection database has the following structure -CREATE TABLE redirects ( - host varchar(255) NOT NULL DEFAULT '', - url varchar(255) NOT NULL DEFAULT '', - dest varchar(255) DEFAULT NULL, - PRIMARY KEY (host,url) -); - -VCL code: - -import dbrw; - -sub vcl_init { - dbrw.config("mysql", "database=dbname;user=varnish;debug=1", - "SELECT dest FROM redirects WHERE host='$host' AND url='$url'"); -} - -sub vcl_recv { - set req.http.X-Redirect-To = - dbrw.rewrite("host=" + req.http.Host + ";" + - "url=" + req.url); - if (req.http.X-Redirect-To != "") { - error(750, "Redirect"); - } -} - -sub vcl_error { - if (obj.status == 750) { - set obj.http.Location = req.http.X-Redirect-To; - set obj.status = 301; - return (deliver); - } -} + CREATE TABLE redirects ( + host varchar(255) NOT NULL DEFAULT '', + url varchar(255) NOT NULL DEFAULT '', + dest varchar(255) DEFAULT NULL, + PRIMARY KEY (host,url) + ); + +VCL 3.x code: + + import dbrw; + + sub vcl_init { + dbrw.config("mysql", "database=dbname;user=varnish;debug=1", + "SELECT dest FROM redirects WHERE host='$host' AND url='$url'"); + } + + sub vcl_recv { + set req.http.X-Redirect-To = + dbrw.rewrite("host=" + req.http.Host + ";" + + "url=" + req.url); + if (req.http.X-Redirect-To != "") { + error(750, "Redirect"); + } + } + + sub vcl_error { + if (obj.status == 750) { + set obj.http.Location = req.http.X-Redirect-To; + set obj.status = 301; + return (deliver); + } + } + +VCL 4.0 code: + + import dbrw; + + sub vcl_init { + dbrw.config("mysql", "database=dbname;user=varnish;debug=1", + "SELECT dest FROM redirects WHERE host='$host' AND url='$url'"); + } + + sub vcl_recv { + set req.http.X-Redirect-To = + dbrw.rewrite("host=" + req.http.Host + ";" + + "url=" + req.url); + if (req.http.X-Redirect-To != "") { + return(synth(301, "Redirect")); + } + } + + sub vcl_synth { + if (resp.status == 301) { + set resp.http.Location = req.http.X-Redirect-To; + return (deliver); + } + } ** More complex case: rewrites Table structure: -CREATE TABLE rewrite ( - host varchar(255) NOT NULL DEFAULT '', - url varchar(255) NOT NULL DEFAULT '', - dest varchar(255) DEFAULT NULL, - value varchar(255) DEFAULT NULL, - pattern varchar(255) DEFAULT NULL, - KEY source (host,url) -) + CREATE TABLE rewrite ( + host varchar(255) NOT NULL DEFAULT '', + url varchar(255) NOT NULL DEFAULT '', + dest varchar(255) DEFAULT NULL, + value varchar(255) DEFAULT NULL, + pattern varchar(255) DEFAULT NULL, + KEY source (host,url) + ) VCL code differs only in definition of the vcl_init: -sub vcl_init { - dbrw.config("mysql", "database=varnish;user=varnish;debug=10", - {"SELECT dest,pattern,value FROM rewrite - WHERE host='$host' and '$url' like url"}); -} + sub vcl_init { + dbrw.config("mysql", "database=varnish;user=varnish;debug=10", + {"SELECT dest,pattern,value FROM rewrite + WHERE host='$host' and '$url' like url"}); + } * Installation In order to compile the package you need to have Varnish source tree. -At least Varnish 3.0.1 is required. Supposing that the varnish source tree -is available under /usr/src/varnish-3.0.1, run: +Both Varnish 3.x and 4.x are supported. Supposing that the Varnish +source tree is available under /usr/src/varnish-3.0.1, run: - ./configure --with-varnish-source=/usr/src/varnish-3.0.1 --with-vmod-dir - -The first option tells configure where Varnish sources reside, the -second one (--with-vmod-dir) instructs it to place created module -files to the standard Varnish module directory. + ./configure --with-varnish-source=/usr/src/varnish-3.0.1 Once configured, do make -This will build the module. After this step you can optionally run -'make test' to test the package. - -Finally, do the following command as root: +This will build the module. Finally, do the following command as root: make install - - + * Bug reporting Send bug reports and suggestions to <gray@gnu.org> @@ -119,6 +136,6 @@ Copyright (C) 2013-2014 Sergey Poznyakoff Local Variables: mode: outline -paragraph-separate: "[ ]*$" +paragraph-separate: "[ ]*$" version-control: never End: diff --git a/configure.ac b/configure.ac index 81ec49b..88ebc51 100644 --- a/configure.ac +++ b/configure.ac @@ -72,6 +72,7 @@ AC_CHECK_FILE([$VARNISHSRC/include/varnishapi.h], [AC_MSG_FAILURE(["$VARNISHSRC" is not a Varnish source directory])]) ]) AC_DEFINE_UNQUOTED([VARNISHVERSION],$VARNISHVERSION,[Varnish major version number]) +AC_SUBST([VARNISHVERSION]) AM_CONDITIONAL([VARNISH3],[test $VARNISHVERSION -eq 3]) AM_CONDITIONAL([VARNISH4],[test $VARNISHVERSION -eq 4]) @@ -185,8 +186,33 @@ esac build_pgsql=$build_pgsql build_mysql=$build_mysql]) +# Initialize the test suite. +AC_ARG_VAR([DBRW_TEST_DBTYPE], [Test database type]) +if test -z "$DBRW_TEST_DBTYPE"; then + if test "$build_mysql" = "yes"; then + DBRW_TEST_DBTYPE=mysql + elif test "$build_pgsql" = "yes"; then + DBRW_TEST_DBTYPE=pgsql + fi +else + eval val=\$build_$DBRW_TEST_DBTYPE + case $val in + yes) ;; + no) AC_MSG_ERROR([DBRW_TEST_DBTYPE is set to a disabled database type]);; + *) AC_MSG_ERROR([DBRW_TEST_DBTYPE is set to unknown database type]);; + esac +fi +AC_ARG_VAR([DBRW_TEST_PARAMS], [SQL connection parameters for testing]) +AC_ARG_VAR([DBRW_TEST_SERVER], [Test SQL server]) +AC_ARG_VAR([DBRW_TEST_NAME], [Test SQL database]) +AC_ARG_VAR([DBRW_TEST_USER], [Test SQL user]) +AC_ARG_VAR([DBRW_TEST_PASS], [Test SQL password]) +AC_ARG_VAR([DBRW_TEST_DEBUG], [Debug settings for testing]) + +AC_CONFIG_TESTDIR(tests) +AC_CONFIG_FILES([tests/Makefile tests/atlocal]) +AM_MISSING_PROG([AUTOM4TE], [autom4te]) -dnl FIXME: tests/Makefile AC_CONFIG_FILES([ Makefile src/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index ed6dd15..1f8bc81 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,32 +14,40 @@ # You should have received a copy of the GNU General Public License # along with vmod-dbrw. If not, see <http://www.gnu.org/licenses/>. -AM_CPPFLAGS = -I$(VARNISHSRC)/include -I$(VARNISHSRC)/bin/varnishd -I$(VARNISHSRC) +AM_CPPFLAGS =\ + -I$(VARNISHSRC)/include\ + -I$(VARNISHSRC)/bin/varnishd\ + -I$(VARNISHSRC) -vmoddir = $(VMODDIR) -vmod_LTLIBRARIES = libvmod_dbrw.la - -libvmod_dbrw_la_LDFLAGS = -module -export-dynamic -avoid-version -libvmod_dbrw_la_LIBADD=@MYSQLLIBS@ @PGSQLLIBS@ - -libvmod_dbrw_la_SOURCES = \ +noinst_LTLIBRARIES = libsql.la +libsql_la_SOURCES = \ + be.c\ dbrw.h\ sql.c\ - vmod_dbrw.c\ wordsplit.h\ wordsplit.c -nodist_libvmod_dbrw_la_SOURCES = vcc_if.c vcc_if.h - -vmod_dbrw.lo: vcc_if.h if USE_MYSQL - libvmod_dbrw_la_SOURCES += mysql.c + libsql_la_SOURCES += mysql.c endif if USE_PGSQL - libvmod_dbrw_la_SOURCES += pgsql.c + libsql_la_SOURCES += pgsql.c endif +libsql_la_LIBADD=@MYSQLLIBS@ @PGSQLLIBS@ + +vmoddir = $(VMODDIR) +vmod_LTLIBRARIES = libvmod_dbrw.la + +libvmod_dbrw_la_LDFLAGS = -module -export-dynamic -avoid-version +libvmod_dbrw_la_LIBADD=./libsql.la + +libvmod_dbrw_la_SOURCES = vmod_dbrw.c +nodist_libvmod_dbrw_la_SOURCES = vcc_if.c vcc_if.h + +vmod_dbrw.lo: vcc_if.h + CLEANFILES = vcc_if.c vcc_if.h *.rst if VARNISH4 diff --git a/src/be.c b/src/be.c new file mode 100644 index 0000000..0e1618b --- /dev/null +++ b/src/be.c @@ -0,0 +1,54 @@ +/* This file is part of vmod-dbrw + Copyright (C) 2013-2014 Sergey Poznyakoff + + Vmod-dbrw is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + Vmod-dbrw is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with vmod-dbrw. If not, see <http://www.gnu.org/licenses/>. +*/ +#include "dbrw.h" + +static struct dbrw_backend *bcktab[] = { +#ifdef USE_SQL_MYSQL + &mysql_backend, +#endif +#ifdef USE_SQL_PGSQL + &pgsql_backend, +#endif + NULL +}; + +struct dbrw_backend * +dbrw_backend_select(const char *name) +{ + int i; + + for (i = 0; bcktab[i]; i++) { + if (strcmp(bcktab[i]->name, name) == 0) + return bcktab[i]; + } + return NULL; +} + +char * +findparam(char **params, char *name) +{ + char *p, *q; + + while (*params) { + p = *params++; + for (q = name; *p && *q && *p == *q; p++, q++); + if (*q == 0 && *p == '=') + return p+1; + } + return NULL; +} + @@ -79,7 +79,7 @@ struct dbrw_backend mysql_backend; struct dbrw_backend pgsql_backend; #endif -char *findparam(char **params, char *name); +struct dbrw_backend *dbrw_backend_select(const char *name); int sql_init(struct dbrw_connection *); int sql_connect(struct dbrw_connection *pd); @@ -92,3 +92,5 @@ void sql_free_result(struct dbrw_connection *pd); void sql_destroy(struct dbrw_connection *pd); const char *sql_get_column(struct dbrw_connection *pd, unsigned row, unsigned col); +char *findparam(char **params, char *name); + diff --git a/src/mysql.c b/src/mysql.c index bcde448..d7406ca 100644 --- a/src/mysql.c +++ b/src/mysql.c @@ -62,6 +62,9 @@ check_errno(struct dbrw_connection *conn) dbrw_error("disabling MySQL connection"); sql_disconnect(conn); conn->state = state_disabled; + break; + default: + dbrw_error("query failed: %s", mysql_error(mp->mysql)); } } diff --git a/src/vmod_dbrw.c b/src/vmod_dbrw.c index ad56b83..13917433 100644 --- a/src/vmod_dbrw.c +++ b/src/vmod_dbrw.c @@ -87,20 +87,6 @@ dbrw_init(struct vmod_priv *priv, const struct VCL_conf *vclconf) return 0; } -char * -findparam(char **params, char *name) -{ - char *p, *q; - - while (*params) { - p = *params++; - for (q = name; *p && *q && *p == *q; p++, q++); - if (*q == 0 && *p == '=') - return p+1; - } - return NULL; -} - static void argv_free(char **argv) { @@ -112,28 +98,6 @@ argv_free(char **argv) } } -static struct dbrw_backend *bcktab[] = { -#ifdef USE_SQL_MYSQL - &mysql_backend, -#endif -#ifdef USE_SQL_PGSQL - &pgsql_backend, -#endif - NULL -}; - -static struct dbrw_backend * -find_backend(const char *name) -{ - int i; - - for (i = 0; bcktab[i]; i++) { - if (strcmp(bcktab[i]->name, name) == 0) - return bcktab[i]; - } - return NULL; -} - static int is_http_status(const char *arg) { @@ -245,7 +209,7 @@ vmod_config(DBRW_CTX ctx, struct vmod_priv *priv, } /* Select backend */ - conf->backend = find_backend(bkname); + conf->backend = dbrw_backend_select(bkname); if (!conf->backend) { dbrw_error("unsupported backend: %s", bkname); argv_free(conf->param); @@ -338,7 +302,7 @@ expand_backref(DBRW_CTX ctx, const char *str, const char *val, WS_Release(WSPTR(ctx), 0); return NULL; } - *p = 0; + *p++ = 0; WS_ReleaseP(WSPTR(ctx), p); @@ -347,6 +311,17 @@ expand_backref(DBRW_CTX ctx, const char *str, const char *val, #define ISEMPTY(s) ((s) == NULL || (s)[0] == 0) +static void +dbrw_sethdr(DBRW_CTX ctx, int where, const char *what, const char *value) +{ +#if VARNISHVERSION == 3 + VRT_SetHdr(ctx, where, what, value, vrt_magic_string_end); +#else + struct gethdr_s s = { where, what }; + VRT_SetHdr(ctx, &s, value, vrt_magic_string_end); +#endif +} + static char * findmatch(DBRW_CTX ctx, struct dbrw_connection *conn, char **param) { @@ -464,10 +439,9 @@ findmatch(DBRW_CTX ctx, struct dbrw_connection *conn, char **param) if (status[0]) { debug(conn->conf, 1, ("setting status %s", status)); - VRT_SetHdr(ctx, HDR_REQ, - "\023X-VMOD-DBRW-Status:", - status, - vrt_magic_string_end); + dbrw_sethdr(ctx, HDR_REQ, + "\023X-VMOD-DBRW-Status:", + status); } break; } diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..e36f81c --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1,7 @@ +atconfig +atlocal +initdb +package.m4 +testsuite +testsuite.dir +testsuite.log diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..1d0094e --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,82 @@ +# This file is part of vmod-dbrw +# Copyright (C) 2013-2014 Sergey Poznyakoff +# +# Vmod-dbrw is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Vmod-dbrw is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with vmod-dbrw. If not, see <http://www.gnu.org/licenses/>. + +EXTRA_DIST = $(TESTSUITE_AT) testsuite package.m4 +DISTCLEANFILES = atconfig $(check_SCRIPTS) +MAINTAINERCLEANFILES = Makefile.in $(TESTSUITE) + + +## ------------ ## +## package.m4. ## +## ------------ ## + +$(srcdir)/package.m4: $(top_srcdir)/configure.ac + $(AM_V_GEN){ \ + echo '# Signature of the current package.'; \ + echo 'm4_define([AT_PACKAGE_NAME], [@PACKAGE_NAME@])'; \ + echo 'm4_define([AT_PACKAGE_TARNAME], [@PACKAGE_TARNAME@])'; \ + echo 'm4_define([AT_PACKAGE_VERSION], [@PACKAGE_VERSION@])'; \ + echo 'm4_define([AT_PACKAGE_STRING], [@PACKAGE_STRING@])'; \ + echo 'm4_define([AT_PACKAGE_BUGREPORT], [@PACKAGE_BUGREPORT@])'; \ + } >$(srcdir)/package.m4 + +# + +## ------------ ## +## Test suite. ## +## ------------ ## + +TESTSUITE_AT = \ + exact01.at\ + initdb.at\ + rewrite01.at\ + rewrite02.at\ + rewrite03.at\ + rewrite04.at\ + rewrite05.at\ + rewrite06.at\ + testsuite.at + +TESTSUITE = $(srcdir)/testsuite +M4=m4 + +AUTOTEST = $(AUTOM4TE) --language=autotest +$(TESTSUITE): package.m4 $(TESTSUITE_AT) + $(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp + mv $@.tmp $@ + +atconfig: $(top_builddir)/config.status + cd $(top_builddir) && ./config.status tests/$@ + +clean-local: + test ! -f $(TESTSUITE) || $(SHELL) $(TESTSUITE) --clean + +check-local: atconfig atlocal $(TESTSUITE) + $(SHELL) $(TESTSUITE) + +# Run the test suite on the *installed* tree. +#installcheck-local: +# $(SHELL) $(TESTSUITE) AUTOTEST_PATH=$(exec_prefix)/bin + + +check_PROGRAMS = initdb +initdb_SOURCES = initdb.c +initdb_LDADD = ../src/libsql.la +initdb_CFLAGS = $(AM_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/src + + + diff --git a/tests/atlocal.in b/tests/atlocal.in new file mode 100644 index 0000000..424072d --- /dev/null +++ b/tests/atlocal.in @@ -0,0 +1,102 @@ +# @configure_input@ -*- shell-script -*- +# Configurable variable values for vmod-dbrw test suite. +# Copyright (C) 2013-2014 Sergey Poznyakoff + +PATH=@abs_builddir@:@abs_top_builddir@/src:@abs_top_srcdir@/build-aux:$top_srcdir:$srcdir:$PATH +VARNISHTEST="@VARNISHSRC@/bin/varnishtest/varnishtest -Dvarnishd=@VARNISHSRC@/bin/varnishd/varnishd" +VARNISHVERSION=@VARNISHVERSION@ +: ${DBRW_TEST_DBTYPE=@DBRW_TEST_DBTYPE@} +: ${DBRW_TEST_PARAMS=@DBRW_TEST_PARAMS@} +: ${DBRW_TEST_SERVER=@DBRW_TEST_SERVER@} +: ${DBRW_TEST_NAME=@DBRW_TEST_NAME@} +: ${DBRW_TEST_USER=@DBRW_TEST_USER@} +: ${DBRW_TEST_PASS=@DBRW_TEST_PASS@} +: ${DBRW_TEST_DEBUG=@DBRW_TEST_DEBUG@} + +if [ -n "$DBRW_TEST_SERVER" ]; then + DBRW_TEST_PARAMS="$DBRW_TEST_PARAMS;server=$DBRW_TEST_SERVER" +fi +if [ -n "$DBRW_TEST_NAME" ]; then + DBRW_TEST_PARAMS="$DBRW_TEST_PARAMS;database=$DBRW_TEST_NAME" +fi +if [ -n "$DBRW_TEST_USER" ]; then + DBRW_TEST_PARAMS="$DBRW_TEST_PARAMS;user=$DBRW_TEST_USER" +fi +if [ -n "$DBRW_TEST_PASS" ]; then + DBRW_TEST_PARAMS="$DBRW_TEST_PARAMS;password=$DBRW_TEST_PASS" +fi +if [ -n "$DBRW_TEST_DEBUG" ]; then + DBRW_TEST_PARAMS="$DBRW_TEST_PARAMS;debug=$DBRW_TEST_DEBUG" +fi + +at_vcl_backend() { + case $VARNISHVERSION in + 3) cat <<EOT +server s1 { + rxreq + txresp +} -start + +varnish v1 -vcl+backend { + import std; + import dbrw from "$abs_top_builddir/src/.libs/libvmod_dbrw.so"; + sub vcl_init { + dbrw.config("$DBRW_TEST_DBTYPE", "$DBRW_TEST_PARAMS", + {"$1"}); + } + + sub vcl_recv { + set req.http.X-Redirect-To = + dbrw.rewrite("host=" + req.http.Host + ";" + + "url=" + req.url); + error(750, "Redirect"); + } + + sub vcl_error { + if (obj.status == 750) { + set obj.http.Location = req.http.X-Redirect-To; + if (req.http.X-VMOD-DBRW-Status) { + set obj.status = std.integer(req.http.X-VMOD-DBRW-Status, 301); + } + return (deliver); + } + } +} -start +EOT + ;; + 4) cat <<EOT +server s1 { + rxreq + txresp +} -start + +varnish v1 -vcl+backend { + import std; + import dbrw from "$abs_top_builddir/src/.libs/libvmod_dbrw.so"; + sub vcl_init { + dbrw.config("$DBRW_TEST_DBTYPE", "$DBRW_TEST_PARAMS", + {"$1"}); + } + + sub vcl_recv { + set req.http.X-Redirect-To = + dbrw.rewrite("host=" + req.http.Host + ";" + + "url=" + req.url); + return(synth(301, "Redirect")); + } + + sub vcl_synth { + if (resp.status == 301) { + if (req.http.X-VMOD-DBRW-Status) { + set resp.status = std.integer(req.http.X-VMOD-DBRW-Status, 301); + } + set resp.http.Location = req.http.X-Redirect-To; + return (deliver); + } + } +} -start +EOT + ;; + *) echo >&2 "unsupported varnish version: $VARNISHVERSION" +esac +} diff --git a/tests/exact01.at b/tests/exact01.at new file mode 100644 index 0000000..a98d832 --- /dev/null +++ b/tests/exact01.at @@ -0,0 +1,32 @@ +# This file is part of vmod-dbrw -*- autotest -*- +# Copyright (C) 2013-2014 Sergey Poznyakoff +# +# Vmod-dbrw is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Vmod-dbrw is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with vmod-dbrw. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP(Exact) +AT_KEYWORDS(exact exact01) +AT_CHECK([ +AT_DBCRED_PREREQ +AT_VCL([SELECT dest FROM redirects WHERE host='$host' AND url='$url'], + [txreq -url /local -hdr "Host:en.example.net" + rxresp + expect resp.http.Location == "http://uno.example.com/remote" +]) +AT_VARNISHTEST +], +[0], +[OK +]) +AT_CLEANUP + diff --git a/tests/initdb.at b/tests/initdb.at new file mode 100644 index 0000000..471942c --- /dev/null +++ b/tests/initdb.at @@ -0,0 +1,60 @@ +# This file is part of vmod-dbrw -*- autotest -*- +# Copyright (C) 2013-2014 Sergey Poznyakoff +# +# Vmod-dbrw is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# Vmod-dbrw is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with vmod-dbrw. If not, see <http://www.gnu.org/licenses/>. + +AT_SETUP([Initialize database]) +AT_KEYWORDS([exact01 rewrite01 rewrite02 rewrite03 rewrite04 rewrite05 + rewrite06]) + +AT_CHECK([ +AT_DBCRED_PREREQ +initdb -c mysql "$DBRW_TEST_PARAMS" 2>err <<'EOT' +DROP TABLE IF EXISTS redirects; +CREATE TABLE redirects ( + host varchar(255) NOT NULL DEFAULT '', + url varchar(255) NOT NULL DEFAULT '', + dest varchar(255) DEFAULT NULL, + PRIMARY KEY (host,url) +); + +INSERT INTO redirects VALUES +('en.example.net','/local','http://uno.example.com/remote'), +('to.example.net','/user','http://dos.example.com/var'); + +DROP TABLE IF EXISTS rewrite; +CREATE TABLE rewrite ( + host varchar(255) NOT NULL DEFAULT '', + url varchar(255) NOT NULL DEFAULT '', + dest varchar(255) DEFAULT NULL, + value varchar(255) DEFAULT NULL, + pattern varchar(255) DEFAULT NULL, + flags varchar(64) DEFAULT NULL, + KEY source (host,url) +); + +INSERT INTO rewrite VALUES +('en.example.net','/local','http://uno.example.com/remote',NULL,NULL,NULL), +('en.example.net','/local/%','http://dos.example.com/$1','$url','/local/(.*)',NULL), +('en.example.net','/local2/%','http://to.example.net/$1$2','$url','/local2/([[^\\?]]*)(\\?.*)?',NULL), +('to.example.net','/local/%','http://dos.example.net/$1','$url','/local/(.*)','QSA'), +('tre.example.net','/local/%','http://dos.example.net/$1?i=10','$url','/local/(.*)','QSA,R=302'); + +EOT +], +[0], +[], +[ignore]) + +AT_CLEANUP
\ No newline at end of file diff --git a/tests/initdb.c b/tests/initdb.c new file mode 100644 index 0000000..16ac968 --- /dev/null +++ b/tests/initdb.c @@ -0,0 +1,254 @@ +/* This file is part of vmod-dbrw + Copyright (C) 2013-2014 Sergey Poznyakoff + + Vmod-dbrw is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + Vmod-dbrw is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with vmod-dbrw. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dbrw.h" +#include "wordsplit.h" +#include <unistd.h> +#include <stdarg.h> +#include <stdio.h> +#include <ctype.h> + +const char *progname; + +void +dbrw_debug(const char *fmt, ...) +{ + va_list ap; + fprintf(stderr, "%s: DEBUG: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputc('\n', stderr); +} + +void +dbrw_error(const char *fmt, ...) +{ + va_list ap; + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputc('\n', stderr); +} + +void +usage(int c) +{ + FILE *fp = c ? stderr : stdout; + fprintf(fp, "usage: %s [-ch] BACKEND CONN\n", progname); + fprintf(fp, "Initializes the test database\n\n"); + fprintf(fp, "BACKEND is mysql or pgsql\n"); + fprintf(fp, "CONN is the vmod-dbrw connection parameter string\n"); + fprintf(fp, "(see second argument to dbrw.config in vmod-dbrw(1))\n"); + fprintf(fp, "\nOPTIONS:\n\n"); + fprintf(fp, " -c create the database if it does not exist\n"); + fprintf(fp, " -h print this help summary\n"); + exit(c); +} + + +int line; +char *qbuf; +size_t qsize; +size_t qlen; + +int +iscomm(const char *p) +{ + for (; *p; p++) { + if (*p == '-' && p[1] == '-') + return 1; + if (!isspace(*p)) + return 0; + } + return 1; +} + +char * +getquery(FILE *fp) +{ + size_t len; + size_t off; + + qlen = off = 0; + while (1) { + if (qlen + 1 >= qsize) { + if (qsize == 0) + qsize = 80; + else + qsize *= 2; + qbuf = realloc(qbuf, qsize); + if (!qbuf) { + dbrw_error("out of memory"); + abort(); + } + } + + + ++line; + if (!fgets(qbuf + qlen, qsize - qlen, fp)) + break; + len = strlen(qbuf + qlen); + qlen += len; + len = qlen; + if (qbuf[len - 1] != '\n') + continue; + while (len > 0 && isspace(qbuf[len - 1])) + --len; + if (iscomm(qbuf + off)) { + qlen = off; + continue; + } else + off = qlen; + if (qbuf[len - 1] == ';') { + qlen = len - 1; + break; + } + } + if (qlen == 0) + return NULL; + qbuf[qlen] = 0; + return qbuf; +} + +void +trycreate(struct dbrw_connection *conn, const char *dbname) +{ + char q[1024]; + if (strcmp(conn->conf->backend->name, "mysql") == 0) { + snprintf(q, sizeof q, "CREATE DATABASE IF NOT EXISTS %s", + dbname); + } else { + snprintf(q, sizeof q, + "IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = '%s') THEN\n" + " CREATE DATABASE %s\n" + "END IF", dbname, dbname); + } + if (sql_query(conn, q)) { + dbrw_error("query failed: %s", q); + exit(4); + } +} + +int +main(int argc, char **argv) +{ + char *s; + struct wordsplit ws; + struct dbrw_config cfg; + struct dbrw_connection conn; + char buf[1024]; + char *p; + char *dbname = NULL; + int create = 0; + int c; + int i; + + progname = argv[0]; + + while ((c = getopt(argc, argv, "ch")) != EOF) { + switch (c) { + case 'c': + create = 1; + break; + + case 'h': + usage(0); + break; + + default: + return 1; + } + } + + argc -= optind; + argv += optind; + + if (argc != 2) + usage(1); + + memset(&cfg, 0, sizeof(cfg)); + cfg.backend = dbrw_backend_select(argv[0]); + if (!cfg.backend) { + dbrw_error("unsupported backend: %s", argv[0]); + return 1; + } + + ws.ws_delim = ";"; + wordsplit(argv[1], &ws, + WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_QUOTE | + WRDSF_CESCAPES | + WRDSF_DELIM | + WRDSF_SHOWERR|WRDSF_ENOMEMABRT); + + cfg.param = ws.ws_wordv; + ws.ws_wordv = NULL; + ws.ws_wordc = 0; + wordsplit_free(&ws); + if (create) { + for (i = 0; cfg.param[i]; i++) + if (strncmp(cfg.param[i], "database=", 9) == 0) + break; + if (!cfg.param[i]) { + dbrw_error("no database specified"); + return 1; + } + dbname = cfg.param[i]; + for (; cfg.param[i+1]; i++) + cfg.param[i] = |