summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Kreen2009-02-13 11:43:01 +0000
committerMarko Kreen2009-02-13 13:20:42 +0000
commit38cd6baf484c0d9219f8bf3628da3e1acc100224 (patch)
tree0f0dce8608b0e8960801d3e4425b81d0dce98e16
parente9b2296f9c273beac1b8cab548d08398914e4de3 (diff)
new tests for cascading
-rw-r--r--tests/cascade/addcol.sql3
-rw-r--r--tests/cascade/conf/londiste_db1.ini8
-rw-r--r--tests/cascade/conf/londiste_db2.ini8
-rw-r--r--tests/cascade/conf/londiste_db3.ini8
-rw-r--r--tests/cascade/conf/nop_consumer.ini12
-rw-r--r--tests/cascade/conf/setadm.ini6
-rw-r--r--tests/cascade/conf/ticker_branch.ini21
-rw-r--r--tests/cascade/conf/ticker_db1.ini7
-rw-r--r--tests/cascade/conf/ticker_db2.ini7
-rw-r--r--tests/cascade/conf/ticker_db3.ini7
-rw-r--r--tests/cascade/conf/worker_db1.ini11
-rw-r--r--tests/cascade/conf/worker_db2.ini11
-rw-r--r--tests/cascade/conf/worker_db3.ini11
-rw-r--r--tests/cascade/footable.sql8
-rwxr-xr-xtests/cascade/init.sh26
-rwxr-xr-xtests/cascade/plainconsumer.py14
-rwxr-xr-xtests/cascade/plainworker.py15
-rwxr-xr-xtests/cascade/regen.sh137
-rwxr-xr-xtests/cascade/status.sh11
-rwxr-xr-xtests/cascade/zcheck.sh4
-rwxr-xr-xtests/cascade/zstop.sh14
-rwxr-xr-xtests/cascade/ztest.sh7
-rw-r--r--tests/env.sh4
-rwxr-xr-xtests/merge/init.sh14
-rwxr-xr-xtests/merge/regen.sh173
-rwxr-xr-xtests/merge/zcheck.sh4
-rwxr-xr-xtests/merge/zstop.sh14
-rwxr-xr-xtests/quoting/regtest.py97
28 files changed, 661 insertions, 1 deletions
diff --git a/tests/cascade/addcol.sql b/tests/cascade/addcol.sql
new file mode 100644
index 00000000..7a0aa69d
--- /dev/null
+++ b/tests/cascade/addcol.sql
@@ -0,0 +1,3 @@
+
+alter table mydata add column foodata text;
+
diff --git a/tests/cascade/conf/londiste_db1.ini b/tests/cascade/conf/londiste_db1.ini
new file mode 100644
index 00000000..d4ce0595
--- /dev/null
+++ b/tests/cascade/conf/londiste_db1.ini
@@ -0,0 +1,8 @@
+[londiste]
+job_name = londiste_db1
+db = dbname=db1
+queue_name = replika
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
+
diff --git a/tests/cascade/conf/londiste_db2.ini b/tests/cascade/conf/londiste_db2.ini
new file mode 100644
index 00000000..9e3417e1
--- /dev/null
+++ b/tests/cascade/conf/londiste_db2.ini
@@ -0,0 +1,8 @@
+[londiste]
+job_name = londiste_db2
+db = dbname=db2
+queue_name = replika
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
+
diff --git a/tests/cascade/conf/londiste_db3.ini b/tests/cascade/conf/londiste_db3.ini
new file mode 100644
index 00000000..44d8104a
--- /dev/null
+++ b/tests/cascade/conf/londiste_db3.ini
@@ -0,0 +1,8 @@
+[londiste]
+job_name = londiste_db3
+db = dbname=db3
+queue_name = replika
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
+
diff --git a/tests/cascade/conf/nop_consumer.ini b/tests/cascade/conf/nop_consumer.ini
new file mode 100644
index 00000000..4cf8f985
--- /dev/null
+++ b/tests/cascade/conf/nop_consumer.ini
@@ -0,0 +1,12 @@
+[nop_consumer]
+
+job_name = nop_consumer
+
+#_provider_db = dbname=db1
+dst_db = dbname=db2
+
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
+queue_name = fooqueue
+
diff --git a/tests/cascade/conf/setadm.ini b/tests/cascade/conf/setadm.ini
new file mode 100644
index 00000000..23b1026f
--- /dev/null
+++ b/tests/cascade/conf/setadm.ini
@@ -0,0 +1,6 @@
+[cascade_admin]
+
+node_db = dbname=db2
+
+queue_name = fooqueue
+
diff --git a/tests/cascade/conf/ticker_branch.ini b/tests/cascade/conf/ticker_branch.ini
new file mode 100644
index 00000000..f2258d4f
--- /dev/null
+++ b/tests/cascade/conf/ticker_branch.ini
@@ -0,0 +1,21 @@
+[pgqadm]
+
+job_name = ticker_branch
+
+db = dbname=db_branch
+
+# how often to run maintenance [minutes]
+maint_delay_min = 1
+
+# how often to check for activity [secs]
+loop_delay = 0.5
+
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
+use_skylog = 0
+
+connection_lifetime = 21
+
+queue_refresh_period = 10
+
diff --git a/tests/cascade/conf/ticker_db1.ini b/tests/cascade/conf/ticker_db1.ini
new file mode 100644
index 00000000..2a422bbe
--- /dev/null
+++ b/tests/cascade/conf/ticker_db1.ini
@@ -0,0 +1,7 @@
+[pgqadm]
+job_name = ticker_db1
+db = dbname=db1
+loop_delay = 0.5
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
diff --git a/tests/cascade/conf/ticker_db2.ini b/tests/cascade/conf/ticker_db2.ini
new file mode 100644
index 00000000..2b3d38e8
--- /dev/null
+++ b/tests/cascade/conf/ticker_db2.ini
@@ -0,0 +1,7 @@
+[pgqadm]
+job_name = ticker_db2
+db = dbname=db2
+loop_delay = 0.5
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
diff --git a/tests/cascade/conf/ticker_db3.ini b/tests/cascade/conf/ticker_db3.ini
new file mode 100644
index 00000000..337575c6
--- /dev/null
+++ b/tests/cascade/conf/ticker_db3.ini
@@ -0,0 +1,7 @@
+[pgqadm]
+job_name = ticker_db3
+db = dbname=db3
+loop_delay = 0.5
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
diff --git a/tests/cascade/conf/worker_db1.ini b/tests/cascade/conf/worker_db1.ini
new file mode 100644
index 00000000..c3e3d302
--- /dev/null
+++ b/tests/cascade/conf/worker_db1.ini
@@ -0,0 +1,11 @@
+[nop_worker]
+
+job_name = node1_worker
+
+dst_db = dbname=db1
+
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
+queue_name = fooqueue
+
diff --git a/tests/cascade/conf/worker_db2.ini b/tests/cascade/conf/worker_db2.ini
new file mode 100644
index 00000000..e77ca20a
--- /dev/null
+++ b/tests/cascade/conf/worker_db2.ini
@@ -0,0 +1,11 @@
+[nop_worker]
+
+job_name = node2_worker
+
+dst_db = dbname=db2
+
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
+queue_name = fooqueue
+
diff --git a/tests/cascade/conf/worker_db3.ini b/tests/cascade/conf/worker_db3.ini
new file mode 100644
index 00000000..b44aa7e6
--- /dev/null
+++ b/tests/cascade/conf/worker_db3.ini
@@ -0,0 +1,11 @@
+[nop_worker]
+
+job_name = node3_worker
+
+dst_db = dbname=db3
+
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+
+queue_name = fooqueue
+
diff --git a/tests/cascade/footable.sql b/tests/cascade/footable.sql
new file mode 100644
index 00000000..83316627
--- /dev/null
+++ b/tests/cascade/footable.sql
@@ -0,0 +1,8 @@
+
+create table footable (
+ id serial primary key,
+ username text not null,
+ utype int4 not null check (utype in (1,2,3))
+);
+create index uindex on footable (username);
+
diff --git a/tests/cascade/init.sh b/tests/cascade/init.sh
new file mode 100755
index 00000000..19df887a
--- /dev/null
+++ b/tests/cascade/init.sh
@@ -0,0 +1,26 @@
+#! /bin/sh
+
+. ../env.sh
+
+dropdb db1
+dropdb db2
+dropdb db3
+
+createdb db1
+createdb db2
+createdb db3
+
+pgqadm.py conf/ticker_db1.ini install
+pgqadm.py conf/ticker_db2.ini install
+pgqadm.py conf/ticker_db3.ini install
+
+lst="part1 part2 part3 part4 full1 full2 full3 full4"
+
+for db in $lst; do
+ echo dropdb $db
+ dropdb $db
+done
+for db in $lst; do
+ echo createdb $db
+ createdb $db
+done
diff --git a/tests/cascade/plainconsumer.py b/tests/cascade/plainconsumer.py
new file mode 100755
index 00000000..81bad948
--- /dev/null
+++ b/tests/cascade/plainconsumer.py
@@ -0,0 +1,14 @@
+#! /usr/bin/env python
+
+import sys, time, skytools
+
+from pgq.cascade.consumer import CascadedConsumer
+
+class PlainCascadedConsumer(CascadedConsumer):
+ def process_remote_event(self, src_curs, dst_curs, ev):
+ ev.tag_done()
+
+if __name__ == '__main__':
+ script = PlainCascadedConsumer('nop_consumer', 'dst_db', sys.argv[1:])
+ script.start()
+
diff --git a/tests/cascade/plainworker.py b/tests/cascade/plainworker.py
new file mode 100755
index 00000000..48f00530
--- /dev/null
+++ b/tests/cascade/plainworker.py
@@ -0,0 +1,15 @@
+#! /usr/bin/env python
+
+import sys, time, skytools
+
+from pgq.cascade.worker import CascadedWorker
+
+class PlainCascadedWorker(CascadedWorker):
+ def process_remote_event(self, src_db, dst_db, ev):
+ self.log.info("got events: %s / %s" % (ev.ev_type, ev.ev_data))
+ ev.tag_done()
+
+if __name__ == '__main__':
+ script = PlainCascadedWorker('nop_worker', 'dst_db', sys.argv[1:])
+ script.start()
+
diff --git a/tests/cascade/regen.sh b/tests/cascade/regen.sh
new file mode 100755
index 00000000..7baf2136
--- /dev/null
+++ b/tests/cascade/regen.sh
@@ -0,0 +1,137 @@
+#! /bin/sh
+
+. ../env.sh
+
+mkdir -p log pid
+
+./zstop.sh
+
+v=
+v=-v
+v=-q
+
+cleardb() {
+ psql -q -d $db -c '
+ set client_min_messages=warning;
+ drop schema if exists londiste cascade;
+ drop schema if exists pgq_node cascade;
+ drop schema if exists pgq cascade;
+ drop table if exists mydata;
+ drop table if exists footable;
+ drop sequence if exists footable_id_seq;
+ '
+}
+
+run() {
+ echo "$ $*"
+ "$@"
+}
+
+for db in db1 db2 db3; do
+ pgqadm.py conf/ticker_$db.ini -k
+ cleardb $db
+done
+
+run ./plainconsumer.py -s conf/nop_consumer.ini
+
+rm -f log/*.log
+
+set -e
+
+run cat conf/ticker_db1.ini
+
+#echo " # pgqadm install # "
+run pgqadm.py $v conf/ticker_db1.ini install
+run pgqadm.py $v conf/ticker_db2.ini install
+run pgqadm.py $v conf/ticker_db3.ini install
+
+#echo " # pgqadm ticker # "
+run pgqadm.py $v -d conf/ticker_db1.ini ticker
+run pgqadm.py $v -d conf/ticker_db2.ini ticker
+run pgqadm.py $v -d conf/ticker_db3.ini ticker
+
+if false; then
+
+#echo " # setadm create-node # "
+run setadm.py $v --worker=node1_worker conf/setadm.ini create-root node1 'dbname=db1'
+run setadm.py $v --worker=node2_worker conf/setadm.ini create-branch node2 'dbname=db2' --provider='dbname=db1'
+run setadm.py $v --worker=node3_worker conf/setadm.ini create-branch node3 'dbname=db3' --provider='dbname=db2'
+
+#echo " # setadm status # "
+run setadm.py $v conf/setadm.ini status
+
+#echo " # plainconsumer # "
+run ./plainconsumer.py $v conf/nop_consumer.ini --register --provider='dbname=db1'
+run ./plainconsumer.py $v -d conf/nop_consumer.ini
+
+#echo " # plainworker # "
+run ./plainworker.py $v -d conf/worker_db1.ini
+run ./plainworker.py $v -d conf/worker_db2.ini
+run ./plainworker.py $v -d conf/worker_db3.ini
+
+
+#echo " # insert_event() # "
+run psql db1 -c "select pgq.insert_event('fooqueue', 'tmp', 'data')"
+
+fi
+
+grep -E 'ERR|WARN|CRIT' log/*.log || true
+
+#exit 0
+
+# -- londiste
+
+for db in db1 db2 db3; do
+ run psql $db -c "create table mydata (id serial primary key, data text)"
+done
+
+run cat conf/londiste_db1.ini
+
+run londiste.py $v conf/londiste_db1.ini create-root rnode1 'dbname=db1'
+run londiste.py $v conf/londiste_db2.ini create-branch rnode2 'dbname=db2' --provider='dbname=db1'
+run londiste.py $v conf/londiste_db3.ini create-branch rnode3 'dbname=db3' --provider='dbname=db2'
+
+run londiste.py $v -d conf/londiste_db1.ini replay
+run londiste.py $v -d conf/londiste_db2.ini replay
+run londiste.py $v -d conf/londiste_db3.ini replay
+
+run londiste.py $v conf/londiste_db1.ini add-table mydata
+run londiste.py $v conf/londiste_db2.ini add-table mydata
+run londiste.py $v conf/londiste_db3.ini add-table mydata
+
+run cat addcol.sql
+run londiste.py $v conf/londiste_db1.ini execute addcol.sql
+
+run sleep 10
+run psql db3 -c '\d mydata'
+
+run londiste.py $v conf/londiste_db1.ini status
+run londiste.py $v conf/londiste_db3.ini change-provider --provider=rnode1
+run londiste.py $v conf/londiste_db1.ini status
+run londiste.py $v conf/londiste_db1.ini switchover --target=rnode2
+run londiste.py $v conf/londiste_db1.ini status
+
+run cat footable.sql
+
+run psql db2 -f footable.sql
+run londiste.py $v conf/londiste_db2.ini add-seq footable_id_seq
+run londiste.py $v conf/londiste_db2.ini add-table footable
+run londiste.py $v conf/londiste_db1.ini add-seq footable_id_seq --create
+run londiste.py $v conf/londiste_db1.ini add-table footable --create
+run londiste.py $v conf/londiste_db3.ini add-seq footable_id_seq --create
+run londiste.py $v conf/londiste_db3.ini add-table footable --create
+
+#run psql db2 -f footable.sql
+#run londiste.py $v conf/londiste_db2.ini add-seq footable_id_seq
+#run londiste.py $v conf/londiste_db2.ini add-table footable
+#run londiste.py $v conf/londiste_db2.ini add-seq footable_id_seq --create
+#run londiste.py $v conf/londiste_db1.ini add-table footable --create
+#run londiste.py $v conf/londiste_db2.ini add-seq footable_id_seq --create
+#run londiste.py $v conf/londiste_db3.ini add-table footable --create
+
+run psql db3 -c '\d footable'
+
+sleep 3
+
+grep -E 'ERR|WARN|CRIT' log/*.log || echo "All OK"
+
diff --git a/tests/cascade/status.sh b/tests/cascade/status.sh
new file mode 100755
index 00000000..9ff9d8d2
--- /dev/null
+++ b/tests/cascade/status.sh
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+. ../env.sh
+
+pgqadm.py conf/ticker_db1.ini status
+pgqadm.py conf/ticker_db2.ini status
+pgqadm.py conf/ticker_db3.ini status
+
+setadm.py -v conf/setadm.ini status
+
+
diff --git a/tests/cascade/zcheck.sh b/tests/cascade/zcheck.sh
new file mode 100755
index 00000000..96f59aed
--- /dev/null
+++ b/tests/cascade/zcheck.sh
@@ -0,0 +1,4 @@
+#! /bin/sh
+
+grep -E 'ERR|WARN|CRIT' log/*.log || echo "All OK"
+
diff --git a/tests/cascade/zstop.sh b/tests/cascade/zstop.sh
new file mode 100755
index 00000000..69e574cb
--- /dev/null
+++ b/tests/cascade/zstop.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+#. ../env.sh
+
+for p in pid/*.pid*; do
+ test -f "$p" || continue
+ pid=`cat "$p"`
+ test -d "/proc/$pid" || {
+ rm -f "$p"
+ continue
+ }
+ kill "$pid"
+done
+
diff --git a/tests/cascade/ztest.sh b/tests/cascade/ztest.sh
new file mode 100755
index 00000000..7ef0e79a
--- /dev/null
+++ b/tests/cascade/ztest.sh
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+. ../env.sh
+
+./plainconsumer.py -v conf/nop_consumer.ini --register
+./plainconsumer.py -v conf/nop_consumer.ini
+
diff --git a/tests/env.sh b/tests/env.sh
index 11d82a3c..d344ffcf 100644
--- a/tests/env.sh
+++ b/tests/env.sh
@@ -1,6 +1,8 @@
PYTHONPATH=../../python:$PYTHONPATH
PATH=../../python:../../python/bin:../../scripts:$PATH
-export PYTHONPATH PATH
+#LD_LIBRARY_PATH=/opt/apps/py26/lib:$LD_LIBRARY_PATH
+#PATH=/opt/apps/py26/bin:$PATH
+export PYTHONPATH PATH LD_LIBRARY_PATH PATH
diff --git a/tests/merge/init.sh b/tests/merge/init.sh
new file mode 100755
index 00000000..3f992dc9
--- /dev/null
+++ b/tests/merge/init.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+. ../env.sh
+
+lst="part1 part2 part3 part4 full1 full2 full3 full4"
+
+for db in $lst; do
+ echo dropdb $db
+ dropdb $db
+done
+for db in $lst; do
+ echo createdb $db
+ createdb $db
+done
diff --git a/tests/merge/regen.sh b/tests/merge/regen.sh
new file mode 100755
index 00000000..fad7463a
--- /dev/null
+++ b/tests/merge/regen.sh
@@ -0,0 +1,173 @@
+#! /bin/sh
+
+. ../env.sh
+
+mkdir -p log pid conf
+
+./zstop.sh
+
+v=
+v=-q
+v=-v
+
+cleardb() {
+ echo "Clearing database $1"
+ psql -q -d $1 -c '
+ set client_min_messages=warning;
+ drop schema if exists londiste cascade;
+ drop schema if exists pgq_node cascade;
+ drop schema if exists pgq cascade;
+ drop table if exists mydata;
+ drop table if exists footable;
+ drop sequence if exists footable_id_seq;
+ '
+}
+
+run() {
+ echo "$ $*"
+ "$@"
+}
+
+part_list="part1 part2 part3 part4"
+full_list="full1 full2 full3 full4"
+merge_list=""
+for dst in $full_list; do
+ for src in $part_list; do
+ merge_list="$merge_list ${src}_${dst}"
+ done
+done
+all_list="$part_list $full_list"
+
+echo " * create configs * "
+
+# create ticker conf
+for db in $all_list; do
+cat > conf/ticker_$db.ini << EOF
+[pgqadm]
+job_name = ticker_$db
+db = dbname=$db
+loop_delay = 0.5
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+EOF
+done
+
+# partition replicas
+for db in $part_list; do
+
+# londiste on part node
+cat > conf/londiste_$db.ini << EOF
+[londiste]
+job_name = londiste_$db
+db = dbname=$db
+queue_name = replika_$db
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+EOF
+
+# londiste on combined nodes
+for dst in full1 full2; do
+cat > conf/londiste_${db}_${dst}.ini << EOF
+[londiste]
+job_name = londiste_${db}_${dst}
+db = dbname=$dst
+queue_name = replika_$db
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+EOF
+
+done
+done
+
+# full replicas
+for db in $full_list; do
+
+cat > conf/londiste_$db.ini << EOF
+[londiste]
+job_name = londiste_$db
+db = dbname=$db
+queue_name = replika
+logfile = log/%(job_name)s.log
+pidfile = pid/%(job_name)s.pid
+EOF
+
+done
+
+
+
+for db in $part_list $full_list; do
+ cleardb $db
+done
+
+echo "clean logs"
+rm -f log/*.log
+
+set -e
+
+for db in $all_list; do
+ run pgqadm.py $v conf/ticker_$db.ini install
+done
+
+run londiste.py $v conf/londiste_full1.ini create-root fnode1 'dbname=full1'
+run londiste.py $v conf/londiste_full2.ini create-branch fnode2 'dbname=full2' --provider='dbname=full1'
+run londiste.py $v conf/londiste_full3.ini create-branch fnode3 'dbname=full3' --provider='dbname=full1'
+run londiste.py $v conf/londiste_full4.ini create-leaf fnode4 'dbname=full4' --provider='dbname=full2'
+
+run londiste.py $v conf/londiste_part1.ini create-root p1root 'dbname=part1'
+run londiste.py $v conf/londiste_part2.ini create-root p2root 'dbname=part2'
+run londiste.py $v conf/londiste_part3.ini create-root p3root 'dbname=part3'
+run londiste.py $v conf/londiste_part4.ini create-root p4root 'dbname=part4'
+
+
+for dst in full1 full2; do
+ for src in $part_list; do
+ run londiste.py $v conf/londiste_${src}_${dst}.ini \
+ create-leaf merge_${src}_${dst} "dbname=$dst" \
+ --provider="dbname=$src" --merge="replika"
+ done
+done
+
+for db in $all_list; do
+ run pgqadm.py $v -d conf/ticker_$db.ini ticker
+ run londiste.py $v -d conf/londiste_$db.ini replay
+done
+
+for dst in full1 full2; do
+ for src in $part_list; do
+ run londiste.py $v -d conf/londiste_${src}_${dst}.ini replay
+ done
+done
+
+for db in $part_list; do
+ run psql $db -c "create table mydata (id int4 primary key, data text)"
+ run londiste.py $v conf/londiste_$db.ini add-table mydata
+done
+for n in 1 2 3 4; do
+ run psql -d part$n -c "insert into mydata values ($n, 'part$n')"
+done
+
+for db in full1; do
+ run psql $db -c "create table mydata (id int4 primary key, data text)"
+ run londiste.py $v conf/londiste_$db.ini add-table mydata
+ for src in $part_list; do
+ run londiste.py $v conf/londiste_${src}_${db}.ini add-table mydata
+ done
+done
+
+run sleep 10
+
+for n in 1 2 3 4; do
+ run psql -d part$n -c "insert into mydata values (4 + $n, 'part$n')"
+done
+
+run sleep 10
+
+for db in full1; do
+run psql -d $db -c "select * from mydata order by id"
+run psql -d $db -c "select * from londiste.table_info order by queue_name"
+done
+run psql -d full1 -c "select * from londiste.get_table_list('replika_part1')"
+run psql -d full1 -c "select * from londiste.get_table_list('replika_part2')"
+
+./zcheck.sh
+
diff --git a/tests/merge/zcheck.sh b/tests/merge/zcheck.sh
new file mode 100755
index 00000000..96f59aed
--- /dev/null
+++ b/tests/merge/zcheck.sh
@@ -0,0 +1,4 @@
+#! /bin/sh
+
+grep -E 'ERR|WARN|CRIT' log/*.log || echo "All OK"
+
diff --git a/tests/merge/zstop.sh b/tests/merge/zstop.sh
new file mode 100755
index 00000000..69e574cb
--- /dev/null
+++ b/tests/merge/zstop.sh
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+#. ../env.sh
+
+for p in pid/*.pid*; do
+ test -f "$p" || continue
+ pid=`cat "$p"`
+ test -d "/proc/$pid" || {
+ rm -f "$p"
+ continue
+ }
+ kill "$pid"
+done
+
diff --git a/tests/quoting/regtest.py b/tests/quoting/regtest.py
new file mode 100755
index 00000000..bbe85c74
--- /dev/null
+++ b/tests/quoting/regtest.py
@@ -0,0 +1,97 @@
+#! /usr/bin/env python
+
+import sys, time
+import skytools.psycopgwrapper
+import skytools._cquoting, skytools._pyquoting
+from decimal import Decimal
+
+# create a DictCursor row
+class fake_cursor:
+ index = {'id': 0, 'data': 1}
+ description = ['x', 'x']
+dbrow = skytools.psycopgwrapper._CompatRow(fake_cursor())
+dbrow[0] = '123'
+dbrow[1] = 'value'
+
+def regtest(name, func, cases):
+ bad = 0
+ for dat, res in cases:
+ res2 = func(dat)
+ if res != res2:
+ print("failure: %s(%s) = %s (expected %s)" % (name, repr(dat), repr(res2), repr(res)))
+ bad += 1
+ if bad:
+ print("%-20s: failed" % name)
+ else:
+ print("%-20s: OK" % name)
+
+
+sql_literal = [
+ [None, "null"],
+ ["", "''"],
+ ["a'b", "'a''b'"],
+ [r"a\'b", r"E'a\\''b'"],
+ [1, "'1'"],
+ [True, "'True'"],
+ [Decimal(1), "'1'"],
+]
+regtest("quote_literal/c", skytools._cquoting.quote_literal, sql_literal)
+regtest("quote_literal/py", skytools._pyquoting.quote_literal, sql_literal)
+
+sql_copy = [
+ [None, "\\N"],
+ ["", ""],
+ ["a'\tb", "a'\\tb"],
+ [r"a\'b", r"a\\'b"],
+ [1, "1"],
+ [True, "True"],
+ [u"qwe", "qwe"],
+ [Decimal(1), "1"],
+]
+regtest("quote_copy/c", skytools._cquoting.quote_copy, sql_copy)
+regtest("quote_copy/py", skytools._pyquoting.quote_copy, sql_copy)
+
+sql_bytea_raw = [
+ [None, None],
+ ["", ""],
+ ["a'\tb", "a'\\011b"],
+ [r"a\'b", r"a\\'b"],
+ ["\t\344", r"\011\344"],
+]
+regtest("quote_bytea_raw/c", skytools._cquoting.quote_bytea_raw, sql_bytea_raw)
+regtest("quote_bytea_raw/py", skytools._pyquoting.quote_bytea_raw, sql_bytea_raw)
+
+t_urlenc = [
+ [{}, ""],
+ [{'a': 1}, "a=1"],
+ [{'a': None}, "a"],
+ [{'qwe': 1, u'zz': u"qwe"}, "qwe=1&zz=qwe"],
+ [{'a': '\000%&'}, "a=%00%25%26"],
+ [dbrow, 'data=value&id=123'],
+ [{'a': Decimal("1")}, "a=1"],
+]
+regtest("db_urlencode/c", skytools._cquoting.db_urlencode, t_urlenc)
+regtest("db_urlencode/py", skytools._pyquoting.db_urlencode, t_urlenc)
+
+t_urldec = [
+ ["", {}],
+ ["a=b&c", {'a': 'b', 'c': None}],
+ ["&&b=f&&", {'b': 'f'}],
+ [u"abc=qwe", {'abc': 'qwe'}],
+ ["b=", {'b': ''}],
+ ["b=%00%45", {'b': '\x00E'}],
+]
+regtest("db_urldecode/c", skytools._cquoting.db_urldecode, t_urldec)
+regtest("db_urldecode/py", skytools._pyquoting.db_urldecode, t_urldec)
+
+t_unesc = [
+ ["", ""],
+ ["\\N", "N"],
+ ["abc", "abc"],
+ [u"abc", "abc"],
+ [r"\0\000\001\01\1", "\0\000\001\001\001"],
+ [r"a\001b\tc\r\n", "a\001b\tc\r\n"],
+]
+regtest("unescape/c", skytools._cquoting.unescape, t_unesc)
+regtest("unescape/py", skytools._pyquoting.unescape, t_unesc)
+