[PATCH] Add regression tests of ecpg command notice (error / warning)

Started by Ryo Kanbayashi11 months ago14 messages
#1Ryo Kanbayashi
kanbayashi.dev@gmail.com
1 attachment(s)

Hi hackers,

When I wrote patch of ecpg command notice bug, I recognized needs of
regression tests for ecpg command notices and I say that I write the
tests.

https://commitfest.postgresql.org/52/5497/
/messages/by-id/0efab1f6-5d8d-451f-a7dc-ef9c73ba9e02@oss.nttdata.com

This mail is about patch of the tests.

Patch is attached to this mail : ecpg_cmd_notice_regress_test.patch
This patch passed CI.
https://cirrus-ci.com/build/4861827500212224

And corresponding diff is below.
https://github.com/ryogrid/postgres/compare/0ec3c295e7594ed3af86bca1a4b4be269c2f069d...72329311a75630594bcaa38248255360b7e8e525

I explain about implementation of this patch.

What is this patch
- add regression tests which test ecpg command notices such as warning
and errors
- test notices implemented in ecpg.addons file

Basic policy on implementation
- do in a way that matches the method using the existing pg_regress
command as much as possible
- avoid methods that increase the scope of influence

Next, I list answers to points that are likely to be pointed out in
advance below :)
- shell scripts and bat files is used due to ...
avoid non zero exit code of ecpg command makes tests failure
avoid increasing C code for executing binary which cares cross platform
- python code is used because I couldn't write meson.build
appropriately describe dependency about materials which is used on
tests without it. please help me...
- as you said, kick this kind of tests by pg_regress accompanied with
needless PG server process execution. but pg_regress doesn't execute
test without it and making pg_regress require modification which has
not small scope of influence

---
Great regards,
Ryo Kanbayashi
https://github.com/ryogrid

Attachments:

ecpg_cmd_notice_regress_test.patchapplication/x-patch; name=ecpg_cmd_notice_regress_test.patchDownload
diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule
index 254a0bacc75..e1cc61d8c52 100644
--- a/src/interfaces/ecpg/test/ecpg_schedule
+++ b/src/interfaces/ecpg/test/ecpg_schedule
@@ -31,6 +31,8 @@ test: preproc/variable
 test: preproc/outofscope
 test: preproc/whenever
 test: preproc/whenever_do_continue
+test: preproc/notice_check
+test: preproc/notice_informix_check
 test: sql/array
 test: sql/binary
 test: sql/bytea
diff --git a/src/interfaces/ecpg/test/expected/preproc-check_cmd_notice.stderr b/src/interfaces/ecpg/test/expected/preproc-check_cmd_notice.stderr
new file mode 100644
index 00000000000..31bfbc9f3bd
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/preproc-check_cmd_notice.stderr
@@ -0,0 +1,13 @@
+preproc/notice.pgc:16: ERROR: AT option not allowed in CONNECT statement
+preproc/notice.pgc:17: ERROR: AT option not allowed in DISCONNECT statement
+preproc/notice.pgc:18: ERROR: AT option not allowed in SET CONNECTION statement
+preproc/notice.pgc:21: WARNING: COPY FROM STDIN is not implemented
+preproc/notice.pgc:25: ERROR: using variable "cursor_var" in different declare statements is not supported
+preproc/notice.pgc:28: ERROR: cursor "duplicate_cursor" is already defined
+preproc/notice.pgc:31: ERROR: SHOW ALL is not implemented
+preproc/notice.pgc:33: ERROR: AT option not allowed in WHENEVER statement
+preproc/notice.pgc:36: WARNING: no longer supported LIMIT #,# syntax passed to server
+preproc/notice.pgc:39: WARNING: cursor "duplicate_cursor" has been declared but not opened
+preproc/notice.pgc:39: WARNING: cursor "duplicate_cursor" has been declared but not opened
+preproc/notice.pgc:39: WARNING: cursor ":cursor_var" has been declared but not opened
+preproc/notice.pgc:39: WARNING: cursor ":cursor_var" has been declared but not opened
diff --git a/src/interfaces/ecpg/test/expected/preproc-check_cmd_notice_informix.stderr b/src/interfaces/ecpg/test/expected/preproc-check_cmd_notice_informix.stderr
new file mode 100644
index 00000000000..0b9013c126e
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/preproc-check_cmd_notice_informix.stderr
@@ -0,0 +1,2 @@
+preproc/notice_informix.pgc:11: ERROR: AT option not allowed in CLOSE DATABASE statement
+preproc/notice_informix.pgc:14: ERROR: "database" cannot be used as cursor name in INFORMIX mode
diff --git a/src/interfaces/ecpg/test/expected/preproc-notice_check.stderr b/src/interfaces/ecpg/test/expected/preproc-notice_check.stderr
new file mode 100644
index 00000000000..b31076a2527
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/preproc-notice_check.stderr
@@ -0,0 +1,15 @@
+notice.pgc:17: ERROR: AT option not allowed in CONNECT statement
+notice.pgc:18: ERROR: AT option not allowed in DISCONNECT statement
+notice.pgc:19: ERROR: AT option not allowed in SET CONNECTION statement
+notice.pgc:20: ERROR: AT option not allowed in TYPE statement
+notice.pgc:21: ERROR: AT option not allowed in WHENEVER statement
+notice.pgc:22: ERROR: AT option not allowed in VAR statement
+notice.pgc:25: WARNING: COPY FROM STDIN is not implemented
+notice.pgc:29: ERROR: using variable "cursor_var" in different declare statements is not supported
+notice.pgc:33: ERROR: cursor "duplicate_cursor" is already defined
+notice.pgc:36: ERROR: SHOW ALL is not implemented
+notice.pgc:39: WARNING: no longer supported LIMIT #,# syntax passed to server
+notice.pgc:42: WARNING: cursor "duplicate_cursor" has been declared but not opened
+notice.pgc:42: WARNING: cursor "duplicate_cursor" has been declared but not opened
+notice.pgc:42: WARNING: cursor ":cursor_var" has been declared but not opened
+notice.pgc:42: WARNING: cursor ":cursor_var" has been declared but not opened
diff --git a/src/interfaces/ecpg/test/expected/preproc-notice_check.stdout b/src/interfaces/ecpg/test/expected/preproc-notice_check.stdout
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stderr b/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stderr
new file mode 100644
index 00000000000..d6386aaa896
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stderr
@@ -0,0 +1,2 @@
+notice_informix.pgc:12: ERROR: AT option not allowed in CLOSE DATABASE statement
+notice_informix.pgc:15: ERROR: "database" cannot be used as cursor name in INFORMIX mode
diff --git a/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stdout b/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stdout
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/src/interfaces/ecpg/test/pg_regress_ecpg.c b/src/interfaces/ecpg/test/pg_regress_ecpg.c
index ba3477f9dd8..18d8b398a30 100644
--- a/src/interfaces/ecpg/test/pg_regress_ecpg.c
+++ b/src/interfaces/ecpg/test/pg_regress_ecpg.c
@@ -22,6 +22,13 @@
 #include "lib/stringinfo.h"
 #include "pg_regress.h"
 
+#define ECPG_CMD_NOTICE_TEST_PREFIX "preproc/notice"
+
+/*
+ * Tests whose prefix is ECPG_CMD_NOTICE_TEST_PREFIX check ecpg command's notice
+ * such as error or warning. Not checking of compiled ECPG programs behavior.
+ * So, we handle these tests differently.
+ */
 
 /*
  * Create a filtered copy of sourcefile, removing any path
@@ -115,6 +122,9 @@ ecpg_filter_stderr(const char *resultfile, const char *tmpfile)
 	{
 		char	   *p1 = strstr(linebuf.data, "connection to server ");
 
+		/* when ecpg command notice test */
+		char	   *p3 = strstr(linebuf.data, "preproc");
+
 		if (p1)
 		{
 			char	   *p2 = strstr(p1, "failed: ");
@@ -125,6 +135,18 @@ ecpg_filter_stderr(const char *resultfile, const char *tmpfile)
 				/* we don't bother to fix up linebuf.len */
 			}
 		}
+
+		if (p3)
+		{
+			char	   *p4 = strstr(p3, "notice");
+
+			if (p4)
+			{
+				memmove(p3, p4, strlen(p4) + 1);
+				/* we don't bother to fix up linebuf.len */
+			}
+		}
+
 		fputs(linebuf.data, t);
 	}
 
@@ -162,9 +184,7 @@ ecpg_start_test(const char *testname,
 				expectfile_source[MAXPGPATH];
 	char		cmd[MAXPGPATH * 3];
 	char	   *appnameenv;
-
-	snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
-	snprintf(insource, sizeof(insource), "%s/%s.c", inputdir, testname);
+	bool		is_ecpg_cmd_notice_test = false;
 
 	/* make a version of the test name that has dashes in place of slashes */
 	initStringInfo(&testname_dash);
@@ -175,15 +195,38 @@ ecpg_start_test(const char *testname,
 			*c = '-';
 	}
 
+	/* check for ECPG_CMD_NOTICE_TEST_PREFIX literal in the beginning */
+	if (strstr(testname, ECPG_CMD_NOTICE_TEST_PREFIX) == testname)
+	{
+		is_ecpg_cmd_notice_test = true;
+	}
+
+	if (is_ecpg_cmd_notice_test)
+	{
+#ifdef WIN32
+		snprintf(inprg, sizeof(inprg), "%s/%s.bat", inputdir, testname);
+#else
+		snprintf(inprg, sizeof(inprg), "%s/%s.sh", inputdir, testname);
+#endif
+	}
+	else
+	{
+		snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
+		snprintf(insource, sizeof(insource), "%s/%s.c", inputdir, testname);
+	}
+
 	snprintf(expectfile_stdout, sizeof(expectfile_stdout),
 			 "%s/expected/%s.stdout",
 			 expecteddir, testname_dash.data);
 	snprintf(expectfile_stderr, sizeof(expectfile_stderr),
 			 "%s/expected/%s.stderr",
 			 expecteddir, testname_dash.data);
-	snprintf(expectfile_source, sizeof(expectfile_source),
-			 "%s/expected/%s.c",
-			 expecteddir, testname_dash.data);
+	if (!is_ecpg_cmd_notice_test)
+	{
+		snprintf(expectfile_source, sizeof(expectfile_source),
+				 "%s/expected/%s.c",
+				 expecteddir, testname_dash.data);
+	}
 
 	snprintf(outfile_stdout, sizeof(outfile_stdout),
 			 "%s/results/%s.stdout",
@@ -191,9 +234,12 @@ ecpg_start_test(const char *testname,
 	snprintf(outfile_stderr, sizeof(outfile_stderr),
 			 "%s/results/%s.stderr",
 			 outputdir, testname_dash.data);
-	snprintf(outfile_source, sizeof(outfile_source),
-			 "%s/results/%s.c",
-			 outputdir, testname_dash.data);
+	if (!is_ecpg_cmd_notice_test)
+	{
+		snprintf(outfile_source, sizeof(outfile_source),
+				 "%s/results/%s.c",
+				 outputdir, testname_dash.data);
+	}
 
 	add_stringlist_item(resultfiles, outfile_stdout);
 	add_stringlist_item(expectfiles, expectfile_stdout);
@@ -203,11 +249,18 @@ ecpg_start_test(const char *testname,
 	add_stringlist_item(expectfiles, expectfile_stderr);
 	add_stringlist_item(tags, "stderr");
 
-	add_stringlist_item(resultfiles, outfile_source);
-	add_stringlist_item(expectfiles, expectfile_source);
-	add_stringlist_item(tags, "source");
+	if (!is_ecpg_cmd_notice_test)
+	{
+		add_stringlist_item(resultfiles, outfile_source);
+		add_stringlist_item(expectfiles, expectfile_source);
+		add_stringlist_item(tags, "source");
+
+		ecpg_filter_source(insource, outfile_source);
+	}
 
-	ecpg_filter_source(insource, outfile_source);
+	appnameenv = psprintf("ecpg/%s", testname_dash.data);
+	setenv("PGAPPNAME", appnameenv, 1);
+	free(appnameenv);
 
 	snprintf(cmd, sizeof(cmd),
 			 "\"%s\" >\"%s\" 2>\"%s\"",
@@ -215,10 +268,6 @@ ecpg_start_test(const char *testname,
 			 outfile_stdout,
 			 outfile_stderr);
 
-	appnameenv = psprintf("ecpg/%s", testname_dash.data);
-	setenv("PGAPPNAME", appnameenv, 1);
-	free(appnameenv);
-
 	pid = spawn_process(cmd);
 
 	if (pid == INVALID_PID)
diff --git a/src/interfaces/ecpg/test/preproc/copy_files.py b/src/interfaces/ecpg/test/preproc/copy_files.py
new file mode 100644
index 00000000000..8678c86e1cd
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/copy_files.py
@@ -0,0 +1,21 @@
+import shutil
+import os
+import sys
+
+def main():
+    if len(sys.argv) < 4:
+        print("Usage: python copy_files.py <src_base> <destination_base> <file1> <file2> ...")
+        sys.exit(1)
+
+    src = sys.argv[1]
+    destination = sys.argv[2]
+    files = sys.argv[3:]
+
+    for file in files:
+        src_path = os.path.join(src, os.path.basename(file))
+        dest_path = os.path.join(destination, os.path.basename(file))
+
+        shutil.copy2(src_path, dest_path)
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/meson.build b/src/interfaces/ecpg/test/preproc/meson.build
index 775502e0102..26bef1f2e73 100644
--- a/src/interfaces/ecpg/test/preproc/meson.build
+++ b/src/interfaces/ecpg/test/preproc/meson.build
@@ -37,3 +37,31 @@ foreach pgc_file : pgc_files
     kwargs: ecpg_test_exec_kw,
   )
 endforeach
+
+# copy materials for ecpg command notice test
+copy_materials = [
+  'notice.pgc',
+  'notice_informix.pgc',
+  'notice_check.bat',
+  'notice_check.sh',
+  'notice_informix_check.bat',
+  'notice_informix_check.sh',
+]
+
+copy_cmdline = [
+  python,
+  meson.current_source_dir() / 'copy_files.py',
+  meson.current_source_dir(),
+  meson.current_build_dir()
+]
+
+foreach file : copy_materials
+  copy_cmdline += file
+endforeach
+
+ecpg_test_dependencies += custom_target('copy_ecpg_test_materials',
+  input: meson.current_source_dir() / 'copy_files.py',
+  output: copy_materials,
+  command: copy_cmdline,
+  build_by_default: false,
+)
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice.pgc b/src/interfaces/ecpg/test/preproc/notice.pgc
new file mode 100644
index 00000000000..03a4f60d5e2
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice.pgc
@@ -0,0 +1,42 @@
+/* Test ECPG notice/warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+    EXEC SQL BEGIN DECLARE SECTION;
+    char *cursor_var = "mycursor";
+    short a;
+    EXEC SQL END DECLARE SECTION;
+
+    /* For consistency with other tests */
+    EXEC SQL CONNECT TO testdb AS con1;
+
+    /* Test AT option errors */
+    EXEC SQL AT con1 CONNECT TO testdb2;
+    EXEC SQL AT con1 DISCONNECT;
+    EXEC SQL AT con1 SET CONNECTION TO testdb2;
+    EXEC SQL AT con1 TYPE string IS char[11];
+    EXEC SQL AT con1 WHENEVER NOT FOUND CONTINUE;
+    EXEC SQL AT con1 VAR a IS int;
+
+    /* Test COPY FROM STDIN warning */
+    EXEC SQL COPY test FROM stdin;
+
+    /* Test same variable in multi declare statement */
+    EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+    EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+
+    /* Test duplicate cursor declarations */
+    EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+    EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+
+    /* Test SHOW ALL error */
+    EXEC SQL SHOW ALL;
+
+    /* Test deprecated LIMIT syntax warning */
+    EXEC SQL SELECT * FROM test LIMIT 10, 5;
+
+    return 0;
+}
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice_check.bat b/src/interfaces/ecpg/test/preproc/notice_check.bat
new file mode 100644
index 00000000000..172950897db
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_check.bat
@@ -0,0 +1,7 @@
+@echo off
+
+PATH=..\preproc\;%PATH%
+ecpg -o preproc\notice.c preproc\notice.pgc
+
+REM always return 0 for test purposes
+exit /b 0
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice_check.sh b/src/interfaces/ecpg/test/preproc/notice_check.sh
new file mode 100755
index 00000000000..11338bb3ede
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_check.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+PATH=../preproc/:$PATH
+ecpg -c -o preproc/notice.c preproc/notice.pgc
+
+# always return 0 for testing purposes
+exit 0
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice_informix.pgc b/src/interfaces/ecpg/test/preproc/notice_informix.pgc
new file mode 100644
index 00000000000..18281f3b9ee
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_informix.pgc
@@ -0,0 +1,18 @@
+/* Test ECPG notice/warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+    /* For consistency with other tests */
+    $CONNECT TO testdb AS con1;
+
+    /* Test AT option usage at CLOSE statement in INFORMIX mode */
+    $AT con1 CLOSE database;
+
+    /* Test cursor name errors in INFORMIX mode */
+    $DECLARE database CURSOR FOR SELECT * FROM test;
+
+    return 0;
+}
diff --git a/src/interfaces/ecpg/test/preproc/notice_informix_check.bat b/src/interfaces/ecpg/test/preproc/notice_informix_check.bat
new file mode 100644
index 00000000000..fd66da3b67e
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_informix_check.bat
@@ -0,0 +1,7 @@
+@echo off
+
+PATH=..\preproc\;%PATH%
+ecpg -C INFORMIX -o preproc\notice_informix.c preproc\notice_informix.pgc
+
+REM always return 0 for test purposes
+exit /b 0
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice_informix_check.sh b/src/interfaces/ecpg/test/preproc/notice_informix_check.sh
new file mode 100755
index 00000000000..ef543e1082e
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_informix_check.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+PATH=../preproc/:$PATH
+ecpg -C INFORMIX -o preproc/notice_informix.c preproc/notice_informix.pgc
+
+# always return 0 for testing purposes
+exit 0
\ No newline at end of file
#2Ryo Kanbayashi
kanbayashi.dev@gmail.com
In reply to: Ryo Kanbayashi (#1)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On Wed, Feb 5, 2025 at 9:31 PM Ryo Kanbayashi <kanbayashi.dev@gmail.com> wrote:

Hi hackers,

When I wrote patch of ecpg command notice bug, I recognized needs of
regression tests for ecpg command notices and I say that I write the
tests.

https://commitfest.postgresql.org/52/5497/
/messages/by-id/0efab1f6-5d8d-451f-a7dc-ef9c73ba9e02@oss.nttdata.com

This mail is about patch of the tests.

Patch is attached to this mail : ecpg_cmd_notice_regress_test.patch
This patch passed CI.
https://cirrus-ci.com/build/4861827500212224

And corresponding diff is below.
https://github.com/ryogrid/postgres/compare/0ec3c295e7594ed3af86bca1a4b4be269c2f069d...72329311a75630594bcaa38248255360b7e8e525

I explain about implementation of this patch.

What is this patch
- add regression tests which test ecpg command notices such as warning
and errors
- test notices implemented in ecpg.addons file

Basic policy on implementation
- do in a way that matches the method using the existing pg_regress
command as much as possible
- avoid methods that increase the scope of influence

Next, I list answers to points that are likely to be pointed out in
advance below :)
- shell scripts and bat files is used due to ...
avoid non zero exit code of ecpg command makes tests failure
avoid increasing C code for executing binary which cares cross platform
- python code is used because I couldn't write meson.build
appropriately describe dependency about materials which is used on
tests without it. please help me...
- as you said, kick this kind of tests by pg_regress accompanied with
needless PG server process execution. but pg_regress doesn't execute
test without it and making pg_regress require modification which has
not small scope of influence

Sorry, I re-send patch because a patch already sent includes needless
stderr output file.
NEW PATCH FILENAME: ecpg_cmd_notice_regress_test2.patch

In addition, diff between patches does not affect test behavior.

---
Sincerely,
Ryo Kanbayashi
https://github.com/ryogrid

#3Ryo Kanbayashi
kanbayashi.dev@gmail.com
In reply to: Ryo Kanbayashi (#2)
1 attachment(s)
Fwd: [PATCH] Add regression tests of ecpg command notice (error / warning)

On Wed, Feb 5, 2025 at 9:31 PM Ryo Kanbayashi <kanbayashi.dev@gmail.com> wrote:

Hi hackers,

When I wrote patch of ecpg command notice bug, I recognized needs of
regression tests for ecpg command notices and I say that I write the
tests.

https://commitfest.postgresql.org/52/5497/
/messages/by-id/0efab1f6-5d8d-451f-a7dc-ef9c73ba9e02@oss.nttdata.com

This mail is about patch of the tests.

Patch is attached to this mail : ecpg_cmd_notice_regress_test.patch
This patch passed CI.
https://cirrus-ci.com/build/4861827500212224

And corresponding diff is below.
https://github.com/ryogrid/postgres/compare/0ec3c295e7594ed3af86bca1a4b4be269c2f069d...72329311a75630594bcaa38248255360b7e8e525

I explain about implementation of this patch.

What is this patch
- add regression tests which test ecpg command notices such as warning
and errors
- test notices implemented in ecpg.addons file

Basic policy on implementation
- do in a way that matches the method using the existing pg_regress
command as much as possible
- avoid methods that increase the scope of influence

Next, I list answers to points that are likely to be pointed out in
advance below :)
- shell scripts and bat files is used due to ...
avoid non zero exit code of ecpg command makes tests failure
avoid increasing C code for executing binary which cares cross platform
- python code is used because I couldn't write meson.build
appropriately describe dependency about materials which is used on
tests without it. please help me...
- as you said, kick this kind of tests by pg_regress accompanied with
needless PG server process execution. but pg_regress doesn't execute
test without it and making pg_regress require modification which has
not small scope of influence

Sorry, I re-send patch because a patch already sent includes needless
stderr output file.
NEW PATCH FILENAME: ecpg_cmd_notice_regress_test2.patch

In addition, diff between patches does not affect test behavior.

---
Sincerely,
Ryo Kanbayashi
https://github.com/ryogrid

Attachments:

ecpg_cmd_notice_regress_test2.patchapplication/octet-stream; name=ecpg_cmd_notice_regress_test2.patchDownload
diff --git a/src/interfaces/ecpg/test/ecpg_schedule b/src/interfaces/ecpg/test/ecpg_schedule
index 254a0bacc75..e1cc61d8c52 100644
--- a/src/interfaces/ecpg/test/ecpg_schedule
+++ b/src/interfaces/ecpg/test/ecpg_schedule
@@ -31,6 +31,8 @@ test: preproc/variable
 test: preproc/outofscope
 test: preproc/whenever
 test: preproc/whenever_do_continue
+test: preproc/notice_check
+test: preproc/notice_informix_check
 test: sql/array
 test: sql/binary
 test: sql/bytea
diff --git a/src/interfaces/ecpg/test/expected/preproc-notice_check.stderr b/src/interfaces/ecpg/test/expected/preproc-notice_check.stderr
new file mode 100644
index 00000000000..b31076a2527
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/preproc-notice_check.stderr
@@ -0,0 +1,15 @@
+notice.pgc:17: ERROR: AT option not allowed in CONNECT statement
+notice.pgc:18: ERROR: AT option not allowed in DISCONNECT statement
+notice.pgc:19: ERROR: AT option not allowed in SET CONNECTION statement
+notice.pgc:20: ERROR: AT option not allowed in TYPE statement
+notice.pgc:21: ERROR: AT option not allowed in WHENEVER statement
+notice.pgc:22: ERROR: AT option not allowed in VAR statement
+notice.pgc:25: WARNING: COPY FROM STDIN is not implemented
+notice.pgc:29: ERROR: using variable "cursor_var" in different declare statements is not supported
+notice.pgc:33: ERROR: cursor "duplicate_cursor" is already defined
+notice.pgc:36: ERROR: SHOW ALL is not implemented
+notice.pgc:39: WARNING: no longer supported LIMIT #,# syntax passed to server
+notice.pgc:42: WARNING: cursor "duplicate_cursor" has been declared but not opened
+notice.pgc:42: WARNING: cursor "duplicate_cursor" has been declared but not opened
+notice.pgc:42: WARNING: cursor ":cursor_var" has been declared but not opened
+notice.pgc:42: WARNING: cursor ":cursor_var" has been declared but not opened
diff --git a/src/interfaces/ecpg/test/expected/preproc-notice_check.stdout b/src/interfaces/ecpg/test/expected/preproc-notice_check.stdout
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stderr b/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stderr
new file mode 100644
index 00000000000..d6386aaa896
--- /dev/null
+++ b/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stderr
@@ -0,0 +1,2 @@
+notice_informix.pgc:12: ERROR: AT option not allowed in CLOSE DATABASE statement
+notice_informix.pgc:15: ERROR: "database" cannot be used as cursor name in INFORMIX mode
diff --git a/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stdout b/src/interfaces/ecpg/test/expected/preproc-notice_informix_check.stdout
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/src/interfaces/ecpg/test/pg_regress_ecpg.c b/src/interfaces/ecpg/test/pg_regress_ecpg.c
index ba3477f9dd8..18d8b398a30 100644
--- a/src/interfaces/ecpg/test/pg_regress_ecpg.c
+++ b/src/interfaces/ecpg/test/pg_regress_ecpg.c
@@ -22,6 +22,13 @@
 #include "lib/stringinfo.h"
 #include "pg_regress.h"
 
+#define ECPG_CMD_NOTICE_TEST_PREFIX "preproc/notice"
+
+/*
+ * Tests whose prefix is ECPG_CMD_NOTICE_TEST_PREFIX check ecpg command's notice
+ * such as error or warning. Not checking of compiled ECPG programs behavior.
+ * So, we handle these tests differently.
+ */
 
 /*
  * Create a filtered copy of sourcefile, removing any path
@@ -115,6 +122,9 @@ ecpg_filter_stderr(const char *resultfile, const char *tmpfile)
 	{
 		char	   *p1 = strstr(linebuf.data, "connection to server ");
 
+		/* when ecpg command notice test */
+		char	   *p3 = strstr(linebuf.data, "preproc");
+
 		if (p1)
 		{
 			char	   *p2 = strstr(p1, "failed: ");
@@ -125,6 +135,18 @@ ecpg_filter_stderr(const char *resultfile, const char *tmpfile)
 				/* we don't bother to fix up linebuf.len */
 			}
 		}
+
+		if (p3)
+		{
+			char	   *p4 = strstr(p3, "notice");
+
+			if (p4)
+			{
+				memmove(p3, p4, strlen(p4) + 1);
+				/* we don't bother to fix up linebuf.len */
+			}
+		}
+
 		fputs(linebuf.data, t);
 	}
 
@@ -162,9 +184,7 @@ ecpg_start_test(const char *testname,
 				expectfile_source[MAXPGPATH];
 	char		cmd[MAXPGPATH * 3];
 	char	   *appnameenv;
-
-	snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
-	snprintf(insource, sizeof(insource), "%s/%s.c", inputdir, testname);
+	bool		is_ecpg_cmd_notice_test = false;
 
 	/* make a version of the test name that has dashes in place of slashes */
 	initStringInfo(&testname_dash);
@@ -175,15 +195,38 @@ ecpg_start_test(const char *testname,
 			*c = '-';
 	}
 
+	/* check for ECPG_CMD_NOTICE_TEST_PREFIX literal in the beginning */
+	if (strstr(testname, ECPG_CMD_NOTICE_TEST_PREFIX) == testname)
+	{
+		is_ecpg_cmd_notice_test = true;
+	}
+
+	if (is_ecpg_cmd_notice_test)
+	{
+#ifdef WIN32
+		snprintf(inprg, sizeof(inprg), "%s/%s.bat", inputdir, testname);
+#else
+		snprintf(inprg, sizeof(inprg), "%s/%s.sh", inputdir, testname);
+#endif
+	}
+	else
+	{
+		snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname);
+		snprintf(insource, sizeof(insource), "%s/%s.c", inputdir, testname);
+	}
+
 	snprintf(expectfile_stdout, sizeof(expectfile_stdout),
 			 "%s/expected/%s.stdout",
 			 expecteddir, testname_dash.data);
 	snprintf(expectfile_stderr, sizeof(expectfile_stderr),
 			 "%s/expected/%s.stderr",
 			 expecteddir, testname_dash.data);
-	snprintf(expectfile_source, sizeof(expectfile_source),
-			 "%s/expected/%s.c",
-			 expecteddir, testname_dash.data);
+	if (!is_ecpg_cmd_notice_test)
+	{
+		snprintf(expectfile_source, sizeof(expectfile_source),
+				 "%s/expected/%s.c",
+				 expecteddir, testname_dash.data);
+	}
 
 	snprintf(outfile_stdout, sizeof(outfile_stdout),
 			 "%s/results/%s.stdout",
@@ -191,9 +234,12 @@ ecpg_start_test(const char *testname,
 	snprintf(outfile_stderr, sizeof(outfile_stderr),
 			 "%s/results/%s.stderr",
 			 outputdir, testname_dash.data);
-	snprintf(outfile_source, sizeof(outfile_source),
-			 "%s/results/%s.c",
-			 outputdir, testname_dash.data);
+	if (!is_ecpg_cmd_notice_test)
+	{
+		snprintf(outfile_source, sizeof(outfile_source),
+				 "%s/results/%s.c",
+				 outputdir, testname_dash.data);
+	}
 
 	add_stringlist_item(resultfiles, outfile_stdout);
 	add_stringlist_item(expectfiles, expectfile_stdout);
@@ -203,11 +249,18 @@ ecpg_start_test(const char *testname,
 	add_stringlist_item(expectfiles, expectfile_stderr);
 	add_stringlist_item(tags, "stderr");
 
-	add_stringlist_item(resultfiles, outfile_source);
-	add_stringlist_item(expectfiles, expectfile_source);
-	add_stringlist_item(tags, "source");
+	if (!is_ecpg_cmd_notice_test)
+	{
+		add_stringlist_item(resultfiles, outfile_source);
+		add_stringlist_item(expectfiles, expectfile_source);
+		add_stringlist_item(tags, "source");
+
+		ecpg_filter_source(insource, outfile_source);
+	}
 
-	ecpg_filter_source(insource, outfile_source);
+	appnameenv = psprintf("ecpg/%s", testname_dash.data);
+	setenv("PGAPPNAME", appnameenv, 1);
+	free(appnameenv);
 
 	snprintf(cmd, sizeof(cmd),
 			 "\"%s\" >\"%s\" 2>\"%s\"",
@@ -215,10 +268,6 @@ ecpg_start_test(const char *testname,
 			 outfile_stdout,
 			 outfile_stderr);
 
-	appnameenv = psprintf("ecpg/%s", testname_dash.data);
-	setenv("PGAPPNAME", appnameenv, 1);
-	free(appnameenv);
-
 	pid = spawn_process(cmd);
 
 	if (pid == INVALID_PID)
diff --git a/src/interfaces/ecpg/test/preproc/copy_files.py b/src/interfaces/ecpg/test/preproc/copy_files.py
new file mode 100644
index 00000000000..8678c86e1cd
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/copy_files.py
@@ -0,0 +1,21 @@
+import shutil
+import os
+import sys
+
+def main():
+    if len(sys.argv) < 4:
+        print("Usage: python copy_files.py <src_base> <destination_base> <file1> <file2> ...")
+        sys.exit(1)
+
+    src = sys.argv[1]
+    destination = sys.argv[2]
+    files = sys.argv[3:]
+
+    for file in files:
+        src_path = os.path.join(src, os.path.basename(file))
+        dest_path = os.path.join(destination, os.path.basename(file))
+
+        shutil.copy2(src_path, dest_path)
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/meson.build b/src/interfaces/ecpg/test/preproc/meson.build
index 775502e0102..26bef1f2e73 100644
--- a/src/interfaces/ecpg/test/preproc/meson.build
+++ b/src/interfaces/ecpg/test/preproc/meson.build
@@ -37,3 +37,31 @@ foreach pgc_file : pgc_files
     kwargs: ecpg_test_exec_kw,
   )
 endforeach
+
+# copy materials for ecpg command notice test
+copy_materials = [
+  'notice.pgc',
+  'notice_informix.pgc',
+  'notice_check.bat',
+  'notice_check.sh',
+  'notice_informix_check.bat',
+  'notice_informix_check.sh',
+]
+
+copy_cmdline = [
+  python,
+  meson.current_source_dir() / 'copy_files.py',
+  meson.current_source_dir(),
+  meson.current_build_dir()
+]
+
+foreach file : copy_materials
+  copy_cmdline += file
+endforeach
+
+ecpg_test_dependencies += custom_target('copy_ecpg_test_materials',
+  input: meson.current_source_dir() / 'copy_files.py',
+  output: copy_materials,
+  command: copy_cmdline,
+  build_by_default: false,
+)
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice.pgc b/src/interfaces/ecpg/test/preproc/notice.pgc
new file mode 100644
index 00000000000..03a4f60d5e2
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice.pgc
@@ -0,0 +1,42 @@
+/* Test ECPG notice/warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+    EXEC SQL BEGIN DECLARE SECTION;
+    char *cursor_var = "mycursor";
+    short a;
+    EXEC SQL END DECLARE SECTION;
+
+    /* For consistency with other tests */
+    EXEC SQL CONNECT TO testdb AS con1;
+
+    /* Test AT option errors */
+    EXEC SQL AT con1 CONNECT TO testdb2;
+    EXEC SQL AT con1 DISCONNECT;
+    EXEC SQL AT con1 SET CONNECTION TO testdb2;
+    EXEC SQL AT con1 TYPE string IS char[11];
+    EXEC SQL AT con1 WHENEVER NOT FOUND CONTINUE;
+    EXEC SQL AT con1 VAR a IS int;
+
+    /* Test COPY FROM STDIN warning */
+    EXEC SQL COPY test FROM stdin;
+
+    /* Test same variable in multi declare statement */
+    EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+    EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+
+    /* Test duplicate cursor declarations */
+    EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+    EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+
+    /* Test SHOW ALL error */
+    EXEC SQL SHOW ALL;
+
+    /* Test deprecated LIMIT syntax warning */
+    EXEC SQL SELECT * FROM test LIMIT 10, 5;
+
+    return 0;
+}
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice_check.bat b/src/interfaces/ecpg/test/preproc/notice_check.bat
new file mode 100644
index 00000000000..172950897db
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_check.bat
@@ -0,0 +1,7 @@
+@echo off
+
+PATH=..\preproc\;%PATH%
+ecpg -o preproc\notice.c preproc\notice.pgc
+
+REM always return 0 for test purposes
+exit /b 0
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice_check.sh b/src/interfaces/ecpg/test/preproc/notice_check.sh
new file mode 100755
index 00000000000..11338bb3ede
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_check.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+PATH=../preproc/:$PATH
+ecpg -c -o preproc/notice.c preproc/notice.pgc
+
+# always return 0 for testing purposes
+exit 0
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice_informix.pgc b/src/interfaces/ecpg/test/preproc/notice_informix.pgc
new file mode 100644
index 00000000000..18281f3b9ee
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_informix.pgc
@@ -0,0 +1,18 @@
+/* Test ECPG notice/warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+    /* For consistency with other tests */
+    $CONNECT TO testdb AS con1;
+
+    /* Test AT option usage at CLOSE statement in INFORMIX mode */
+    $AT con1 CLOSE database;
+
+    /* Test cursor name errors in INFORMIX mode */
+    $DECLARE database CURSOR FOR SELECT * FROM test;
+
+    return 0;
+}
diff --git a/src/interfaces/ecpg/test/preproc/notice_informix_check.bat b/src/interfaces/ecpg/test/preproc/notice_informix_check.bat
new file mode 100644
index 00000000000..fd66da3b67e
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_informix_check.bat
@@ -0,0 +1,7 @@
+@echo off
+
+PATH=..\preproc\;%PATH%
+ecpg -C INFORMIX -o preproc\notice_informix.c preproc\notice_informix.pgc
+
+REM always return 0 for test purposes
+exit /b 0
\ No newline at end of file
diff --git a/src/interfaces/ecpg/test/preproc/notice_informix_check.sh b/src/interfaces/ecpg/test/preproc/notice_informix_check.sh
new file mode 100755
index 00000000000..ef543e1082e
--- /dev/null
+++ b/src/interfaces/ecpg/test/preproc/notice_informix_check.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+PATH=../preproc/:$PATH
+ecpg -C INFORMIX -o preproc/notice_informix.c preproc/notice_informix.pgc
+
+# always return 0 for testing purposes
+exit 0
\ No newline at end of file
#4Fujii Masao
masao.fujii@oss.nttdata.com
In reply to: Ryo Kanbayashi (#2)
1 attachment(s)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On 2025/02/06 8:57, Ryo Kanbayashi wrote:

On Wed, Feb 5, 2025 at 9:31 PM Ryo Kanbayashi <kanbayashi.dev@gmail.com> wrote:

Hi hackers,

When I wrote patch of ecpg command notice bug, I recognized needs of
regression tests for ecpg command notices and I say that I write the
tests.

Thanks for working on this!

I explain about implementation of this patch.

What is this patch
- add regression tests which test ecpg command notices such as warning
and errors
- test notices implemented in ecpg.addons file

Basic policy on implementation
- do in a way that matches the method using the existing pg_regress
command as much as possible
- avoid methods that increase the scope of influence

Next, I list answers to points that are likely to be pointed out in
advance below :)
- shell scripts and bat files is used due to ...
avoid non zero exit code of ecpg command makes tests failure
avoid increasing C code for executing binary which cares cross platform
- python code is used because I couldn't write meson.build
appropriately describe dependency about materials which is used on
tests without it. please help me...
- as you said, kick this kind of tests by pg_regress accompanied with
needless PG server process execution. but pg_regress doesn't execute
test without it and making pg_regress require modification which has
not small scope of influence

Wouldn't it be simpler to use the existing TAP test mechanism,
as shown in the attached patch? Please note that this patch is very WIP,
so there would be many places that need further implementation and refinement.

Regards,

--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION

Attachments:

WIP_ecpg_test_v1.patchtext/plain; charset=UTF-8; name=WIP_ecpg_test_v1.patchDownload
diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile
index 84199a9a5d..d0e3852a87 100644
--- a/src/interfaces/ecpg/preproc/Makefile
+++ b/src/interfaces/ecpg/preproc/Makefile
@@ -81,6 +81,9 @@ ecpg_keywords.o: ecpg_kwlist_d.h
 c_keywords.o: c_kwlist_d.h
 keywords.o: $(top_srcdir)/src/include/parser/kwlist.h
 
+check:
+	$(prove_check)
+
 install: all installdirs
 	$(INSTALL_PROGRAM) ecpg$(X) '$(DESTDIR)$(bindir)'
 
diff --git a/src/interfaces/ecpg/preproc/t/001_ecpg.pl b/src/interfaces/ecpg/preproc/t/001_ecpg.pl
new file mode 100644
index 0000000000..bc52d19a7f
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/001_ecpg.pl
@@ -0,0 +1,37 @@
+
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');
+
+command_checks_all(
+	[ 'ecpg', 't/notice.pgc' ],
+	3,
+	[qr//],
+	[
+		qr/ERROR: AT option not allowed in CONNECT statement/,
+		qr/ERROR: AT option not allowed in DISCONNECT statement/,
+		qr/ERROR: AT option not allowed in SET CONNECTION statement/,
+		qr/ERROR: AT option not allowed in TYPE statement/,
+		qr/ERROR: AT option not allowed in WHENEVER statement/,
+		qr/ERROR: AT option not allowed in VAR statement/,
+		qr/WARNING: COPY FROM STDIN is not implemented/,
+		qr/ERROR: using variable "cursor_var" in different declare statements is not supported/,
+		qr/ERROR: cursor "duplicate_cursor" is already defined/,
+		qr/ERROR: SHOW ALL is not implemented/,
+		qr/WARNING: no longer supported LIMIT/,
+		qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/,
+		qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/,
+		qr/WARNING: cursor ":cursor_var" has been declared but not opened/,
+		qr/WARNING: cursor ":cursor_var" has been declared but not opened/
+	],
+	'ecpg with warnings');
+
+done_testing();
diff --git a/src/interfaces/ecpg/preproc/t/notice.pgc b/src/interfaces/ecpg/preproc/t/notice.pgc
new file mode 100644
index 0000000000..7e54627fcb
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/notice.pgc
@@ -0,0 +1,42 @@
+/* Test ECPG notice/warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+	EXEC SQL BEGIN DECLARE SECTION;
+	char *cursor_var = "mycursor";
+	short a;
+	EXEC SQL END DECLARE SECTION;
+
+	/* For consistency with other tests */
+	EXEC SQL CONNECT TO testdb AS con1;
+
+	/* Test AT option errors */
+	EXEC SQL AT con1 CONNECT TO testdb2;
+	EXEC SQL AT con1 DISCONNECT;
+	EXEC SQL AT con1 SET CONNECTION TO testdb2;
+	EXEC SQL AT con1 TYPE string IS char[11];
+	EXEC SQL AT con1 WHENEVER NOT FOUND CONTINUE;
+	EXEC SQL AT con1 VAR a IS int;
+
+	/* Test COPY FROM STDIN warning */
+	EXEC SQL COPY test FROM stdin;
+
+	/* Test same variable in multi declare statement */
+	EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+	EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+
+	/* Test duplicate cursor declarations */
+	EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+	EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+
+	/* Test SHOW ALL error */
+	EXEC SQL SHOW ALL;
+
+	/* Test deprecated LIMIT syntax warning */
+	EXEC SQL SELECT * FROM test LIMIT 10, 5;
+
+	return 0;
+}
#5Ryo Kanbayashi
kanbayashi.dev@gmail.com
In reply to: Fujii Masao (#4)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On Thu, Feb 13, 2025 at 10:49 PM Fujii Masao
<masao.fujii@oss.nttdata.com> wrote:

On 2025/02/06 8:57, Ryo Kanbayashi wrote:

On Wed, Feb 5, 2025 at 9:31 PM Ryo Kanbayashi <kanbayashi.dev@gmail.com> wrote:

Hi hackers,

When I wrote patch of ecpg command notice bug, I recognized needs of
regression tests for ecpg command notices and I say that I write the
tests.

Thanks for working on this!

I explain about implementation of this patch.

What is this patch
- add regression tests which test ecpg command notices such as warning
and errors
- test notices implemented in ecpg.addons file

Basic policy on implementation
- do in a way that matches the method using the existing pg_regress
command as much as possible
- avoid methods that increase the scope of influence

Next, I list answers to points that are likely to be pointed out in
advance below :)
- shell scripts and bat files is used due to ...
avoid non zero exit code of ecpg command makes tests failure
avoid increasing C code for executing binary which cares cross platform
- python code is used because I couldn't write meson.build
appropriately describe dependency about materials which is used on
tests without it. please help me...
- as you said, kick this kind of tests by pg_regress accompanied with
needless PG server process execution. but pg_regress doesn't execute
test without it and making pg_regress require modification which has
not small scope of influence

Wouldn't it be simpler to use the existing TAP test mechanism,
as shown in the attached patch? Please note that this patch is very WIP,
so there would be many places that need further implementation and refinement.

Fujii San,

Thank you for reviewing and indication of better implementation.
I rewrite my patch based on your reference implementation :)

---
Great regards,
Ryo Kanbayashi
NTT Open Source Software Center

#6Ryo Kanbayashi
kanbayashi.dev@gmail.com
In reply to: Ryo Kanbayashi (#5)
1 attachment(s)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On Tue, Feb 18, 2025 at 12:49 PM Ryo Kanbayashi
<kanbayashi.dev@gmail.com> wrote:

On Thu, Feb 13, 2025 at 10:49 PM Fujii Masao
<masao.fujii@oss.nttdata.com> wrote:

On 2025/02/06 8:57, Ryo Kanbayashi wrote:

On Wed, Feb 5, 2025 at 9:31 PM Ryo Kanbayashi <kanbayashi.dev@gmail.com> wrote:

Hi hackers,

When I wrote patch of ecpg command notice bug, I recognized needs of
regression tests for ecpg command notices and I say that I write the
tests.

Thanks for working on this!

I explain about implementation of this patch.

What is this patch
- add regression tests which test ecpg command notices such as warning
and errors
- test notices implemented in ecpg.addons file

Basic policy on implementation
- do in a way that matches the method using the existing pg_regress
command as much as possible
- avoid methods that increase the scope of influence

Next, I list answers to points that are likely to be pointed out in
advance below :)
- shell scripts and bat files is used due to ...
avoid non zero exit code of ecpg command makes tests failure
avoid increasing C code for executing binary which cares cross platform
- python code is used because I couldn't write meson.build
appropriately describe dependency about materials which is used on
tests without it. please help me...
- as you said, kick this kind of tests by pg_regress accompanied with
needless PG server process execution. but pg_regress doesn't execute
test without it and making pg_regress require modification which has
not small scope of influence

Wouldn't it be simpler to use the existing TAP test mechanism,
as shown in the attached patch? Please note that this patch is very WIP,
so there would be many places that need further implementation and refinement.

Fujii San,

Thank you for reviewing and indication of better implementation.
I rewrite my patch based on your reference implementation :)

Fujii San and other hackers,

I have rewrote my patch on TAP test sttyle :)
File for build are also updated.

Commitfest entry:
https://commitfest.postgresql.org/patch/5543/

---
Great regards,
Ryo Kanbayashi
NTT Open Source Software Center

Attachments:

ecpg-notice-regress-patch-tap-ver.patchapplication/octet-stream; name=ecpg-notice-regress-patch-tap-ver.patchDownload
diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile
index 84199a9a5d..d0e3852a87 100644
--- a/src/interfaces/ecpg/preproc/Makefile
+++ b/src/interfaces/ecpg/preproc/Makefile
@@ -81,6 +81,9 @@ ecpg_keywords.o: ecpg_kwlist_d.h
 c_keywords.o: c_kwlist_d.h
 keywords.o: $(top_srcdir)/src/include/parser/kwlist.h
 
+check:
+	$(prove_check)
+
 install: all installdirs
 	$(INSTALL_PROGRAM) ecpg$(X) '$(DESTDIR)$(bindir)'
 
diff --git a/src/interfaces/ecpg/preproc/meson.build b/src/interfaces/ecpg/preproc/meson.build
index bfd0ed2efb..223d4e800c 100644
--- a/src/interfaces/ecpg/preproc/meson.build
+++ b/src/interfaces/ecpg/preproc/meson.build
@@ -86,3 +86,16 @@ ecpg_exe = executable('ecpg',
 ecpg_targets += ecpg_exe
 
 subdir('po', if_found: libintl)
+
+tests += {
+  'name': 'ecpg',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tap': {
+    'tests': [
+      't/001_ecpg_notice.pl',
+      't/002_ecpg_notice_informix.pl',
+    ],
+    'deps': ecpg_exe,
+  },
+}
\ No newline at end of file
diff --git a/src/interfaces/ecpg/preproc/t/001_ecpg_notice.pl b/src/interfaces/ecpg/preproc/t/001_ecpg_notice.pl
new file mode 100644
index 0000000000..320bd38264
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/001_ecpg_notice.pl
@@ -0,0 +1,37 @@
+
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');
+
+command_checks_all(
+	[ 'ecpg', 't/notice.pgc' ],
+	3,
+	[qr//],
+	[
+		qr/ERROR: AT option not allowed in CONNECT statement/,
+		qr/ERROR: AT option not allowed in DISCONNECT statement/,
+		qr/ERROR: AT option not allowed in SET CONNECTION statement/,
+		qr/ERROR: AT option not allowed in TYPE statement/,
+		qr/ERROR: AT option not allowed in WHENEVER statement/,
+		qr/ERROR: AT option not allowed in VAR statement/,
+		qr/WARNING: COPY FROM STDIN is not implemented/,
+		qr/ERROR: using variable "cursor_var" in different declare statements is not supported/,
+		qr/ERROR: cursor "duplicate_cursor" is already defined/,
+		qr/ERROR: SHOW ALL is not implemented/,
+		qr/WARNING: no longer supported LIMIT/,
+		qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/,
+		qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/,
+		qr/WARNING: cursor ":cursor_var" has been declared but not opened/,
+		qr/WARNING: cursor ":cursor_var" has been declared but not opened/
+	],
+	'ecpg with erros and warnings');
+
+done_testing();
diff --git a/src/interfaces/ecpg/preproc/t/002_ecpg_notice_informix.pl b/src/interfaces/ecpg/preproc/t/002_ecpg_notice_informix.pl
new file mode 100644
index 0000000000..1607a66164
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/002_ecpg_notice_informix.pl
@@ -0,0 +1,24 @@
+
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');
+
+command_checks_all(
+	[ 'ecpg', '-C', 'INFORMIX', 't/notice_informix.pgc' ],
+	3,
+	[qr//],
+	[
+		qr/ERROR: AT option not allowed in CLOSE DATABASE statement/,
+		qr/ERROR: "database" cannot be used as cursor name in INFORMIX mode/
+	],
+	'ecpg with errors');
+
+done_testing();
diff --git a/src/interfaces/ecpg/preproc/t/notice.pgc b/src/interfaces/ecpg/preproc/t/notice.pgc
new file mode 100644
index 0000000000..7e54627fcb
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/notice.pgc
@@ -0,0 +1,42 @@
+/* Test ECPG notice/warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+	EXEC SQL BEGIN DECLARE SECTION;
+	char *cursor_var = "mycursor";
+	short a;
+	EXEC SQL END DECLARE SECTION;
+
+	/* For consistency with other tests */
+	EXEC SQL CONNECT TO testdb AS con1;
+
+	/* Test AT option errors */
+	EXEC SQL AT con1 CONNECT TO testdb2;
+	EXEC SQL AT con1 DISCONNECT;
+	EXEC SQL AT con1 SET CONNECTION TO testdb2;
+	EXEC SQL AT con1 TYPE string IS char[11];
+	EXEC SQL AT con1 WHENEVER NOT FOUND CONTINUE;
+	EXEC SQL AT con1 VAR a IS int;
+
+	/* Test COPY FROM STDIN warning */
+	EXEC SQL COPY test FROM stdin;
+
+	/* Test same variable in multi declare statement */
+	EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+	EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+
+	/* Test duplicate cursor declarations */
+	EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+	EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+
+	/* Test SHOW ALL error */
+	EXEC SQL SHOW ALL;
+
+	/* Test deprecated LIMIT syntax warning */
+	EXEC SQL SELECT * FROM test LIMIT 10, 5;
+
+	return 0;
+}
diff --git a/src/interfaces/ecpg/preproc/t/notice_informix.pgc b/src/interfaces/ecpg/preproc/t/notice_informix.pgc
new file mode 100644
index 0000000000..18281f3b9e
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/notice_informix.pgc
@@ -0,0 +1,18 @@
+/* Test ECPG notice/warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+    /* For consistency with other tests */
+    $CONNECT TO testdb AS con1;
+
+    /* Test AT option usage at CLOSE statement in INFORMIX mode */
+    $AT con1 CLOSE database;
+
+    /* Test cursor name errors in INFORMIX mode */
+    $DECLARE database CURSOR FOR SELECT * FROM test;
+
+    return 0;
+}
#7Fujii Masao
masao.fujii@oss.nttdata.com
In reply to: Ryo Kanbayashi (#6)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On 2025/02/28 9:24, Ryo Kanbayashi wrote:

I have rewrote my patch on TAP test sttyle :)
File for build are also updated.

Thanks for updating the patch!

+    'tests': [
+      't/001_ecpg_notice.pl',
+      't/002_ecpg_notice_informix.pl',

Since neither test emits "notice" messages, shouldn't the test file
names be revised to reflect this?

Also, I'm unsure if it's ideal to place input files directly under
the "t" directory. I looked for similar TAP tests with input files,
but I couldn't find any examples to guide this decision...

+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');

These checks seem unnecessary in 002 since they're already covered in 001.

Regards,

--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION

#8Ryo Kanbayashi
kanbayashi.dev@gmail.com
In reply to: Fujii Masao (#7)
1 attachment(s)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On Fri, Feb 28, 2025 at 11:27 PM Fujii Masao
<masao.fujii@oss.nttdata.com> wrote:

On 2025/02/28 9:24, Ryo Kanbayashi wrote:

I have rewrote my patch on TAP test sttyle :)
File for build are also updated.

Thanks for updating the patch!

Thanks for review:)

+    'tests': [
+      't/001_ecpg_notice.pl',
+      't/002_ecpg_notice_informix.pl',

Since neither test emits "notice" messages, shouldn't the test file
names be revised to reflect this?

I replaced "notice" to "err_warn_msg"

Also, I'm unsure if it's ideal to place input files directly under
the "t" directory. I looked for similar TAP tests with input files,
but I couldn't find any examples to guide this decision...

I couldn't too. So places are not changed.

+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');

These checks seem unnecessary in 002 since they're already covered in 001.

I reflected above.

---
Great regards,
Ryo Kanbayashi

Attachments:

ecpg-notice-regress-patch-tap-ver-rebased.patchapplication/octet-stream; name=ecpg-notice-regress-patch-tap-ver-rebased.patchDownload
diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile
index 84199a9a5d0..d0e3852a878 100644
--- a/src/interfaces/ecpg/preproc/Makefile
+++ b/src/interfaces/ecpg/preproc/Makefile
@@ -81,6 +81,9 @@ ecpg_keywords.o: ecpg_kwlist_d.h
 c_keywords.o: c_kwlist_d.h
 keywords.o: $(top_srcdir)/src/include/parser/kwlist.h
 
+check:
+	$(prove_check)
+
 install: all installdirs
 	$(INSTALL_PROGRAM) ecpg$(X) '$(DESTDIR)$(bindir)'
 
diff --git a/src/interfaces/ecpg/preproc/meson.build b/src/interfaces/ecpg/preproc/meson.build
index bfd0ed2efb4..01f2ac671ec 100644
--- a/src/interfaces/ecpg/preproc/meson.build
+++ b/src/interfaces/ecpg/preproc/meson.build
@@ -86,3 +86,16 @@ ecpg_exe = executable('ecpg',
 ecpg_targets += ecpg_exe
 
 subdir('po', if_found: libintl)
+
+tests += {
+  'name': 'ecpg',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tap': {
+    'tests': [
+      't/001_ecpg_err_warn_msg.pl',
+      't/002_ecpg_err_warn_msg_informix.pl',
+    ],
+    'deps': ecpg_exe,
+  },
+}
\ No newline at end of file
diff --git a/src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl b/src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl
new file mode 100644
index 00000000000..e0edec7cf7e
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl
@@ -0,0 +1,37 @@
+
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');
+
+command_checks_all(
+	[ 'ecpg', 't/err_warn_msg.pgc' ],
+	3,
+	[qr//],
+	[
+		qr/ERROR: AT option not allowed in CONNECT statement/,
+		qr/ERROR: AT option not allowed in DISCONNECT statement/,
+		qr/ERROR: AT option not allowed in SET CONNECTION statement/,
+		qr/ERROR: AT option not allowed in TYPE statement/,
+		qr/ERROR: AT option not allowed in WHENEVER statement/,
+		qr/ERROR: AT option not allowed in VAR statement/,
+		qr/WARNING: COPY FROM STDIN is not implemented/,
+		qr/ERROR: using variable "cursor_var" in different declare statements is not supported/,
+		qr/ERROR: cursor "duplicate_cursor" is already defined/,
+		qr/ERROR: SHOW ALL is not implemented/,
+		qr/WARNING: no longer supported LIMIT/,
+		qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/,
+		qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/,
+		qr/WARNING: cursor ":cursor_var" has been declared but not opened/,
+		qr/WARNING: cursor ":cursor_var" has been declared but not opened/
+	],
+	'ecpg with erros and warnings');
+
+done_testing();
diff --git a/src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl b/src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl
new file mode 100644
index 00000000000..e67dea1494f
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl
@@ -0,0 +1,19 @@
+
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+command_checks_all(
+	[ 'ecpg', '-C', 'INFORMIX', 't/err_warn_msg_informix.pgc' ],
+	3,
+	[qr//],
+	[
+		qr/ERROR: AT option not allowed in CLOSE DATABASE statement/,
+		qr/ERROR: "database" cannot be used as cursor name in INFORMIX mode/
+	],
+	'ecpg with errors');
+
+done_testing();
diff --git a/src/interfaces/ecpg/preproc/t/err_warn_msg.pgc b/src/interfaces/ecpg/preproc/t/err_warn_msg.pgc
new file mode 100644
index 00000000000..5ab0a761866
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/err_warn_msg.pgc
@@ -0,0 +1,42 @@
+/* Test ECPG warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+	EXEC SQL BEGIN DECLARE SECTION;
+	char *cursor_var = "mycursor";
+	short a;
+	EXEC SQL END DECLARE SECTION;
+
+	/* For consistency with other tests */
+	EXEC SQL CONNECT TO testdb AS con1;
+
+	/* Test AT option errors */
+	EXEC SQL AT con1 CONNECT TO testdb2;
+	EXEC SQL AT con1 DISCONNECT;
+	EXEC SQL AT con1 SET CONNECTION TO testdb2;
+	EXEC SQL AT con1 TYPE string IS char[11];
+	EXEC SQL AT con1 WHENEVER NOT FOUND CONTINUE;
+	EXEC SQL AT con1 VAR a IS int;
+
+	/* Test COPY FROM STDIN warning */
+	EXEC SQL COPY test FROM stdin;
+
+	/* Test same variable in multi declare statement */
+	EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+	EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+
+	/* Test duplicate cursor declarations */
+	EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+	EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+
+	/* Test SHOW ALL error */
+	EXEC SQL SHOW ALL;
+
+	/* Test deprecated LIMIT syntax warning */
+	EXEC SQL SELECT * FROM test LIMIT 10, 5;
+
+	return 0;
+}
diff --git a/src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc b/src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc
new file mode 100644
index 00000000000..839a023cb98
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc
@@ -0,0 +1,18 @@
+/* Test ECPG warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+    /* For consistency with other tests */
+    $CONNECT TO testdb AS con1;
+
+    /* Test AT option usage at CLOSE statement in INFORMIX mode */
+    $AT con1 CLOSE database;
+
+    /* Test cursor name errors in INFORMIX mode */
+    $DECLARE database CURSOR FOR SELECT * FROM test;
+
+    return 0;
+}
#9Fujii Masao
masao.fujii@oss.nttdata.com
In reply to: Ryo Kanbayashi (#8)
1 attachment(s)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On 2025/03/01 19:45, Ryo Kanbayashi wrote:

+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');

These checks seem unnecessary in 002 since they're already covered in 001.

I reflected above.

Thanks for updating the patch!

I've made some minor fixes and cosmetic adjustments.
The updated patch is attached.

Unless there are any objections, I'll commit it.

Regards,

--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION

Attachments:

v6-0001-ecpg-Add-TAP-test-for-the-ecpg-command.patchtext/plain; charset=UTF-8; name=v6-0001-ecpg-Add-TAP-test-for-the-ecpg-command.patchDownload
From 3d06f586d1f9f4760f8259bc10c11f2152c3266f Mon Sep 17 00:00:00 2001
From: Fujii Masao <fujii@postgresql.org>
Date: Mon, 3 Mar 2025 09:24:02 +0900
Subject: [PATCH v6] ecpg: Add TAP test for the ecpg command.

This commit adds a TAP test to verify that the ecpg command correctly
detects unsupported or disallowed statements in input files and reports
the appropriate error or warning messages.

This test helps catch bugs like the one introduced in commit 3d009e45bd,
which broke ecpg's handling of unsupported COPY FROM STDIN statements,
later fixed by commit 94b914f601b.

Author: Ryo Kanbayashi <kanbayashi.dev@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CANOn0EzoMyxA1m-quDS1UeQUq6FNki6+GGiGucgr9tm2R78rKw@mail.gmail.com
---
 src/interfaces/ecpg/preproc/Makefile          |  3 ++
 src/interfaces/ecpg/preproc/meson.build       | 13 ++++++
 .../ecpg/preproc/t/001_ecpg_err_warn_msg.pl   | 40 ++++++++++++++++++
 .../t/002_ecpg_err_warn_msg_informix.pl       | 22 ++++++++++
 .../ecpg/preproc/t/err_warn_msg.pgc           | 42 +++++++++++++++++++
 .../ecpg/preproc/t/err_warn_msg_informix.pgc  | 18 ++++++++
 6 files changed, 138 insertions(+)
 create mode 100644 src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl
 create mode 100644 src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl
 create mode 100644 src/interfaces/ecpg/preproc/t/err_warn_msg.pgc
 create mode 100644 src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc

diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile
index 84199a9a5d0..d0e3852a878 100644
--- a/src/interfaces/ecpg/preproc/Makefile
+++ b/src/interfaces/ecpg/preproc/Makefile
@@ -81,6 +81,9 @@ ecpg_keywords.o: ecpg_kwlist_d.h
 c_keywords.o: c_kwlist_d.h
 keywords.o: $(top_srcdir)/src/include/parser/kwlist.h
 
+check:
+	$(prove_check)
+
 install: all installdirs
 	$(INSTALL_PROGRAM) ecpg$(X) '$(DESTDIR)$(bindir)'
 
diff --git a/src/interfaces/ecpg/preproc/meson.build b/src/interfaces/ecpg/preproc/meson.build
index bfd0ed2efb4..01f2ac671ec 100644
--- a/src/interfaces/ecpg/preproc/meson.build
+++ b/src/interfaces/ecpg/preproc/meson.build
@@ -86,3 +86,16 @@ ecpg_exe = executable('ecpg',
 ecpg_targets += ecpg_exe
 
 subdir('po', if_found: libintl)
+
+tests += {
+  'name': 'ecpg',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tap': {
+    'tests': [
+      't/001_ecpg_err_warn_msg.pl',
+      't/002_ecpg_err_warn_msg_informix.pl',
+    ],
+    'deps': ecpg_exe,
+  },
+}
\ No newline at end of file
diff --git a/src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl b/src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl
new file mode 100644
index 00000000000..a18e09e6ee8
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/001_ecpg_err_warn_msg.pl
@@ -0,0 +1,40 @@
+
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');
+
+# Test that the ecpg command correctly detects unsupported or disallowed
+# statements in the input file and reports the appropriate error or
+# warning messages.
+command_checks_all(
+	[ 'ecpg', 't/err_warn_msg.pgc' ],
+	3,
+	[qr//],
+	[
+		qr/ERROR: AT option not allowed in CONNECT statement/,
+		qr/ERROR: AT option not allowed in DISCONNECT statement/,
+		qr/ERROR: AT option not allowed in SET CONNECTION statement/,
+		qr/ERROR: AT option not allowed in TYPE statement/,
+		qr/ERROR: AT option not allowed in WHENEVER statement/,
+		qr/ERROR: AT option not allowed in VAR statement/,
+		qr/WARNING: COPY FROM STDIN is not implemented/,
+		qr/ERROR: using variable "cursor_var" in different declare statements is not supported/,
+		qr/ERROR: cursor "duplicate_cursor" is already defined/,
+		qr/ERROR: SHOW ALL is not implemented/,
+		qr/WARNING: no longer supported LIMIT/,
+		qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/,
+		qr/WARNING: cursor "duplicate_cursor" has been declared but not opened/,
+		qr/WARNING: cursor ":cursor_var" has been declared but not opened/,
+		qr/WARNING: cursor ":cursor_var" has been declared but not opened/
+	],
+	'ecpg with errors and warnings');
+
+done_testing();
diff --git a/src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl b/src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl
new file mode 100644
index 00000000000..cb0502dfc2b
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/002_ecpg_err_warn_msg_informix.pl
@@ -0,0 +1,22 @@
+
+# Copyright (c) 2021-2025, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+# Test that the ecpg command in INFORMIX mode correctly detects
+# unsupported or disallowed statements in the input file and reports
+# the appropriate error or warning messages.
+command_checks_all(
+	[ 'ecpg', '-C', 'INFORMIX', 't/err_warn_msg_informix.pgc' ],
+	3,
+	[qr//],
+	[
+		qr/ERROR: AT option not allowed in CLOSE DATABASE statement/,
+		qr/ERROR: "database" cannot be used as cursor name in INFORMIX mode/
+	],
+	'ecpg in INFORMIX mode with errors and warnings');
+
+done_testing();
diff --git a/src/interfaces/ecpg/preproc/t/err_warn_msg.pgc b/src/interfaces/ecpg/preproc/t/err_warn_msg.pgc
new file mode 100644
index 00000000000..5ab0a761866
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/err_warn_msg.pgc
@@ -0,0 +1,42 @@
+/* Test ECPG warning/error messages */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+	EXEC SQL BEGIN DECLARE SECTION;
+	char *cursor_var = "mycursor";
+	short a;
+	EXEC SQL END DECLARE SECTION;
+
+	/* For consistency with other tests */
+	EXEC SQL CONNECT TO testdb AS con1;
+
+	/* Test AT option errors */
+	EXEC SQL AT con1 CONNECT TO testdb2;
+	EXEC SQL AT con1 DISCONNECT;
+	EXEC SQL AT con1 SET CONNECTION TO testdb2;
+	EXEC SQL AT con1 TYPE string IS char[11];
+	EXEC SQL AT con1 WHENEVER NOT FOUND CONTINUE;
+	EXEC SQL AT con1 VAR a IS int;
+
+	/* Test COPY FROM STDIN warning */
+	EXEC SQL COPY test FROM stdin;
+
+	/* Test same variable in multi declare statement */
+	EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+	EXEC SQL DECLARE :cursor_var CURSOR FOR SELECT * FROM test;
+
+	/* Test duplicate cursor declarations */
+	EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+	EXEC SQL DECLARE duplicate_cursor CURSOR FOR SELECT * FROM test;
+
+	/* Test SHOW ALL error */
+	EXEC SQL SHOW ALL;
+
+	/* Test deprecated LIMIT syntax warning */
+	EXEC SQL SELECT * FROM test LIMIT 10, 5;
+
+	return 0;
+}
diff --git a/src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc b/src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc
new file mode 100644
index 00000000000..e8db65eefa1
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/t/err_warn_msg_informix.pgc
@@ -0,0 +1,18 @@
+/* Test ECPG warning/error messages in INFORMIX mode */
+
+#include <stdlib.h>
+
+int
+main(void)
+{
+    /* For consistency with other tests */
+    $CONNECT TO testdb AS con1;
+
+    /* Test AT option usage at CLOSE DATABASE statement in INFORMIX mode */
+    $AT con1 CLOSE DATABASE;
+
+    /* Test cursor name errors in INFORMIX mode */
+    $DECLARE database CURSOR FOR SELECT * FROM test;
+
+    return 0;
+}
-- 
2.48.1

#10Ryo Kanbayashi
kanbayashi.dev@gmail.com
In reply to: Fujii Masao (#9)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On Mon, Mar 3, 2025 at 12:23 PM Fujii Masao <masao.fujii@oss.nttdata.com> wrote:
On 2025/03/01 19:45, Ryo Kanbayashi wrote:

+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');

These checks seem unnecessary in 002 since they're already covered in 001.

I reflected above.

Thanks for updating the patch!

I've made some minor fixes and cosmetic adjustments.
The updated patch is attached.

Unless there are any objections, I'll commit it.

Thanks for reviewing and adustments.
There is no objections :)

---
Great regards,
Ryo Kanbayashi
NTT Open Source Software Center

#11Fujii Masao
masao.fujii@oss.nttdata.com
In reply to: Ryo Kanbayashi (#10)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On 2025/03/03 14:09, Ryo Kanbayashi wrote:

On Mon, Mar 3, 2025 at 12:23 PM Fujii Masao <masao.fujii@oss.nttdata.com> wrote:
On 2025/03/01 19:45, Ryo Kanbayashi wrote:

+program_help_ok('ecpg');
+program_version_ok('ecpg');
+program_options_handling_ok('ecpg');
+command_fails(['ecpg'], 'ecpg without arguments fails');

These checks seem unnecessary in 002 since they're already covered in 001.

I reflected above.

Thanks for updating the patch!

I've made some minor fixes and cosmetic adjustments.
The updated patch is attached.

Unless there are any objections, I'll commit it.

Thanks for reviewing and adustments.
There is no objections :)

I've pushed the patch. Thanks!

Regards,

--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION

#12Jacob Champion
jacob.champion@enterprisedb.com
In reply to: Fujii Masao (#11)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On Mon, Mar 3, 2025 at 10:02 PM Fujii Masao <masao.fujii@oss.nttdata.com> wrote:

I've pushed the patch. Thanks!

Hi all,

+tests += {
+  'name': 'ecpg',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tap': {
+    'tests': [
+      't/001_ecpg_err_warn_msg.pl',
+      't/002_ecpg_err_warn_msg_informix.pl',
+    ],
+    'deps': ecpg_exe,
+  },
+}

My version of Meson is complaining about this use of 'deps':

../meson.build:3603: WARNING: Project targets '>=0.54' but uses
feature introduced in '0.60.0': list.<plus>. The right hand operand
was not a list.
Adding test "ecpg/001_ecpg_err_warn_msg"
...

ecpg_exe should perhaps be wrapped in a list for now? I.e.

    -    'deps': ecpg_exe,
    +    'deps': [ecpg_exe],

Thanks,
--Jacob

#13Fujii Masao
masao.fujii@oss.nttdata.com
In reply to: Jacob Champion (#12)
1 attachment(s)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On 2025/03/05 7:26, Jacob Champion wrote:

On Mon, Mar 3, 2025 at 10:02 PM Fujii Masao <masao.fujii@oss.nttdata.com> wrote:

I've pushed the patch. Thanks!

Hi all,

+tests += {
+  'name': 'ecpg',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tap': {
+    'tests': [
+      't/001_ecpg_err_warn_msg.pl',
+      't/002_ecpg_err_warn_msg_informix.pl',
+    ],
+    'deps': ecpg_exe,
+  },
+}

My version of Meson is complaining about this use of 'deps':

../meson.build:3603: WARNING: Project targets '>=0.54' but uses
feature introduced in '0.60.0': list.<plus>. The right hand operand
was not a list.
Adding test "ecpg/001_ecpg_err_warn_msg"
...

ecpg_exe should perhaps be wrapped in a list for now? I.e.

-    'deps': ecpg_exe,
+    'deps': [ecpg_exe],

Thanks for reporting this and suggesting a fix. I think you're right.

I confirmed that the compiler warning also appears in my environment,
and your fix resolves it. I’ve converted your fix into a patch, which is attached.

Unless there are any objections, I'm thinking to commit it.

Regards,

--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION

Attachments:

v1-0001-ecpg-Fix-compiler-warning-in-ecpg-build-with-Meso.patchtext/plain; charset=UTF-8; name=v1-0001-ecpg-Fix-compiler-warning-in-ecpg-build-with-Meso.patchDownload
From 0a477edb2528db8b0008e9453a1de084f926e162 Mon Sep 17 00:00:00 2001
From: Fujii Masao <fujii@postgresql.org>
Date: Wed, 5 Mar 2025 09:23:20 +0900
Subject: [PATCH v1] ecpg: Fix compiler warning in ecpg build with Meson.

Previously, Meson could produce a warning about the use of 'deps' in ecpg:

    WARNING: Project targets '>=0.54' but uses a feature introduced in '0.60.0': list.<plus>. The right-hand operand was not a list.

The right-hand operand of 'deps' should be a list. This commit fixes
the warning by wrapping it with square brackets.

This issue was introduced in commit 28f04984f0c.

Author: Jacob Champion <jacob.champion@enterprisedb.com>
Discussion: https://postgr.es/m/CAOYmi+ks8wO06Ymxduw2h_eQJ_D4_jHGeyMK0P=p5Q3psnEdMA@mail.gmail.com
---
 src/interfaces/ecpg/preproc/meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/interfaces/ecpg/preproc/meson.build b/src/interfaces/ecpg/preproc/meson.build
index 01f2ac671ec..c9f4035053d 100644
--- a/src/interfaces/ecpg/preproc/meson.build
+++ b/src/interfaces/ecpg/preproc/meson.build
@@ -96,6 +96,6 @@ tests += {
       't/001_ecpg_err_warn_msg.pl',
       't/002_ecpg_err_warn_msg_informix.pl',
     ],
-    'deps': ecpg_exe,
+    'deps': [ecpg_exe],
   },
 }
\ No newline at end of file
-- 
2.48.1

#14Fujii Masao
masao.fujii@oss.nttdata.com
In reply to: Fujii Masao (#13)
Re: [PATCH] Add regression tests of ecpg command notice (error / warning)

On 2025/03/05 9:32, Fujii Masao wrote:

On 2025/03/05 7:26, Jacob Champion wrote:

On Mon, Mar 3, 2025 at 10:02 PM Fujii Masao <masao.fujii@oss.nttdata.com> wrote:

I've pushed the patch. Thanks!

Hi all,

+tests += {
+  'name': 'ecpg',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tap': {
+    'tests': [
+      't/001_ecpg_err_warn_msg.pl',
+      't/002_ecpg_err_warn_msg_informix.pl',
+    ],
+    'deps': ecpg_exe,
+  },
+}

My version of Meson is complaining about this use of 'deps':

     ../meson.build:3603: WARNING: Project targets '>=0.54' but uses
feature introduced in '0.60.0': list.<plus>. The right hand operand
was not a list.
     Adding test "ecpg/001_ecpg_err_warn_msg"
     ...

ecpg_exe should perhaps be wrapped in a list for now? I.e.

     -    'deps': ecpg_exe,
     +    'deps': [ecpg_exe],

Thanks for reporting this and suggesting a fix. I think you're right.

I confirmed that the compiler warning also appears in my environment,
and your fix resolves it. I’ve converted your fix into a patch, which is attached.

Unless there are any objections, I'm thinking to commit it.

I've pushed the patch. Thanks!

Regards,

--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION