From: Michael Paquier Date: Thu, 27 Mar 2025 07:01:38 +0000 (+0900) Subject: libpq: Add TAP tests for service files and names X-Git-Tag: REL_18_BETA1~416 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=72c2f36d5727;p=postgresql.git libpq: Add TAP tests for service files and names This commit adds a set of regression tests that checks various patterns with service names and service files, with: - Service file with no contents, used as default for PGSERVICEFILE to prevent any lookups at the HOME directory of an environment where the test is run. - Service file with valid service name and its section. - Service file at the root of PGSYSCONFDIR, named pg_service.conf. - Missing service file. - Service name defined as a connection parameter or as PGSERVICE. Note that PGSYSCONFDIR is set to always point at a temporary directory created by the test, so as we never try to look at SYSCONFDIR. This set of tests has come up as a useful independent addition while discussing a patch that adds an equivalent of PGSERVICEFILE as a connection parameter as there have never been any tests for service files and service names. Torsten Foertsch and Ryo Kanbayashi have provided a basic implementation, that I have expanded to what is introduced in this commit. Author: Torsten Foertsch Author: Ryo Kanbayashi Author: Michael Paquier Discussion: https://postgr.es/m/CAKkG4_nCjx3a_F3gyXHSPWxD8Sd8URaM89wey7fG_9g7KBkOCQ@mail.gmail.com --- diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build index 19f4a52a97a..292fecf3320 100644 --- a/src/interfaces/libpq/meson.build +++ b/src/interfaces/libpq/meson.build @@ -122,6 +122,7 @@ tests += { 't/003_load_balance_host_list.pl', 't/004_load_balance_dns.pl', 't/005_negotiate_encryption.pl', + 't/006_service.pl', ], 'env': { 'with_ssl': ssl_library, diff --git a/src/interfaces/libpq/t/006_service.pl b/src/interfaces/libpq/t/006_service.pl new file mode 100644 index 00000000000..d3ecfa6b6fc --- /dev/null +++ b/src/interfaces/libpq/t/006_service.pl @@ -0,0 +1,141 @@ +# Copyright (c) 2025, PostgreSQL Global Development Group +use strict; +use warnings FATAL => 'all'; +use File::Copy; +use PostgreSQL::Test::Utils; +use PostgreSQL::Test::Cluster; +use Test::More; + +# This tests scenarios related to the service name and the service file, +# for the connection options and their environment variables. + +my $node = PostgreSQL::Test::Cluster->new('node'); +$node->init; +$node->start; + +my $td = PostgreSQL::Test::Utils::tempdir; + +# Windows vs non-Windows: CRLF vs LF for the file's newline, relying on +# the fact that libpq uses fgets() when reading the lines of a service file. +my $newline = $windows_os ? "\r\n" : "\n"; + +# Create the set of service files used in the tests. +# File that includes a valid service name, that uses a decomposed connection +# string for its contents, split on spaces. +my $srvfile_valid = "$td/pg_service_valid.conf"; +append_to_file($srvfile_valid, "[my_srv]", $newline); +append_to_file($srvfile_valid, split(/\s+/, $node->connstr) . $newline); + +# File defined with no contents, used as default value for PGSERVICEFILE, +# so as no lookup is attempted in the user's home directory. +my $srvfile_empty = "$td/pg_service_empty.conf"; +append_to_file($srvfile_empty, ''); + +# Default service file in PGSYSCONFDIR. +my $srvfile_default = "$td/pg_service.conf"; + +# Missing service file. +my $srvfile_missing = "$td/pg_service_missing.conf"; + +# Set the fallback directory lookup of the service file to the temporary +# directory of this test. PGSYSCONFDIR is used if the service file +# defined in PGSERVICEFILE cannot be found, or when a service file is +# found but not the service name. +local $ENV{PGSYSCONFDIR} = $td; +# Force PGSERVICEFILE to a default location, so as this test never +# tries to look at a home directory. This value needs to remain +# at the top of this script before running any tests, and should never +# be changed. +local $ENV{PGSERVICEFILE} = "$srvfile_empty"; + +# Checks combinations of service name and a valid service file. +{ + local $ENV{PGSERVICEFILE} = $srvfile_valid; + $node->connect_ok( + 'service=my_srv', + 'connection with correct "service" string and PGSERVICEFILE', + sql => "SELECT 'connect1_1'", + expected_stdout => qr/connect1_1/); + + $node->connect_ok( + 'postgres://?service=my_srv', + 'connection with correct "service" URI and PGSERVICEFILE', + sql => "SELECT 'connect1_2'", + expected_stdout => qr/connect1_2/); + + $node->connect_fails( + 'service=undefined-service', + 'connection with incorrect "service" string and PGSERVICEFILE', + expected_stderr => + qr/definition of service "undefined-service" not found/); + + local $ENV{PGSERVICE} = 'my_srv'; + $node->connect_ok( + '', + 'connection with correct PGSERVICE and PGSERVICEFILE', + sql => "SELECT 'connect1_3'", + expected_stdout => qr/connect1_3/); + + local $ENV{PGSERVICE} = 'undefined-service'; + $node->connect_fails( + '', + 'connection with incorrect PGSERVICE and PGSERVICEFILE', + expected_stdout => + qr/definition of service "undefined-service" not found/); +} + +# Checks case of incorrect service file. +{ + local $ENV{PGSERVICEFILE} = $srvfile_missing; + $node->connect_fails( + 'service=my_srv', + 'connection with correct "service" string and incorrect PGSERVICEFILE', + expected_stderr => + qr/service file ".*pg_service_missing.conf" not found/); +} + +# Checks case of service file named "pg_service.conf" in PGSYSCONFDIR. +{ + # Create copy of valid file + my $srvfile_default = "$td/pg_service.conf"; + copy($srvfile_valid, $srvfile_default); + + $node->connect_ok( + 'service=my_srv', + 'connection with correct "service" string and pg_service.conf', + sql => "SELECT 'connect2_1'", + expected_stdout => qr/connect2_1/); + + $node->connect_ok( + 'postgres://?service=my_srv', + 'connection with correct "service" URI and default pg_service.conf', + sql => "SELECT 'connect2_2'", + expected_stdout => qr/connect2_2/); + + $node->connect_fails( + 'service=undefined-service', + 'connection with incorrect "service" string and default pg_service.conf', + expected_stderr => + qr/definition of service "undefined-service" not found/); + + local $ENV{PGSERVICE} = 'my_srv'; + $node->connect_ok( + '', + 'connection with correct PGSERVICE and default pg_service.conf', + sql => "SELECT 'connect2_3'", + expected_stdout => qr/connect2_3/); + + local $ENV{PGSERVICE} = 'undefined-service'; + $node->connect_fails( + '', + 'connection with incorrect PGSERVICE and default pg_service.conf', + expected_stdout => + qr/definition of service "undefined-service" not found/); + + # Remove default pg_service.conf. + unlink($srvfile_default); +} + +$node->teardown_node; + +done_testing();