Hi,
while working on installcheck support with meson, that currently running
installcheck-world fails regularly with meson and occasionally with make.
A way to quite reliably reproduce this with make is
make -s -j48 -C contrib/ USE_MODULE_DB=1 installcheck-adminpack-recurse
installcheck-passwordcheck-recurse
that will fail with diffs like:
diff -du10
/home/andres/src/postgresql/contrib/passwordcheck/expected/passwordcheck.out
/home/andres/build/postgres/dev-assert/vpath/contrib/passwordcheck/res>
---
/home/andres/src/postgresql/contrib/passwordcheck/expected/passwordcheck.out
2022-10-03 15:56:57.900326662 -0700
+++
/home/andres/build/postgres/dev-assert/vpath/contrib/passwordcheck/results/passwordcheck.out
2022-10-03 15:56:59.930329973 -0700
@@ -1,19 +1,22 @@
LOAD 'passwordcheck';
CREATE USER regress_user1;
-- ok
ALTER USER regress_user1 PASSWORD 'a_nice_long_password';
+ERROR: tuple concurrently deleted
-- error: too short
ALTER USER regress_user1 PASSWORD 'tooshrt';
-ERROR: password is too short
+ERROR: role "regress_user1" does not exist
-- error: contains user name
ALTER USER regress_user1 PASSWORD 'xyzregress_user1';
-ERROR: password must not contain user name
+ERROR: role "regress_user1" does not exist
-- error: contains only letters
LOAD 'passwordcheck';
CREATE USER regress_user1;
-- ok
ALTER USER regress_user1 PASSWORD 'a_nice_long_password';
+ERROR: tuple concurrently deleted
-- error: too short
ALTER USER regress_user1 PASSWORD 'tooshrt';
-ERROR: password is too short
+ERROR: role "regress_user1" does not exist
-- error: contains user name
That's not surprising, given the common name of "regress_user1".
The attached patch fixes a number of instances of this issue. With it I got
through ~5 iterations of installcheck-world on ac, and >30 iterations with
meson.
There's a few further roles that seem to pose some danger goign forward:
./contrib/file_fdw/sql/file_fdw.sql:CREATE ROLE regress_no_priv_user LOGIN;
-- has priv but no user mapping
./contrib/postgres_fdw/sql/postgres_fdw.sql:CREATE ROLE regress_view_owner
SUPERUSER;
./contrib/postgres_fdw/sql/postgres_fdw.sql:CREATE ROLE regress_nosuper
NOSUPERUSER;
./contrib/passwordcheck/sql/passwordcheck.sql:CREATE USER
regress_passwordcheck_user1;
./contrib/citext/sql/create_index_acl.sql:CREATE ROLE regress_minimal;
./src/test/modules/test_rls_hooks/sql/test_rls_hooks.sql:CREATE ROLE regress_r1;
./src/test/modules/test_rls_hooks/sql/test_rls_hooks.sql:CREATE ROLE regress_s1;
./src/test/modules/test_oat_hooks/sql/test_oat_hooks.sql:CREATE ROLE
regress_role_joe;
./src/test/modules/test_oat_hooks/sql/test_oat_hooks.sql:CREATE USER
regress_test_user;
./src/test/modules/unsafe_tests/sql/rolenames.sql:CREATE ROLE regress_testrol0
SUPERUSER LOGIN;
./src/test/modules/unsafe_tests/sql/rolenames.sql:CREATE ROLE regress_testrolx
SUPERUSER LOGIN;
./src/test/modules/unsafe_tests/sql/rolenames.sql:CREATE ROLE regress_testrol2
SUPERUSER;
./src/test/modules/unsafe_tests/sql/rolenames.sql:CREATE ROLE regress_testrol1
SUPERUSER LOGIN IN ROLE regress_testrol2;
./src/test/modules/unsafe_tests/sql/rolenames.sql:CREATE ROLE
regress_role_haspriv;
./src/test/modules/unsafe_tests/sql/rolenames.sql:CREATE ROLE
regress_role_nopriv;
./src/test/modules/unsafe_tests/sql/guc_privs.sql:CREATE ROLE regress_admin
SUPERUSER;
./src/test/modules/test_ddl_deparse/sql/alter_function.sql:CREATE ROLE
regress_alter_function_role;
BTW, shouldn't src/test/modules/unsafe_tests use the PG_TEST_EXTRA mechanism
somehow? Seems not great to run it as part of installcheck-world, if we don't
want to run it as part of installcheck.
A second issue I noticed is that advisory_lock.sql often fails, because the
pg_locks queries don't restrict to the current database. Patch attached.
I haven't seen that with autoconf installcheck-world, presumably because of
this:
# There are too many interdependencies between the subdirectories, so
# don't attempt parallel make here.
.NOTPARALLEL:
With those two patches applied, I got through 10 iterations of running all
regress / isolation tests concurrently with meson without failures.
I attached the meson patch as well, but just because I used it to to get to
these patches.
Greetings,
Andres Freund
>From fee4e186f18134df929618bbd00cc1519149f144 Mon Sep 17 00:00:00 2001
From: Andres Freund <[email protected]>
Date: Sun, 25 Sep 2022 16:49:51 -0700
Subject: [PATCH v2 1/3] tests: Rename conflicting role names
These cause problems when running installcheck concurrently.
---
src/pl/plperl/expected/plperl_setup.out | 30 +++++++++----------
src/pl/plperl/sql/plperl_setup.sql | 30 +++++++++----------
contrib/adminpack/expected/adminpack.out | 20 ++++++-------
contrib/adminpack/sql/adminpack.sql | 20 ++++++-------
.../passwordcheck/expected/passwordcheck.out | 16 +++++-----
contrib/passwordcheck/sql/passwordcheck.sql | 16 +++++-----
6 files changed, 66 insertions(+), 66 deletions(-)
diff --git a/src/pl/plperl/expected/plperl_setup.out b/src/pl/plperl/expected/plperl_setup.out
index 5234febefd6..5537a95ccc2 100644
--- a/src/pl/plperl/expected/plperl_setup.out
+++ b/src/pl/plperl/expected/plperl_setup.out
@@ -4,9 +4,9 @@
-- Before going ahead with the to-be-tested installations, verify that
-- a non-superuser is allowed to install plperl (but not plperlu) when
-- suitable permissions have been granted.
-CREATE USER regress_user1;
-CREATE USER regress_user2;
-SET ROLE regress_user1;
+CREATE USER regress_plperl_user1;
+CREATE USER regress_plperl_user2;
+SET ROLE regress_plperl_user1;
CREATE EXTENSION plperl; -- fail
ERROR: permission denied to create extension "plperl"
HINT: Must have CREATE privilege on current database to create this extension.
@@ -16,18 +16,18 @@ HINT: Must be superuser to create this extension.
RESET ROLE;
DO $$
begin
- execute format('grant create on database %I to regress_user1',
+ execute format('grant create on database %I to regress_plperl_user1',
current_database());
end;
$$;
-SET ROLE regress_user1;
+SET ROLE regress_plperl_user1;
CREATE EXTENSION plperl;
CREATE EXTENSION plperlu; -- fail
ERROR: permission denied to create extension "plperlu"
HINT: Must be superuser to create this extension.
CREATE SCHEMA plperl_setup_scratch;
SET search_path = plperl_setup_scratch;
-GRANT ALL ON SCHEMA plperl_setup_scratch TO regress_user2;
+GRANT ALL ON SCHEMA plperl_setup_scratch TO regress_plperl_user2;
CREATE FUNCTION foo1() returns int language plperl as '1;';
SELECT foo1();
foo1
@@ -38,15 +38,15 @@ SELECT foo1();
-- Must reconnect to avoid failure with non-MULTIPLICITY Perl interpreters
\c -
SET search_path = plperl_setup_scratch;
-SET ROLE regress_user1;
+SET ROLE regress_plperl_user1;
-- Should be able to change privileges on the language
revoke all on language plperl from public;
-SET ROLE regress_user2;
+SET ROLE regress_plperl_user2;
CREATE FUNCTION foo2() returns int language plperl as '2;'; -- fail
ERROR: permission denied for language plperl
-SET ROLE regress_user1;
-grant usage on language plperl to regress_user2;
-SET ROLE regress_user2;
+SET ROLE regress_plperl_user1;
+grant usage on language plperl to regress_plperl_user2;
+SET ROLE regress_plperl_user2;
CREATE FUNCTION foo2() returns int language plperl as '2;';
SELECT foo2();
foo2
@@ -54,7 +54,7 @@ SELECT foo2();
2
(1 row)
-SET ROLE regress_user1;
+SET ROLE regress_plperl_user1;
-- Should be able to drop the extension, but not the language per se
DROP LANGUAGE plperl CASCADE;
ERROR: cannot drop language plperl because extension plperl requires it
@@ -65,9 +65,9 @@ DETAIL: drop cascades to function foo1()
drop cascades to function foo2()
-- Clean up
RESET ROLE;
-DROP OWNED BY regress_user1;
-DROP USER regress_user1;
-DROP USER regress_user2;
+DROP OWNED BY regress_plperl_user1;
+DROP USER regress_plperl_user1;
+DROP USER regress_plperl_user2;
-- Now install the versions that will be used by subsequent test scripts.
CREATE EXTENSION plperl;
CREATE EXTENSION plperlu;
diff --git a/src/pl/plperl/sql/plperl_setup.sql b/src/pl/plperl/sql/plperl_setup.sql
index a89cf56617e..0eac9156294 100644
--- a/src/pl/plperl/sql/plperl_setup.sql
+++ b/src/pl/plperl/sql/plperl_setup.sql
@@ -6,10 +6,10 @@
-- a non-superuser is allowed to install plperl (but not plperlu) when
-- suitable permissions have been granted.
-CREATE USER regress_user1;
-CREATE USER regress_user2;
+CREATE USER regress_plperl_user1;
+CREATE USER regress_plperl_user2;
-SET ROLE regress_user1;
+SET ROLE regress_plperl_user1;
CREATE EXTENSION plperl; -- fail
CREATE EXTENSION plperlu; -- fail
@@ -18,18 +18,18 @@ RESET ROLE;
DO $$
begin
- execute format('grant create on database %I to regress_user1',
+ execute format('grant create on database %I to regress_plperl_user1',
current_database());
end;
$$;
-SET ROLE regress_user1;
+SET ROLE regress_plperl_user1;
CREATE EXTENSION plperl;
CREATE EXTENSION plperlu; -- fail
CREATE SCHEMA plperl_setup_scratch;
SET search_path = plperl_setup_scratch;
-GRANT ALL ON SCHEMA plperl_setup_scratch TO regress_user2;
+GRANT ALL ON SCHEMA plperl_setup_scratch TO regress_plperl_user2;
CREATE FUNCTION foo1() returns int language plperl as '1;';
SELECT foo1();
@@ -38,25 +38,25 @@ SELECT foo1();
\c -
SET search_path = plperl_setup_scratch;
-SET ROLE regress_user1;
+SET ROLE regress_plperl_user1;
-- Should be able to change privileges on the language
revoke all on language plperl from public;
-SET ROLE regress_user2;
+SET ROLE regress_plperl_user2;
CREATE FUNCTION foo2() returns int language plperl as '2;'; -- fail
-SET ROLE regress_user1;
+SET ROLE regress_plperl_user1;
-grant usage on language plperl to regress_user2;
+grant usage on language plperl to regress_plperl_user2;
-SET ROLE regress_user2;
+SET ROLE regress_plperl_user2;
CREATE FUNCTION foo2() returns int language plperl as '2;';
SELECT foo2();
-SET ROLE regress_user1;
+SET ROLE regress_plperl_user1;
-- Should be able to drop the extension, but not the language per se
DROP LANGUAGE plperl CASCADE;
@@ -64,9 +64,9 @@ DROP EXTENSION plperl CASCADE;
-- Clean up
RESET ROLE;
-DROP OWNED BY regress_user1;
-DROP USER regress_user1;
-DROP USER regress_user2;
+DROP OWNED BY regress_plperl_user1;
+DROP USER regress_plperl_user1;
+DROP USER regress_plperl_user2;
-- Now install the versions that will be used by subsequent test scripts.
CREATE EXTENSION plperl;
diff --git a/contrib/adminpack/expected/adminpack.out b/contrib/adminpack/expected/adminpack.out
index 76aafe6316a..6bcf2217f25 100644
--- a/contrib/adminpack/expected/adminpack.out
+++ b/contrib/adminpack/expected/adminpack.out
@@ -36,10 +36,10 @@ SELECT pg_read_file('test_file1');
-- disallowed file paths for non-superusers and users who are
-- not members of pg_write_server_files
-CREATE ROLE regress_user1;
-GRANT pg_read_all_settings TO regress_user1;
-GRANT EXECUTE ON FUNCTION pg_file_write(text,text,bool) TO regress_user1;
-SET ROLE regress_user1;
+CREATE ROLE regress_adminpack_user1;
+GRANT pg_read_all_settings TO regress_adminpack_user1;
+GRANT EXECUTE ON FUNCTION pg_file_write(text,text,bool) TO regress_adminpack_user1;
+SET ROLE regress_adminpack_user1;
SELECT pg_file_write('../test_file0', 'test0', false);
ERROR: path must be in or below the current directory
SELECT pg_file_write('/tmp/test_file0', 'test0', false);
@@ -53,9 +53,9 @@ SELECT pg_file_write(current_setting('data_directory') || '/test_file4', 'test4'
SELECT pg_file_write(current_setting('data_directory') || '/../test_file4', 'test4', false);
ERROR: absolute path not allowed
RESET ROLE;
-REVOKE EXECUTE ON FUNCTION pg_file_write(text,text,bool) FROM regress_user1;
-REVOKE pg_read_all_settings FROM regress_user1;
-DROP ROLE regress_user1;
+REVOKE EXECUTE ON FUNCTION pg_file_write(text,text,bool) FROM regress_adminpack_user1;
+REVOKE pg_read_all_settings FROM regress_adminpack_user1;
+DROP ROLE regress_adminpack_user1;
-- sync
SELECT pg_file_sync('test_file1'); -- sync file
pg_file_sync
@@ -153,8 +153,8 @@ SELECT pg_file_unlink('test_file4');
(1 row)
-- superuser checks
-CREATE USER regress_user1;
-SET ROLE regress_user1;
+CREATE USER regress_adminpack_user1;
+SET ROLE regress_adminpack_user1;
SELECT pg_file_write('test_file0', 'test0', false);
ERROR: permission denied for function pg_file_write
SELECT pg_file_sync('test_file0');
@@ -167,6 +167,6 @@ ERROR: permission denied for function pg_file_unlink
SELECT pg_logdir_ls();
ERROR: permission denied for function pg_logdir_ls
RESET ROLE;
-DROP USER regress_user1;
+DROP USER regress_adminpack_user1;
-- no further tests for pg_logdir_ls() because it depends on the
-- server's logging setup
diff --git a/contrib/adminpack/sql/adminpack.sql b/contrib/adminpack/sql/adminpack.sql
index 918d0bdc65e..5776c9af0d1 100644
--- a/contrib/adminpack/sql/adminpack.sql
+++ b/contrib/adminpack/sql/adminpack.sql
@@ -14,20 +14,20 @@ SELECT pg_read_file('test_file1');
-- disallowed file paths for non-superusers and users who are
-- not members of pg_write_server_files
-CREATE ROLE regress_user1;
+CREATE ROLE regress_adminpack_user1;
-GRANT pg_read_all_settings TO regress_user1;
-GRANT EXECUTE ON FUNCTION pg_file_write(text,text,bool) TO regress_user1;
+GRANT pg_read_all_settings TO regress_adminpack_user1;
+GRANT EXECUTE ON FUNCTION pg_file_write(text,text,bool) TO regress_adminpack_user1;
-SET ROLE regress_user1;
+SET ROLE regress_adminpack_user1;
SELECT pg_file_write('../test_file0', 'test0', false);
SELECT pg_file_write('/tmp/test_file0', 'test0', false);
SELECT pg_file_write(current_setting('data_directory') || '/test_file4', 'test4', false);
SELECT pg_file_write(current_setting('data_directory') || '/../test_file4', 'test4', false);
RESET ROLE;
-REVOKE EXECUTE ON FUNCTION pg_file_write(text,text,bool) FROM regress_user1;
-REVOKE pg_read_all_settings FROM regress_user1;
-DROP ROLE regress_user1;
+REVOKE EXECUTE ON FUNCTION pg_file_write(text,text,bool) FROM regress_adminpack_user1;
+REVOKE pg_read_all_settings FROM regress_adminpack_user1;
+DROP ROLE regress_adminpack_user1;
-- sync
SELECT pg_file_sync('test_file1'); -- sync file
@@ -59,8 +59,8 @@ SELECT pg_file_unlink('test_file4');
-- superuser checks
-CREATE USER regress_user1;
-SET ROLE regress_user1;
+CREATE USER regress_adminpack_user1;
+SET ROLE regress_adminpack_user1;
SELECT pg_file_write('test_file0', 'test0', false);
SELECT pg_file_sync('test_file0');
@@ -69,7 +69,7 @@ SELECT pg_file_unlink('test_file0');
SELECT pg_logdir_ls();
RESET ROLE;
-DROP USER regress_user1;
+DROP USER regress_adminpack_user1;
-- no further tests for pg_logdir_ls() because it depends on the
diff --git a/contrib/passwordcheck/expected/passwordcheck.out b/contrib/passwordcheck/expected/passwordcheck.out
index e04cda6bd95..2027681daf6 100644
--- a/contrib/passwordcheck/expected/passwordcheck.out
+++ b/contrib/passwordcheck/expected/passwordcheck.out
@@ -1,19 +1,19 @@
LOAD 'passwordcheck';
-CREATE USER regress_user1;
+CREATE USER regress_passwordcheck_user1;
-- ok
-ALTER USER regress_user1 PASSWORD 'a_nice_long_password';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
-- error: too short
-ALTER USER regress_user1 PASSWORD 'tooshrt';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
ERROR: password is too short
-- error: contains user name
-ALTER USER regress_user1 PASSWORD 'xyzregress_user1';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'xyzregress_passwordcheck_user1';
ERROR: password must not contain user name
-- error: contains only letters
-ALTER USER regress_user1 PASSWORD 'alessnicelongpassword';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'alessnicelongpassword';
ERROR: password must contain both letters and nonletters
-- encrypted ok (password is "secret")
-ALTER USER regress_user1 PASSWORD 'md51a44d829a20a23eac686d9f0d258af13';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'md592350e12ac34e52dd598f90893bb3ae7';
-- error: password is user name
-ALTER USER regress_user1 PASSWORD 'md5e589150ae7d28f93333afae92b36ef48';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'md507a112732ed9f2087fa90b192d44e358';
ERROR: password must not equal user name
-DROP USER regress_user1;
+DROP USER regress_passwordcheck_user1;
diff --git a/contrib/passwordcheck/sql/passwordcheck.sql b/contrib/passwordcheck/sql/passwordcheck.sql
index d98796ac494..1fbd6b0e96e 100644
--- a/contrib/passwordcheck/sql/passwordcheck.sql
+++ b/contrib/passwordcheck/sql/passwordcheck.sql
@@ -1,23 +1,23 @@
LOAD 'passwordcheck';
-CREATE USER regress_user1;
+CREATE USER regress_passwordcheck_user1;
-- ok
-ALTER USER regress_user1 PASSWORD 'a_nice_long_password';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
-- error: too short
-ALTER USER regress_user1 PASSWORD 'tooshrt';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
-- error: contains user name
-ALTER USER regress_user1 PASSWORD 'xyzregress_user1';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'xyzregress_passwordcheck_user1';
-- error: contains only letters
-ALTER USER regress_user1 PASSWORD 'alessnicelongpassword';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'alessnicelongpassword';
-- encrypted ok (password is "secret")
-ALTER USER regress_user1 PASSWORD 'md51a44d829a20a23eac686d9f0d258af13';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'md592350e12ac34e52dd598f90893bb3ae7';
-- error: password is user name
-ALTER USER regress_user1 PASSWORD 'md5e589150ae7d28f93333afae92b36ef48';
+ALTER USER regress_passwordcheck_user1 PASSWORD 'md507a112732ed9f2087fa90b192d44e358';
-DROP USER regress_user1;
+DROP USER regress_passwordcheck_user1;
--
2.37.3.542.gdd3f6c4cae
>From 36db621755bd4e31e9431e432c7bdc3823f71db5 Mon Sep 17 00:00:00 2001
From: Andres Freund <[email protected]>
Date: Mon, 3 Oct 2022 16:30:36 -0700
Subject: [PATCH v2 2/3] test: Restrict pg_locks queries in advisory_locks.sql
to current database
Otherwise testing an existing installation can fail, if there are other locks,
e.g. from one of the isolation tests.
Author:
Reviewed-by:
Discussion: https://postgr.es/m/
Backpatch:
---
src/test/regress/expected/advisory_lock.out | 31 ++++++++++----------
src/test/regress/sql/advisory_lock.sql | 32 +++++++++++----------
2 files changed, 33 insertions(+), 30 deletions(-)
diff --git a/src/test/regress/expected/advisory_lock.out b/src/test/regress/expected/advisory_lock.out
index 2a2df6f7e4b..02e07765ac2 100644
--- a/src/test/regress/expected/advisory_lock.out
+++ b/src/test/regress/expected/advisory_lock.out
@@ -1,6 +1,7 @@
--
-- ADVISORY LOCKS
--
+SELECT oid AS datoid FROM pg_database WHERE datname = current_database() \gset
BEGIN;
SELECT
pg_advisory_xact_lock(1), pg_advisory_xact_lock_shared(2),
@@ -11,7 +12,7 @@ SELECT
(1 row)
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
locktype | classid | objid | objsubid | mode | granted
----------+---------+-------+----------+---------------+---------
@@ -28,7 +29,7 @@ SELECT pg_advisory_unlock_all();
(1 row)
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
count
-------
4
@@ -49,7 +50,7 @@ WARNING: you don't own a lock of type ShareLock
-- automatically release xact locks at commit
COMMIT;
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
count
-------
0
@@ -66,7 +67,7 @@ SELECT
(1 row)
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
locktype | classid | objid | objsubid | mode | granted
----------+---------+-------+----------+---------------+---------
@@ -86,7 +87,7 @@ SELECT
ROLLBACK;
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
locktype | classid | objid | objsubid | mode | granted
----------+---------+-------+----------+---------------+---------
@@ -111,7 +112,7 @@ WARNING: you don't own a lock of type ShareLock
t | f | t | f | t | f | t | f
(1 row)
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
count
-------
0
@@ -128,7 +129,7 @@ SELECT
(1 row)
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
locktype | classid | objid | objsubid | mode | granted
----------+---------+-------+----------+---------------+---------
@@ -148,7 +149,7 @@ SELECT
ROLLBACK;
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
locktype | classid | objid | objsubid | mode | granted
----------+---------+-------+----------+---------------+---------
@@ -165,7 +166,7 @@ SELECT pg_advisory_unlock_all();
(1 row)
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
count
-------
0
@@ -184,7 +185,7 @@ SELECT
(1 row)
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
locktype | classid | objid | objsubid | mode | granted
----------+---------+-------+----------+---------------+---------
@@ -195,7 +196,7 @@ SELECT locktype, classid, objid, objsubid, mode, granted
(4 rows)
COMMIT;
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
count
-------
0
@@ -213,7 +214,7 @@ SELECT
(1 row)
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
locktype | classid | objid | objsubid | mode | granted
----------+---------+-------+----------+---------------+---------
@@ -233,7 +234,7 @@ SELECT
t | t | t | t | t | t | t | t
(1 row)
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
count
-------
0
@@ -251,7 +252,7 @@ SELECT
(1 row)
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
locktype | classid | objid | objsubid | mode | granted
----------+---------+-------+----------+---------------+---------
@@ -267,7 +268,7 @@ SELECT pg_advisory_unlock_all();
(1 row)
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
count
-------
0
diff --git a/src/test/regress/sql/advisory_lock.sql b/src/test/regress/sql/advisory_lock.sql
index 57c47c0faca..8513ab8e98f 100644
--- a/src/test/regress/sql/advisory_lock.sql
+++ b/src/test/regress/sql/advisory_lock.sql
@@ -2,6 +2,8 @@
-- ADVISORY LOCKS
--
+SELECT oid AS datoid FROM pg_database WHERE datname = current_database() \gset
+
BEGIN;
SELECT
@@ -9,14 +11,14 @@ SELECT
pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2);
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
-- pg_advisory_unlock_all() shouldn't release xact locks
SELECT pg_advisory_unlock_all();
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
-- can't unlock xact locks
@@ -28,7 +30,7 @@ SELECT
-- automatically release xact locks at commit
COMMIT;
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
BEGIN;
@@ -39,7 +41,7 @@ SELECT
pg_advisory_xact_lock(1, 1), pg_advisory_xact_lock_shared(2, 2);
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
SELECT
@@ -49,7 +51,7 @@ SELECT
ROLLBACK;
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
@@ -60,7 +62,7 @@ SELECT
pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1),
pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2);
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
BEGIN;
@@ -71,7 +73,7 @@ SELECT
pg_advisory_lock(1, 1), pg_advisory_lock_shared(2, 2);
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
SELECT
@@ -81,14 +83,14 @@ SELECT
ROLLBACK;
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
-- releasing all session locks
SELECT pg_advisory_unlock_all();
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
BEGIN;
@@ -102,12 +104,12 @@ SELECT
pg_advisory_xact_lock_shared(2, 2), pg_advisory_xact_lock_shared(2, 2);
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
COMMIT;
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
-- grabbing session locks multiple times
@@ -118,7 +120,7 @@ SELECT
pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2);
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
SELECT
@@ -127,7 +129,7 @@ SELECT
pg_advisory_unlock(1, 1), pg_advisory_unlock(1, 1),
pg_advisory_unlock_shared(2, 2), pg_advisory_unlock_shared(2, 2);
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
-- .. and releasing them all at once
@@ -138,9 +140,9 @@ SELECT
pg_advisory_lock_shared(2, 2), pg_advisory_lock_shared(2, 2);
SELECT locktype, classid, objid, objsubid, mode, granted
- FROM pg_locks WHERE locktype = 'advisory'
+ FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid
ORDER BY classid, objid, objsubid;
SELECT pg_advisory_unlock_all();
-SELECT count(*) FROM pg_locks WHERE locktype = 'advisory';
+SELECT count(*) FROM pg_locks WHERE locktype = 'advisory' AND database = :datoid;
--
2.37.3.542.gdd3f6c4cae
>From 5f546b4d05747eff04d81dc15437de27bbaad7fb Mon Sep 17 00:00:00 2001
From: Andres Freund <[email protected]>
Date: Sun, 25 Sep 2022 16:57:01 -0700
Subject: [PATCH v2 3/3] wip: meson: Add installcheck equivalent
run all tests that support running against existing server:
$ meson test --setup running
run just the main pg_regress tests against existing server:
$ meson test --setup running main-running/regress
---
contrib/basic_archive/meson.build | 1 +
contrib/pg_freespacemap/meson.build | 3 +
contrib/pg_stat_statements/meson.build | 4 +
contrib/pg_walinspect/meson.build | 3 +
contrib/test_decoding/meson.build | 5 ++
src/interfaces/ecpg/test/meson.build | 1 +
src/test/isolation/meson.build | 1 +
src/test/modules/commit_ts/meson.build | 3 +
src/test/modules/snapshot_too_old/meson.build | 3 +
src/test/modules/test_oat_hooks/meson.build | 1 +
src/test/modules/test_pg_dump/meson.build | 2 +
src/test/modules/worker_spi/meson.build | 4 +-
src/test/regress/meson.build | 1 +
.cirrus.yml | 15 ++++
meson.build | 87 ++++++++++++++++---
15 files changed, 120 insertions(+), 14 deletions(-)
diff --git a/contrib/basic_archive/meson.build b/contrib/basic_archive/meson.build
index b67cbef60bd..0600c04940b 100644
--- a/contrib/basic_archive/meson.build
+++ b/contrib/basic_archive/meson.build
@@ -19,5 +19,6 @@ tests += {
'regress_args': [
'--temp-config', files('basic_archive.conf'),
],
+ 'runningcheck': false,
},
}
diff --git a/contrib/pg_freespacemap/meson.build b/contrib/pg_freespacemap/meson.build
index f795014d7ca..a8703660c73 100644
--- a/contrib/pg_freespacemap/meson.build
+++ b/contrib/pg_freespacemap/meson.build
@@ -25,5 +25,8 @@ tests += {
'regress_args': [
'--temp-config', files('pg_freespacemap.conf')
],
+ # Disabled because these tests require "autovacuum=off", which
+ # typical runningcheck users do not have (e.g. buildfarm clients).
+ 'runningcheck': false,
},
}
diff --git a/contrib/pg_stat_statements/meson.build b/contrib/pg_stat_statements/meson.build
index ac117d2fc1d..07c5d5d4442 100644
--- a/contrib/pg_stat_statements/meson.build
+++ b/contrib/pg_stat_statements/meson.build
@@ -31,5 +31,9 @@ tests += {
'pg_stat_statements',
],
'regress_args': ['--temp-config', files('pg_stat_statements.conf')],
+ # Disabled because these tests require
+ # "shared_preload_libraries=pg_stat_statements", which typical
+ # runningcheck users do not have (e.g. buildfarm clients).
+ 'runningcheck': false,
},
}
diff --git a/contrib/pg_walinspect/meson.build b/contrib/pg_walinspect/meson.build
index d6b27877dd0..15a052ec879 100644
--- a/contrib/pg_walinspect/meson.build
+++ b/contrib/pg_walinspect/meson.build
@@ -22,6 +22,9 @@ tests += {
'sql': [
'pg_walinspect',
],
+ # Disabled because these tests require "wal_level=replica", which
+ # some runningcheck users do not have (e.g. buildfarm clients).
'regress_args': ['--temp-config', files('walinspect.conf')],
+ 'runningcheck': false,
},
}
diff --git a/contrib/test_decoding/meson.build b/contrib/test_decoding/meson.build
index dd7cb0101ad..48b9c866a43 100644
--- a/contrib/test_decoding/meson.build
+++ b/contrib/test_decoding/meson.build
@@ -37,6 +37,9 @@ tests += {
'regress_args': [
'--temp-config', files('logical.conf'),
],
+ # Disabled because these tests require "wal_level=logical", which
+ # typical runningcheck users do not have (e.g. buildfarm clients).
+ 'runningcheck': false,
},
'isolation': {
'specs': [
@@ -54,6 +57,8 @@ tests += {
'regress_args': [
'--temp-config', files('logical.conf'),
],
+ # see above
+ 'runningcheck': false,
},
'tap': {
'tests': [
diff --git a/src/interfaces/ecpg/test/meson.build b/src/interfaces/ecpg/test/meson.build
index f0ace641f0c..21331501a5a 100644
--- a/src/interfaces/ecpg/test/meson.build
+++ b/src/interfaces/ecpg/test/meson.build
@@ -79,6 +79,7 @@ tests += {
'test_kwargs': {
'depends': ecpg_test_dependencies,
},
+ 'dbname': 'ecpg1_regression,ecpg2_regression',
'regress_args': ecpg_regress_args,
},
}
diff --git a/src/test/isolation/meson.build b/src/test/isolation/meson.build
index c7656fd4609..6c748b08209 100644
--- a/src/test/isolation/meson.build
+++ b/src/test/isolation/meson.build
@@ -54,5 +54,6 @@ tests += {
'priority': 40,
'timeout': 1000,
},
+ 'dbname': 'isolation_regression',
},
}
diff --git a/src/test/modules/commit_ts/meson.build b/src/test/modules/commit_ts/meson.build
index 60cb12164d2..fa86e70e880 100644
--- a/src/test/modules/commit_ts/meson.build
+++ b/src/test/modules/commit_ts/meson.build
@@ -6,6 +6,9 @@ tests += {
'sql': [
'commit_timestamp',
],
+ # Disabled because these tests require "track_commit_timestamp = on",
+ # which typical runningcheck users do not have (e.g. buildfarm clients).
+ 'runningcheck': false,
},
'tap': {
'tests': [
diff --git a/src/test/modules/snapshot_too_old/meson.build b/src/test/modules/snapshot_too_old/meson.build
index efd3f1f113b..5094b52949b 100644
--- a/src/test/modules/snapshot_too_old/meson.build
+++ b/src/test/modules/snapshot_too_old/meson.build
@@ -10,5 +10,8 @@ tests += {
'sto_using_hash_index',
],
'regress_args': ['--temp-config', files('sto.conf')],
+ # Disabled because these tests require "old_snapshot_threshold" >= 0, which
+ # typical runningcheck users do not have (e.g. buildfarm clients).
+ 'runningcheck': false,
},
}
diff --git a/src/test/modules/test_oat_hooks/meson.build b/src/test/modules/test_oat_hooks/meson.build
index 5faf0459777..b2faab98a5f 100644
--- a/src/test/modules/test_oat_hooks/meson.build
+++ b/src/test/modules/test_oat_hooks/meson.build
@@ -14,5 +14,6 @@ tests += {
'test_oat_hooks',
],
'regress_args': ['--no-locale', '--encoding=UTF8'],
+ 'runningcheck': false,
},
}
diff --git a/src/test/modules/test_pg_dump/meson.build b/src/test/modules/test_pg_dump/meson.build
index 41021829f3a..73f1fcf9428 100644
--- a/src/test/modules/test_pg_dump/meson.build
+++ b/src/test/modules/test_pg_dump/meson.build
@@ -13,6 +13,8 @@ tests += {
'sql': [
'test_pg_dump',
],
+ # doesn't delete its user
+ 'runningcheck': false,
},
'tap': {
'tests': [
diff --git a/src/test/modules/worker_spi/meson.build b/src/test/modules/worker_spi/meson.build
index 32acad883b2..5491248f16f 100644
--- a/src/test/modules/worker_spi/meson.build
+++ b/src/test/modules/worker_spi/meson.build
@@ -21,6 +21,8 @@ tests += {
'sql': [
'worker_spi',
],
- 'regress_args': ['--temp-config', files('dynamic.conf'), '--dbname=contrib_regression'],
+ 'dbname': 'contrib_regression',
+ 'regress_args': ['--temp-config', files('dynamic.conf')],
+ 'runningcheck': false,
},
}
diff --git a/src/test/regress/meson.build b/src/test/regress/meson.build
index 03de591b0c7..18a5e1acf7c 100644
--- a/src/test/regress/meson.build
+++ b/src/test/regress/meson.build
@@ -67,5 +67,6 @@ tests += {
'priority': 50,
'timeout': 1000,
},
+ 'dbname': 'regression',
},
}
diff --git a/.cirrus.yml b/.cirrus.yml
index 531cfe96f65..e5416371049 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -122,6 +122,21 @@ task:
meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
EOF
+ # test runningcheck, freebsd chosen because it's currently fast enough
+ test_running_script: |
+ su postgres <<-EOF
+ set -e
+ ulimit -c unlimited
+ meson test $MTEST_ARGS --quiet --suite setup
+ export LD_LIBRARY_PATH="$(pwd)/build/tmp_install/usr/local/pgsql/lib/:$LD_LIBRARY_PATH"
+ mkdir -p build/testrun
+ build/tmp_install/usr/local/pgsql/bin/initdb -N build/runningcheck --no-instructions -A trust
+ echo "include '$(pwd)/src/tools/ci/pg_ci_base.conf'" >> build/runningcheck/postgresql.conf
+ build/tmp_install/usr/local/pgsql/bin/pg_ctl -c -o '-c fsync=off' -D build/runningcheck -l build/testrun/runningcheck.log start
+ meson test $MTEST_ARGS --num-processes ${TEST_JOBS} --setup running
+ build/tmp_install/usr/local/pgsql/bin/pg_ctl -D build/runningcheck stop
+ EOF
+
on_failure:
<<: *on_failure_meson
cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
diff --git a/meson.build b/meson.build
index 253994931e8..48e6a108bfe 100644
--- a/meson.build
+++ b/meson.build
@@ -2820,6 +2820,18 @@ endif
# Test Generation
###############################################################
+# when using a meson version understanding exclude_suites, define a 'default'
+# test setup that excludes tests running against a pre-existing install and a
+# 'running' setup that conflicts with creation of the temporary installation
+# and tap tests (which don't support running against a running server).
+running_suites = []
+install_suites = []
+if meson.version().version_compare('>=0.57')
+ runningcheck = true
+else
+ runningcheck = false
+endif
+
testwrap = files('src/tools/testwrap')
foreach test_dir : tests
@@ -2827,7 +2839,6 @@ foreach test_dir : tests
testwrap,
'--basedir', meson.build_root(),
'--srcdir', test_dir['sd'],
- '--testgroup', test_dir['name'],
]
foreach kind, v : test_dir
@@ -2840,41 +2851,51 @@ foreach test_dir : tests
if kind in ['regress', 'isolation', 'ecpg']
if kind == 'regress'
runner = pg_regress
+ fallback_dbname = 'regression_@0@'
elif kind == 'isolation'
runner = pg_isolation_regress
+ fallback_dbname = 'isolation_regression_@0@'
elif kind == 'ecpg'
runner = pg_regress_ecpg
+ fallback_dbname = 'ecpg_regression_@0@'
endif
- test_output = test_result_dir / test_dir['name'] / kind
+ test_group = test_dir['name']
+ test_group_running = test_dir['name'] + '-running'
- test_command = [
+ test_output = test_result_dir / test_group / kind
+ test_output_running = test_result_dir / test_group_running/ kind
+
+ # Unless specified by the test, choose a non-conflicting database name,
+ # to avoid conflicts when running against existing server.
+ dbname = t.get('dbname',
+ fallback_dbname.format(test_dir['name']))
+
+ test_command_base = [
runner.full_path(),
'--inputdir', t.get('inputdir', test_dir['sd']),
'--expecteddir', t.get('expecteddir', test_dir['sd']),
- '--outputdir', test_output,
- '--temp-instance', test_output / 'tmp_check',
'--bindir', '',
'--dlpath', test_dir['bd'],
'--max-concurrent-tests=20',
- '--port', testport.to_string(),
+ '--dbname', dbname,
] + t.get('regress_args', [])
+ test_selection = []
if t.has_key('schedule')
- test_command += ['--schedule', t['schedule'],]
+ test_selection += ['--schedule', t['schedule'],]
endif
if kind == 'isolation'
- test_command += t.get('specs', [])
+ test_selection += t.get('specs', [])
else
- test_command += t.get('sql', [])
+ test_selection += t.get('sql', [])
endif
env = test_env
env.prepend('PATH', temp_install_bindir, test_dir['bd'])
test_kwargs = {
- 'suite': [test_dir['name']],
'priority': 10,
'timeout': 1000,
'depends': test_deps + t.get('deps', []),
@@ -2883,12 +2904,41 @@ foreach test_dir : tests
test(test_dir['name'] / kind,
python,
- args: testwrap_base + [
+ args: [
+ testwrap_base,
+ '--testgroup', test_group,
'--testname', kind,
- '--', test_command,
+ '--',
+ test_command_base,
+ '--outputdir', test_output,
+ '--temp-instance', test_output / 'tmp_check',
+ '--port', testport.to_string(),
+ test_selection,
],
+ suite: test_group,
kwargs: test_kwargs,
)
+ install_suites += test_dir['name']
+
+ # some tests can't support running against running DB
+ if runningcheck and t.get('runningcheck', true)
+ test(test_group_running / kind,
+ python,
+ args: [
+ testwrap_base,
+ '--testgroup', test_group_running,
+ '--testname', kind,
+ '--',
+ test_command_base,
+ '--outputdir', test_output_running,
+ test_selection,
+ ],
+ is_parallel: t.get('runningcheck-parallel', true),
+ suite: test_group_running,
+ kwargs: test_kwargs,
+ )
+ running_suites += test_group_running
+ endif
testport += 1
elif kind == 'tap'
@@ -2911,9 +2961,10 @@ foreach test_dir : tests
env.set(name, value)
endforeach
+ suite = test_dir['name']
test_kwargs = {
'protocol': 'tap',
- 'suite': [test_dir['name']],
+ 'suite': suite,
'timeout': 1000,
'depends': test_deps + t.get('deps', []),
'env': env,
@@ -2933,12 +2984,14 @@ foreach test_dir : tests
python,
kwargs: test_kwargs,
args: testwrap_base + [
+ '--testgroup', test_dir['name'],
'--testname', onetap_p,
'--', test_command,
test_dir['sd'] / onetap,
],
)
endforeach
+ install_suites += suite
else
error('unknown kind @0@ of test in @1@'.format(kind, test_dir['sd']))
endif
@@ -2947,6 +3000,14 @@ foreach test_dir : tests
endforeach # directories with tests
+# repeat condition so meson realizes version dependency
+if meson.version().version_compare('>=0.57')
+ add_test_setup('default',
+ is_default: true,
+ exclude_suites: running_suites)
+ add_test_setup('running',
+ exclude_suites: ['setup'] + install_suites)
+endif
###############################################################
--
2.37.3.542.gdd3f6c4cae