From 2da536c0f6a081a50cb708de3ad6631345ec8dca Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Wed, 14 Mar 2018 16:47:44 -0300
Subject: [PATCH] test module

---
 src/test/modules/Makefile                          |  1 +
 src/test/modules/test_subscription/Makefile        | 18 +++++++
 .../modules/test_subscription/testsub1--1.0.sql    | 22 +++++++++
 src/test/modules/test_subscription/testsub1.c      | 42 ++++++++++++++++
 .../modules/test_subscription/testsub1.control     |  4 ++
 .../modules/test_subscription/testsub2--1.0.sql    | 22 +++++++++
 src/test/modules/test_subscription/testsub2.c      | 45 +++++++++++++++++
 .../modules/test_subscription/testsub2.control     |  4 ++
 src/test/subscription/Makefile                     |  2 +-
 src/test/subscription/t/010_slot_store_error.pl    | 56 ++++++++++++++++++++++
 10 files changed, 215 insertions(+), 1 deletion(-)
 create mode 100644 src/test/modules/test_subscription/Makefile
 create mode 100644 src/test/modules/test_subscription/testsub1--1.0.sql
 create mode 100644 src/test/modules/test_subscription/testsub1.c
 create mode 100644 src/test/modules/test_subscription/testsub1.control
 create mode 100644 src/test/modules/test_subscription/testsub2--1.0.sql
 create mode 100644 src/test/modules/test_subscription/testsub2.c
 create mode 100644 src/test/modules/test_subscription/testsub2.control
 create mode 100644 src/test/subscription/t/010_slot_store_error.pl

diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 7294b6958b..a455634538 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -17,6 +17,7 @@ SUBDIRS = \
 		  test_rbtree \
 		  test_rls_hooks \
 		  test_shm_mq \
+		  test_subscription \
 		  worker_spi
 
 all: submake-generated-headers
diff --git a/src/test/modules/test_subscription/Makefile b/src/test/modules/test_subscription/Makefile
new file mode 100644
index 0000000000..12993e0ac5
--- /dev/null
+++ b/src/test/modules/test_subscription/Makefile
@@ -0,0 +1,18 @@
+# src/test/modules/test_subscription/Makefile
+
+MODULES = testsub1 testsub2
+EXTENSION = testsub1 testsub2
+DATA = testsub1--1.0.sql testsub2--1.0.sql
+
+PGFILEDESC = "test_subscription - mock extensions for subscription test"
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_subscription
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_subscription/testsub1--1.0.sql b/src/test/modules/test_subscription/testsub1--1.0.sql
new file mode 100644
index 0000000000..43ab7187df
--- /dev/null
+++ b/src/test/modules/test_subscription/testsub1--1.0.sql
@@ -0,0 +1,22 @@
+/* src/test/modules/test_subscription/testsub1--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION testsub1" to load this file. \quit
+
+CREATE TYPE dummytext;
+
+CREATE FUNCTION dummytext_in(cstring)
+RETURNS dummytext
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION dummytext_out(dummytext)
+RETURNS cstring
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE TYPE dummytext (
+       INTERNALLENGTH = -1,
+       INPUT = dummytext_in,
+       OUTPUT = dummytext_out
+);
diff --git a/src/test/modules/test_subscription/testsub1.c b/src/test/modules/test_subscription/testsub1.c
new file mode 100644
index 0000000000..e94fbe735a
--- /dev/null
+++ b/src/test/modules/test_subscription/testsub1.c
@@ -0,0 +1,42 @@
+/*--------------------------------------------------------------------------
+ *
+ * testsub1.c
+ *		Code for testing logical replication subscriptions.
+ *
+ * Copyright (c) 2018, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		src/test/modules/test_subscription/testsub1.c
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "fmgr.h"
+#include "utils/builtins.h"
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(dummytext_in);
+PG_FUNCTION_INFO_V1(dummytext_out);
+
+/* Dummy input of data type function */
+Datum
+dummytext_in(PG_FUNCTION_ARGS)
+{
+	char	*inputText = PG_GETARG_CSTRING(0);
+
+	if (inputText)
+		elog(LOG, "input text: \"%s\"", inputText);
+
+	PG_RETURN_TEXT_P(cstring_to_text(inputText));
+}
+
+/* Dummy output of data type function */
+Datum
+dummytext_out(PG_FUNCTION_ARGS)
+{
+	Datum	txt = PG_GETARG_DATUM(0);
+
+	PG_RETURN_CSTRING(TextDatumGetCString(txt));
+}
diff --git a/src/test/modules/test_subscription/testsub1.control b/src/test/modules/test_subscription/testsub1.control
new file mode 100644
index 0000000000..746bba3442
--- /dev/null
+++ b/src/test/modules/test_subscription/testsub1.control
@@ -0,0 +1,4 @@
+comment = 'extension testsub1 to test subscriptions'
+default_version = '1.0'
+module_pathname = '$libdir/testsub1'
+relocatable = true
diff --git a/src/test/modules/test_subscription/testsub2--1.0.sql b/src/test/modules/test_subscription/testsub2--1.0.sql
new file mode 100644
index 0000000000..4c94dd3c92
--- /dev/null
+++ b/src/test/modules/test_subscription/testsub2--1.0.sql
@@ -0,0 +1,22 @@
+/* src/test/modules/test_subscription/testsub2--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION testsub2" to load this file. \quit
+
+CREATE TYPE dummyint;
+
+CREATE FUNCTION dummyint_in(cstring)
+RETURNS dummyint
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE FUNCTION dummyint_out(dummyint)
+RETURNS cstring
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
+
+CREATE TYPE dummyint (
+	   LIKE = pg_catalog.int4,
+       INPUT = dummyint_in,
+       OUTPUT = dummyint_out
+);
diff --git a/src/test/modules/test_subscription/testsub2.c b/src/test/modules/test_subscription/testsub2.c
new file mode 100644
index 0000000000..d1a91b6656
--- /dev/null
+++ b/src/test/modules/test_subscription/testsub2.c
@@ -0,0 +1,45 @@
+/*--------------------------------------------------------------------------
+ *
+ * testsub2.c
+ *		Code for testing logical replication subscriptions.
+ *
+ * Copyright (c) 2018, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *		src/test/modules/test_subscription/testsub2.c
+ *
+ * -------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "fmgr.h"
+#include "utils/builtins.h"
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(dummyint_in);
+PG_FUNCTION_INFO_V1(dummyint_out);
+
+/* Dummy input of data type function */
+Datum
+dummyint_in(PG_FUNCTION_ARGS)
+{
+	char   *num = PG_GETARG_CSTRING(0);
+	int32	val;
+
+	val = pg_atoi(num, sizeof(int32), '\0');
+	elog(LOG, "input int: %d", val);
+
+	PG_RETURN_INT32(val);
+}
+
+/* Dummy output of data type function */
+Datum
+dummyint_out(PG_FUNCTION_ARGS)
+{
+	int32		arg1 = PG_GETARG_INT32(0);
+	char	   *result = (char *) palloc(12);	/* sign, 10 digits, '\0' */
+
+	pg_ltoa(arg1, result);
+	PG_RETURN_CSTRING(result);
+}
diff --git a/src/test/modules/test_subscription/testsub2.control b/src/test/modules/test_subscription/testsub2.control
new file mode 100644
index 0000000000..8a0341c86f
--- /dev/null
+++ b/src/test/modules/test_subscription/testsub2.control
@@ -0,0 +1,4 @@
+comment = 'extension testsub2 to test subscriptions'
+default_version = '1.0'
+module_pathname = '$libdir/testsub2'
+relocatable = true
diff --git a/src/test/subscription/Makefile b/src/test/subscription/Makefile
index 0f3d2098ad..f5e76bb264 100644
--- a/src/test/subscription/Makefile
+++ b/src/test/subscription/Makefile
@@ -13,7 +13,7 @@ subdir = src/test/subscription
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-EXTRA_INSTALL = contrib/hstore
+EXTRA_INSTALL = contrib/hstore src/test/modules/test_subscription
 
 check:
 	$(prove_check)
diff --git a/src/test/subscription/t/010_slot_store_error.pl b/src/test/subscription/t/010_slot_store_error.pl
new file mode 100644
index 0000000000..b525bc03dc
--- /dev/null
+++ b/src/test/subscription/t/010_slot_store_error.pl
@@ -0,0 +1,56 @@
+# This tests that the errors when data type conversion are correctly
+# handled by logical replication apply workers
+use strict;
+use warnings;
+
+use PostgresNode;
+use TestLib;
+use Test::More tests => 1;
+
+# Initialize publisher node
+my $node_publisher = get_new_node('publisher');
+$node_publisher->init(allows_streaming => 'logical');
+$node_publisher->start;
+
+# Create subscriber node
+my $node_subscriber = get_new_node('subscriber');
+$node_subscriber->init(allows_streaming => 'logical');
+$node_subscriber->start;
+
+# Setup same table by different steps so that publisher and subscriber get
+# different datatype OIDs.
+$node_publisher->safe_psql('postgres', qq[
+CREATE EXTENSION testsub2;
+CREATE EXTENSION testsub1;
+CREATE TABLE test (a dummytext, b dummyint);]);
+
+$node_subscriber->safe_psql('postgres', qq[
+CREATE EXTENSION testsub1;
+CREATE EXTENSION testsub2;
+CREATE TABLE test (b dummyint, a dummytext);]);
+
+# Setup logical replication
+my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
+$node_publisher->safe_psql('postgres', qq[
+CREATE PUBLICATION tap_pub FOR TABLE test
+]);
+my $appname = 'tap_sub';
+$node_subscriber->safe_psql('postgres', qq[
+CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (slot_name = tap_sub_slot, copy_data = false)
+]);
+
+# Insert test data, which will lead to call the callback function for the date
+# type conversion on subscriber.
+$node_publisher->safe_psql('postgres', qq(
+INSERT INTO test VALUES ('one', '1');
+));
+
+$node_publisher->wait_for_catchup($appname);
+
+# Check the data on subscriber
+my $result = $node_subscriber->safe_psql('postgres', qq(
+SELECT a FROM test;
+));
+
+# Inserted data is replicated correctly
+is( $result, 'one');
-- 
2.11.0

