aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2014-11-11 21:11:37 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2014-11-12 00:10:27 +0200
commit5d91de768f4a5f75f6b663e7d80c94f47e45de23 (patch)
tree8d07950953625faa8c9852379c071c7ea454b8c9
parent55e620d377854d7416ee63d8e2d91905e78b421b (diff)
downloadvmod-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.am2
-rw-r--r--README135
-rw-r--r--configure.ac28
-rw-r--r--src/Makefile.am36
-rw-r--r--src/be.c54
-rw-r--r--src/dbrw.h4
-rw-r--r--src/mysql.c3
-rw-r--r--src/vmod_dbrw.c58
-rw-r--r--tests/.gitignore7
-rw-r--r--tests/Makefile.am82
-rw-r--r--tests/atlocal.in102
-rw-r--r--tests/exact01.at32
-rw-r--r--tests/initdb.at60
-rw-r--r--tests/initdb.c254
-rw-r--r--tests/rewrite01.at34
-rw-r--r--tests/rewrite02.at34
-rw-r--r--tests/rewrite03.at33
-rw-r--r--tests/rewrite04.at33
-rw-r--r--tests/rewrite05.at33
-rw-r--r--tests/rewrite06.at34
-rw-r--r--tests/testsuite.at52
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
diff --git a/README b/README
index f730269..4c22ea4 100644
--- a/README
+++ b/README
@@ -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;
+}
+
diff --git a/src/dbrw.h b/src/dbrw.h
index 7dd6606..855720a 100644
--- a/src/dbrw.h
+++ b/src/dbrw.h
@@ -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] =