1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-30 21:42:05 +03:00

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 <tfoertsch123@gmail.com>
Author: Ryo Kanbayashi <kanbayashi.dev@gmail.com>
Author: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CAKkG4_nCjx3a_F3gyXHSPWxD8Sd8URaM89wey7fG_9g7KBkOCQ@mail.gmail.com
This commit is contained in:
Michael Paquier
2025-03-27 16:01:38 +09:00
parent ad9a23bc4f
commit 72c2f36d57
2 changed files with 142 additions and 0 deletions

View File

@ -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,

View File

@ -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();