From 103453166a81967611df6c99b7906a635940927f Mon Sep 17 00:00:00 2001
From: Shenhao Wang <wangsh.fnst@fujitsu.com>
Date: Sun, 26 Sep 2021 15:46:03 +0800
Subject: [PATCH 3/3] v1 some canonicalize_path tests

---
 src/test/modules/Makefile                     |   1 +
 src/test/modules/test_path/.gitignore         |   4 +
 src/test/modules/test_path/Makefile           |  23 +
 .../modules/test_path/expected/test_path.out  | 485 ++++++++++++++++++
 .../test_path/expected/test_path_1.out        | 485 ++++++++++++++++++
 src/test/modules/test_path/sql/test_path.sql  | 101 ++++
 src/test/modules/test_path/test_path--1.0.sql |  14 +
 src/test/modules/test_path/test_path.c        |  53 ++
 src/test/modules/test_path/test_path.control  |   5 +
 9 files changed, 1171 insertions(+)
 create mode 100644 src/test/modules/test_path/.gitignore
 create mode 100644 src/test/modules/test_path/Makefile
 create mode 100644 src/test/modules/test_path/expected/test_path.out
 create mode 100644 src/test/modules/test_path/expected/test_path_1.out
 create mode 100644 src/test/modules/test_path/sql/test_path.sql
 create mode 100644 src/test/modules/test_path/test_path--1.0.sql
 create mode 100644 src/test/modules/test_path/test_path.c
 create mode 100644 src/test/modules/test_path/test_path.control

diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index dffc79b2d9..1317d97049 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -21,6 +21,7 @@ SUBDIRS = \
 		  test_integerset \
 		  test_misc \
 		  test_parser \
+		  test_path \
 		  test_pg_dump \
 		  test_predtest \
 		  test_rbtree \
diff --git a/src/test/modules/test_path/.gitignore b/src/test/modules/test_path/.gitignore
new file mode 100644
index 0000000000..5dcb3ff972
--- /dev/null
+++ b/src/test/modules/test_path/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/test_path/Makefile b/src/test/modules/test_path/Makefile
new file mode 100644
index 0000000000..3f2d4ff001
--- /dev/null
+++ b/src/test/modules/test_path/Makefile
@@ -0,0 +1,23 @@
+# src/test/modules/test_path/Makefile
+
+MODULE_big = test_path
+OBJS = \
+	$(WIN32RES) \
+	test_path.o
+PGFILEDESC = "test_path - test canonicalize_path"
+
+EXTENSION = test_path
+DATA = test_path--1.0.sql
+
+REGRESS = test_path
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_path
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/test_path/expected/test_path.out b/src/test/modules/test_path/expected/test_path.out
new file mode 100644
index 0000000000..c60eac452b
--- /dev/null
+++ b/src/test/modules/test_path/expected/test_path.out
@@ -0,0 +1,485 @@
+CREATE EXTENSION test_path;
+SELECT * FROM test_platform();
+ test_platform 
+---------------
+ Linux
+(1 row)
+
+-- prefix is '/'
+SELECT * FROM test_canonicalize_path('/');
+ test_canonicalize_path 
+------------------------
+ /
+(1 row)
+
+SELECT * FROM test_canonicalize_path('//');
+ test_canonicalize_path 
+------------------------
+ /
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/./abc/def/');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/./../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/./../../abc/def/');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/./../abc/def//');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/def/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/def/../../../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+-- prefix is '/abc'
+SELECT * FROM test_canonicalize_path('/abc/./abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/abc/../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/abc/./../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/abc/def/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/abc/def
+(1 row)
+
+-- prefix is '.'
+SELECT * FROM test_canonicalize_path('.');
+ test_canonicalize_path 
+------------------------
+ .
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./');
+ test_canonicalize_path 
+------------------------
+ .
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/..');
+ test_canonicalize_path 
+------------------------
+ .
+(1 row)
+
+-- prefix is '..'
+SELECT * FROM test_canonicalize_path('..');
+ test_canonicalize_path 
+------------------------
+ ..
+(1 row)
+
+SELECT * FROM test_canonicalize_path('../');
+ test_canonicalize_path 
+------------------------
+ ..
+(1 row)
+
+SELECT * FROM test_canonicalize_path('../abc/def');
+ test_canonicalize_path 
+------------------------
+ ../abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./../abc/def');
+ test_canonicalize_path 
+------------------------
+ ../abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ ../abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/./def/.././ghi/../../../abc/def');
+ test_canonicalize_path 
+------------------------
+ ../abc/def
+(1 row)
+
+-- prefix is 'abc'
+SELECT * FROM test_canonicalize_path('abc');
+ test_canonicalize_path 
+------------------------
+ abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/');
+ test_canonicalize_path 
+------------------------
+ abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/./../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/./def/.././../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/./../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/./def/.././../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+-- special
+SELECT * FROM test_canonicalize_path('/abc/c:abc');
+ test_canonicalize_path 
+------------------------
+ /abc/c:abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:/abc');
+ test_canonicalize_path 
+------------------------
+ /abc/c:/abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:\abc');
+ test_canonicalize_path 
+------------------------
+ /abc/c:\abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/c:abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:abc/./def');
+ test_canonicalize_path 
+------------------------
+ /abc/c:abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:abc/./../def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('c:abc');
+ test_canonicalize_path 
+------------------------
+ c:abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('c:abc/def');
+ test_canonicalize_path 
+------------------------
+ c:abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./c:abc/./def');
+ test_canonicalize_path 
+------------------------
+ c:abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('../c:abc/./../def');
+ test_canonicalize_path 
+------------------------
+ ../def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/..a/b..');
+ test_canonicalize_path 
+------------------------
+ /..a/b..
+(1 row)
+
+-- Windows
+-- prefix is 'C:\' or '\\network'
+SELECT * FROM test_canonicalize_path('C:');
+ test_canonicalize_path 
+------------------------
+ C:
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\');
+ test_canonicalize_path 
+------------------------
+ C:\
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\\');
+ test_canonicalize_path 
+------------------------
+ C:\\
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\\\');
+ test_canonicalize_path 
+------------------------
+ C:\\\
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\\.\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:\\.\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\\.\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:\\.\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\.\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:\.\..\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:\..\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:\abc\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\.\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:\abc\.\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:\abc\..\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\def\..\..\abc\def');
+  test_canonicalize_path  
+--------------------------
+ C:\abc\def\..\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\def\..\..\..\..\abc\def');
+     test_canonicalize_path     
+--------------------------------
+ C:\abc\def\..\..\..\..\abc\def
+(1 row)
+
+-- prefix is '\\network'
+SELECT * FROM test_canonicalize_path('\\127.0.0.1');
+ test_canonicalize_path 
+------------------------
+ \\127.0.0.1
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\');
+ test_canonicalize_path 
+------------------------
+ \\127.0.0.1\
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\');
+ test_canonicalize_path 
+------------------------
+ \\127.0.0.1\\
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\\');
+ test_canonicalize_path 
+------------------------
+ \\127.0.0.1\\\
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\.\abc\def');
+ test_canonicalize_path 
+------------------------
+ \\127.0.0.1\\.\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\.\..\abc\def');
+  test_canonicalize_path   
+---------------------------
+ \\127.0.0.1\\.\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\.\..\..\abc\def');
+   test_canonicalize_path    
+-----------------------------
+ \\127.0.0.1\.\..\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ \\127.0.0.1\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\..\..\abc\def');
+  test_canonicalize_path   
+---------------------------
+ \\127.0.0.1\..\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\..\abc\def');
+   test_canonicalize_path   
+----------------------------
+ \\127.0.0.1\abc\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\.\..\abc\def');
+    test_canonicalize_path    
+------------------------------
+ \\127.0.0.1\abc\.\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\..\..\abc\def');
+    test_canonicalize_path     
+-------------------------------
+ \\127.0.0.1\abc\..\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\def\..\..\abc\def');
+      test_canonicalize_path       
+-----------------------------------
+ \\127.0.0.1\abc\def\..\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\def\..\..\..\..\abc\def');
+         test_canonicalize_path          
+-----------------------------------------
+ \\127.0.0.1\abc\def\..\..\..\..\abc\def
+(1 row)
+
+-- prefix is 'C:\abc' or '\\network\abc'
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\.\abc\def');
+  test_canonicalize_path   
+---------------------------
+ \\127.0.0.1\abc\.\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\abc\..\abc\def');
+     test_canonicalize_path     
+--------------------------------
+ \\127.0.0.1\abc\abc\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\abc\.\..\abc\def');
+      test_canonicalize_path      
+----------------------------------
+ \\127.0.0.1\abc\abc\.\..\abc\def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\abc\def\..\..\abc\def');
+        test_canonicalize_path         
+---------------------------------------
+ \\127.0.0.1\abc\abc\def\..\..\abc\def
+(1 row)
+
diff --git a/src/test/modules/test_path/expected/test_path_1.out b/src/test/modules/test_path/expected/test_path_1.out
new file mode 100644
index 0000000000..6a15af3780
--- /dev/null
+++ b/src/test/modules/test_path/expected/test_path_1.out
@@ -0,0 +1,485 @@
+CREATE EXTENSION test_path;
+SELECT * FROM test_platform();
+ test_platform 
+---------------
+ Win32
+(1 row)
+
+-- prefix is '/'
+SELECT * FROM test_canonicalize_path('/');
+ test_canonicalize_path 
+------------------------
+ /
+(1 row)
+
+SELECT * FROM test_canonicalize_path('//');
+ test_canonicalize_path 
+------------------------
+ //
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/./abc/def/');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/./../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/./../../abc/def/');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/./../abc/def//');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/def/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/def/../../../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+-- prefix is '/abc'
+SELECT * FROM test_canonicalize_path('/abc/./abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/abc/../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/abc/./../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/abc/def/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/abc/def
+(1 row)
+
+-- prefix is '.'
+SELECT * FROM test_canonicalize_path('.');
+ test_canonicalize_path 
+------------------------
+ .
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./');
+ test_canonicalize_path 
+------------------------
+ .
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/..');
+ test_canonicalize_path 
+------------------------
+ .
+(1 row)
+
+-- prefix is '..'
+SELECT * FROM test_canonicalize_path('..');
+ test_canonicalize_path 
+------------------------
+ ..
+(1 row)
+
+SELECT * FROM test_canonicalize_path('../');
+ test_canonicalize_path 
+------------------------
+ ..
+(1 row)
+
+SELECT * FROM test_canonicalize_path('../abc/def');
+ test_canonicalize_path 
+------------------------
+ ../abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./../abc/def');
+ test_canonicalize_path 
+------------------------
+ ../abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/../../abc/def');
+ test_canonicalize_path 
+------------------------
+ ../abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/./def/.././ghi/../../../abc/def');
+ test_canonicalize_path 
+------------------------
+ ../abc/def
+(1 row)
+
+-- prefix is 'abc'
+SELECT * FROM test_canonicalize_path('abc');
+ test_canonicalize_path 
+------------------------
+ abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/');
+ test_canonicalize_path 
+------------------------
+ abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/./../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./abc/./def/.././../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/./../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('abc/./def/.././../abc/def');
+ test_canonicalize_path 
+------------------------
+ abc/def
+(1 row)
+
+-- special
+SELECT * FROM test_canonicalize_path('/abc/c:abc');
+ test_canonicalize_path 
+------------------------
+ /abc/c:abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:/abc');
+ test_canonicalize_path 
+------------------------
+ /abc/c:/abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:\abc');
+ test_canonicalize_path 
+------------------------
+ /abc/c:/abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:abc/def');
+ test_canonicalize_path 
+------------------------
+ /abc/c:abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:abc/./def');
+ test_canonicalize_path 
+------------------------
+ /abc/c:abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/abc/c:abc/./../def');
+ test_canonicalize_path 
+------------------------
+ /abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('c:abc');
+ test_canonicalize_path 
+------------------------
+ c:abc
+(1 row)
+
+SELECT * FROM test_canonicalize_path('c:abc/def');
+ test_canonicalize_path 
+------------------------
+ c:abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('./c:abc/./def');
+ test_canonicalize_path 
+------------------------
+ c:abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('../c:abc/./../def');
+ test_canonicalize_path 
+------------------------
+ ../def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('/..a/b..');
+ test_canonicalize_path 
+------------------------
+ /..a/b..
+(1 row)
+
+-- Windows
+-- prefix is 'C:\' or '\\network'
+SELECT * FROM test_canonicalize_path('C:');
+ test_canonicalize_path 
+------------------------
+ C:
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\');
+ test_canonicalize_path 
+------------------------
+ C:/
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\\');
+ test_canonicalize_path 
+------------------------
+ C:/
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\\\');
+ test_canonicalize_path 
+------------------------
+ C:/
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\\.\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\\.\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\.\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\.\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\def\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('C:\abc\def\..\..\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ C:/abc/def
+(1 row)
+
+-- prefix is '\\network'
+SELECT * FROM test_canonicalize_path('\\127.0.0.1');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\\');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\.\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\.\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\.\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\.\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\def\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\def\..\..\..\..\abc\def');
+ test_canonicalize_path 
+------------------------
+ //127.0.0.1/abc/def
+(1 row)
+
+-- prefix is 'C:\abc' or '\\network\abc'
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\.\abc\def');
+ test_canonicalize_path  
+-------------------------
+ //127.0.0.1/abc/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\abc\..\abc\def');
+ test_canonicalize_path  
+-------------------------
+ //127.0.0.1/abc/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\abc\.\..\abc\def');
+ test_canonicalize_path  
+-------------------------
+ //127.0.0.1/abc/abc/def
+(1 row)
+
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\abc\def\..\..\abc\def');
+ test_canonicalize_path  
+-------------------------
+ //127.0.0.1/abc/abc/def
+(1 row)
+
diff --git a/src/test/modules/test_path/sql/test_path.sql b/src/test/modules/test_path/sql/test_path.sql
new file mode 100644
index 0000000000..b0f2134570
--- /dev/null
+++ b/src/test/modules/test_path/sql/test_path.sql
@@ -0,0 +1,101 @@
+CREATE EXTENSION test_path;
+
+SELECT * FROM test_platform();
+
+-- prefix is '/'
+SELECT * FROM test_canonicalize_path('/');
+SELECT * FROM test_canonicalize_path('//');
+SELECT * FROM test_canonicalize_path('/./abc/def/');
+SELECT * FROM test_canonicalize_path('/./../abc/def');
+SELECT * FROM test_canonicalize_path('/./../../abc/def/');
+SELECT * FROM test_canonicalize_path('/../abc/def');
+SELECT * FROM test_canonicalize_path('/../../abc/def');
+SELECT * FROM test_canonicalize_path('/abc/../abc/def');
+SELECT * FROM test_canonicalize_path('/abc/./../abc/def//');
+SELECT * FROM test_canonicalize_path('/abc/../../abc/def');
+SELECT * FROM test_canonicalize_path('/abc/def/../../abc/def');
+SELECT * FROM test_canonicalize_path('/abc/def/../../../../abc/def');
+
+-- prefix is '/abc'
+SELECT * FROM test_canonicalize_path('/abc/./abc/def');
+SELECT * FROM test_canonicalize_path('/abc/abc/../abc/def');
+SELECT * FROM test_canonicalize_path('/abc/abc/./../abc/def');
+SELECT * FROM test_canonicalize_path('/abc/abc/def/../../abc/def');
+
+-- prefix is '.'
+SELECT * FROM test_canonicalize_path('.');
+SELECT * FROM test_canonicalize_path('./');
+SELECT * FROM test_canonicalize_path('./abc/..');
+
+-- prefix is '..'
+SELECT * FROM test_canonicalize_path('..');
+SELECT * FROM test_canonicalize_path('../');
+SELECT * FROM test_canonicalize_path('../abc/def');
+SELECT * FROM test_canonicalize_path('./../abc/def');
+SELECT * FROM test_canonicalize_path('./abc/../../abc/def');
+SELECT * FROM test_canonicalize_path('./abc/./def/.././ghi/../../../abc/def');
+
+-- prefix is 'abc'
+SELECT * FROM test_canonicalize_path('abc');
+SELECT * FROM test_canonicalize_path('abc/');
+SELECT * FROM test_canonicalize_path('./abc/def');
+SELECT * FROM test_canonicalize_path('./abc/../abc/def');
+SELECT * FROM test_canonicalize_path('./abc/./../abc/def');
+SELECT * FROM test_canonicalize_path('./abc/./def/.././../abc/def');
+SELECT * FROM test_canonicalize_path('abc/def');
+SELECT * FROM test_canonicalize_path('abc/../abc/def');
+SELECT * FROM test_canonicalize_path('abc/./../abc/def');
+SELECT * FROM test_canonicalize_path('abc/./def/.././../abc/def');
+
+-- special
+SELECT * FROM test_canonicalize_path('/abc/c:abc');
+SELECT * FROM test_canonicalize_path('/abc/c:/abc');
+SELECT * FROM test_canonicalize_path('/abc/c:\abc');
+SELECT * FROM test_canonicalize_path('/abc/c:abc/def');
+SELECT * FROM test_canonicalize_path('/abc/c:abc/./def');
+SELECT * FROM test_canonicalize_path('/abc/c:abc/./../def');
+SELECT * FROM test_canonicalize_path('c:abc');
+SELECT * FROM test_canonicalize_path('c:abc/def');
+SELECT * FROM test_canonicalize_path('./c:abc/./def');
+SELECT * FROM test_canonicalize_path('../c:abc/./../def');
+SELECT * FROM test_canonicalize_path('/..a/b..');
+
+
+-- Windows
+-- prefix is 'C:\' or '\\network'
+SELECT * FROM test_canonicalize_path('C:');
+SELECT * FROM test_canonicalize_path('C:\');
+SELECT * FROM test_canonicalize_path('C:\\');
+SELECT * FROM test_canonicalize_path('C:\\\');
+SELECT * FROM test_canonicalize_path('C:\\.\abc\def');
+SELECT * FROM test_canonicalize_path('C:\\.\..\abc\def');
+SELECT * FROM test_canonicalize_path('C:\.\..\..\abc\def');
+SELECT * FROM test_canonicalize_path('C:\..\abc\def');
+SELECT * FROM test_canonicalize_path('C:\..\..\abc\def');
+SELECT * FROM test_canonicalize_path('C:\abc\..\abc\def');
+SELECT * FROM test_canonicalize_path('C:\abc\.\..\abc\def');
+SELECT * FROM test_canonicalize_path('C:\abc\..\..\abc\def');
+SELECT * FROM test_canonicalize_path('C:\abc\def\..\..\abc\def');
+SELECT * FROM test_canonicalize_path('C:\abc\def\..\..\..\..\abc\def');
+
+-- prefix is '\\network'
+SELECT * FROM test_canonicalize_path('\\127.0.0.1');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\\');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\.\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\\.\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\.\..\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\..\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\.\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\..\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\def\..\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\def\..\..\..\..\abc\def');
+
+-- prefix is 'C:\abc' or '\\network\abc'
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\.\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\abc\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\abc\.\..\abc\def');
+SELECT * FROM test_canonicalize_path('\\127.0.0.1\abc\abc\def\..\..\abc\def');
\ No newline at end of file
diff --git a/src/test/modules/test_path/test_path--1.0.sql b/src/test/modules/test_path/test_path--1.0.sql
new file mode 100644
index 0000000000..042ff2439b
--- /dev/null
+++ b/src/test/modules/test_path/test_path--1.0.sql
@@ -0,0 +1,14 @@
+/* src/test/modules/test_path/test_path--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION test_path" to load this file. \quit
+
+CREATE FUNCTION test_canonicalize_path(text)
+RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION test_platform()
+RETURNS text
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
\ No newline at end of file
diff --git a/src/test/modules/test_path/test_path.c b/src/test/modules/test_path/test_path.c
new file mode 100644
index 0000000000..12b1300dc7
--- /dev/null
+++ b/src/test/modules/test_path/test_path.c
@@ -0,0 +1,53 @@
+/*-------------------------------------------------------------------------
+ *
+ * test_parser.c
+ *	  test canonicalize_path
+ *
+ * Copyright (c) 2007-2021, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *	  src/test/modules/test_path/test_path.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "fmgr.h"
+#include "utils/builtins.h"
+
+PG_MODULE_MAGIC;
+
+/*
+ * functions
+ */
+PG_FUNCTION_INFO_V1(test_canonicalize_path);
+PG_FUNCTION_INFO_V1(test_platform);
+
+Datum
+test_canonicalize_path(PG_FUNCTION_ARGS)
+{
+	char	   *path = strdup(text_to_cstring(PG_GETARG_TEXT_PP(0)));
+
+	if (!path)
+			ereport(ERROR,
+					(errcode(ERRCODE_OUT_OF_MEMORY),
+					 errmsg("out of memory")));
+
+	canonicalize_path(path);
+
+	PG_RETURN_TEXT_P(cstring_to_text(path));
+}
+
+Datum
+test_platform(PG_FUNCTION_ARGS)
+{
+	char *platform;
+
+#ifdef WIN32
+	platform = strdup("Win32");
+#else
+	platform = strdup("Linux");
+#endif
+
+	PG_RETURN_TEXT_P(cstring_to_text(platform));
+}
\ No newline at end of file
diff --git a/src/test/modules/test_path/test_path.control b/src/test/modules/test_path/test_path.control
new file mode 100644
index 0000000000..31ab323033
--- /dev/null
+++ b/src/test/modules/test_path/test_path.control
@@ -0,0 +1,5 @@
+# test_path extension
+comment = 'test canonicalize_path'
+default_version = '1.0'
+module_pathname = '$libdir/test_path'
+relocatable = true
-- 
2.26.2

