2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-02 08:51:44 +00:00
Files
xcat-core/xCAT-test/unit/pgsqlsetup_native_schema.t
T
2026-09-14 22:56:16 -03:00

132 lines
6.6 KiB
Perl

#!/usr/bin/env perl
use strict;
use warnings;
no warnings 'once';
use FindBin;
use lib "$FindBin::Bin/../lib";
use lib "$FindBin::Bin/../../perl-xCAT";
use File::Path qw(make_path);
use File::Temp qw(tempdir);
use Test::More;
use XCAT::Test::File qw(repo_path);
use DBI;
my $bindir = $ENV{XCAT_TEST_PG_BINDIR};
plan skip_all => 'Set XCAT_TEST_PG_BINDIR to native PostgreSQL binaries' unless $bindir;
BAIL_OUT('The private PostgreSQL fixture must run without root privileges') if $< == 0;
for my $command (qw(initdb pg_ctl postgres psql createdb)) {
BAIL_OUT("Missing native PostgreSQL program $command") unless -x "$bindir/$command";
}
BEGIN {
*CORE::GLOBAL::exit = sub { die bless { status => $_[0] || 0 }, 'PgSchemaTestExit' };
}
my $tmp = tempdir('xcat-pg-schema-XXXXXX', TMPDIR => 1, CLEANUP => 1);
make_path("$tmp/socket", "$tmp/xcatdb");
local $ENV{PGHOST} = "$tmp/socket";
local $ENV{PGPORT} = 55491;
local $ENV{PGUSER} = 'postgres';
local $ENV{PGDATABASE} = 'postgres';
local $ENV{PSQL_HISTORY} = '/dev/null';
local $ENV{XCATROOT} = repo_path('xCAT-server');
local $ENV{XCATCFG} = "SQLite:$tmp/xcatdb";
my $started = 0;
END {
if ($started) {
system("$bindir/pg_ctl", '-D', "$tmp/data", '-m', 'immediate', '-w', 'stop');
}
}
sub quiet_system {
my (@args) = @_;
open(my $log, '>>', "$tmp/commands.log") or die $!;
local *STDOUT = $log;
local *STDERR = $log;
return system(@args);
}
my @init = ("$bindir/initdb", '-D', "$tmp/data", '-U', 'postgres', '--auth-local=trust', '--auth-host=reject', '--no-locale');
push @init, ('-L', $ENV{XCAT_TEST_PG_SHAREDIR}) if $ENV{XCAT_TEST_PG_SHAREDIR};
is(quiet_system(@init), 0, 'native initdb creates a private cluster');
my $start = quiet_system("$bindir/pg_ctl", '-D', "$tmp/data", '-l', "$tmp/server.log", '-o', "-k $tmp/socket -h '' -p $ENV{PGPORT}", '-w', 'start');
is($start, 0, 'private PostgreSQL starts with only a private Unix socket');
BAIL_OUT('Unable to start the private PostgreSQL fixture') if $start != 0;
$started = 1;
my $admin = DBI->connect("dbi:Pg:dbname=postgres;host=$ENV{PGHOST};port=$ENV{PGPORT}", 'postgres', '', { RaiseError => 1, PrintError => 0, AutoCommit => 1 });
my ($version) = $admin->selectrow_array('SHOW server_version_num');
cmp_ok($version, '>=', 150000, 'fixture exercises the PostgreSQL 15 schema privilege contract');
my ($listen) = $admin->selectrow_array('SHOW listen_addresses');
is($listen, '', 'fixture does not listen on TCP');
my ($help, $load_error);
{
local @ARGV = ('--help');
open(my $out, '>', \$help) or die $!;
local *STDOUT = $out;
do($ENV{XCAT_PGSQLSETUP_SOURCE} || repo_path('xCAT-client/bin/pgsqlsetup'));
$load_error = $@;
}
is(ref($load_error), 'PgSchemaTestExit', 'complete pgsqlsetup loads through its help path');
BAIL_OUT("Unable to load pgsqlsetup: $load_error") unless ref($load_error) eq 'PgSchemaTestExit' && $load_error->{status} == 0;
{
local $::osname = 'Linux';
local $::linuxos = 'openeuler24.03sp3';
local $::dbname = 'xcat_schema_fixture';
local $::pgcmddir = $bindir;
local $::adminpassword = 'fixture';
no warnings 'redefine';
local *main::runpgcmd_chkoutput = sub { return quiet_system($_[0]) };
local *main::runpostgrescmd = sub { return quiet_system($_[0]) };
eval { main::setupxcatdb() };
is($@, '', 'complete setupxcatdb creates the database and both roles on native PostgreSQL');
}
my $db = DBI->connect("dbi:Pg:dbname=xcat_schema_fixture;host=$ENV{PGHOST};port=$ENV{PGPORT}", 'postgres', '', { RaiseError => 1, PrintError => 0, AutoCommit => 1 });
my ($owner) = $db->selectrow_array("SELECT pg_get_userbyid(datdba) FROM pg_database WHERE datname = current_database()");
is($owner, 'postgres', 'database ownership remains with postgres');
my ($schema_owner) = $db->selectrow_array("SELECT pg_get_userbyid(nspowner) FROM pg_namespace WHERE nspname = 'public'");
is($schema_owner, 'pg_database_owner', 'public schema retains the native owner');
my ($public_create) = $db->selectrow_array("SELECT count(*) FROM pg_namespace, aclexplode(nspacl) a WHERE nspname='public' AND a.grantee=0 AND a.privilege_type='CREATE'");
is($public_create, 0, 'schema CREATE is not granted to PUBLIC');
for my $role (qw(xcatadm root)) {
my ($create, $usage) = $db->selectrow_array("SELECT has_schema_privilege(?, 'public', 'CREATE'), has_schema_privilege(?, 'public', 'USAGE')", undef, $role, $role);
ok($create, "$role can create public schema tables");
ok($usage, "$role can use the public schema");
my $user = DBI->connect("dbi:Pg:dbname=xcat_schema_fixture;host=$ENV{PGHOST};port=$ENV{PGPORT}", $role, 'fixture', { RaiseError => 0, PrintError => 0, AutoCommit => 1 });
ok($user, "$role connects using its configured database identity");
my $table = 'fixture_' . $role;
my $created = $user && $user->do("CREATE TABLE $table (id integer primary key, value text)");
ok($created, "$role creates an actual table");
my $inserted = $created && $user->do("INSERT INTO $table VALUES (1, 'retained')");
ok($inserted, "$role inserts a row");
my ($value) = $inserted ? $user->selectrow_array("SELECT value FROM $table WHERE id = 1") : (undef);
is($value, 'retained', "$role reads the stored row");
$user->disconnect if $user;
}
$db->disconnect;
$admin->do('DROP DATABASE xcat_schema_fixture');
$admin->do('DROP ROLE xcatadm');
$admin->do('DROP ROLE root');
{
local $::osname = 'Linux';
local $::linuxos = 'openeuler24.03sp3';
local $::dbname = 'xcat_schema_failure';
local $::pgcmddir = $bindir;
local $::adminpassword = 'fixture';
my ($continued, $failed_command) = (0, undef);
no warnings 'redefine';
local *main::runpgcmd_chkoutput = sub { return quiet_system($_[0]) };
local *main::runpostgrescmd = sub {
my $failure_db = DBI->connect("dbi:Pg:dbname=xcat_schema_failure;host=$ENV{PGHOST};port=$ENV{PGPORT}", 'postgres', '', { RaiseError => 1, PrintError => 0, AutoCommit => 1 });
$failure_db->do('DROP SCHEMA public');
$failure_db->disconnect;
$failed_command = quiet_system($_[0]);
return $failed_command;
};
eval { main::setupxcatdb(); $continued = 1; };
my $error = $@;
ok(defined($failed_command) && $failed_command != 0, 'native psql returns failure when the schema grant cannot run');
is(ref($error) ? $error->{status} : undef, 1, 'actual native schema grant failure fails the CLI');
is($continued, 0, 'actual native schema grant failure prevents subsequent setup');
}
$admin->disconnect;
is(quiet_system("$bindir/pg_ctl", '-D', "$tmp/data", '-m', 'fast', '-w', 'stop'), 0, 'private PostgreSQL shuts down cleanly');
$started = 0;
done_testing();