From 968caa8cdd45252ec9f507dde3bff403f937cd21 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Sun, 5 Apr 2026 00:01:06 +0200 Subject: [PATCH 2/2] Refactor checksum injection point tests Refactor the injection point tests for online checksum enabling to use the injection_points extension. Author: Daniel Gustafsson --- src/backend/postmaster/datachecksum_state.c | 26 +++++- .../modules/test_checksums/t/005_injection.pl | 7 +- .../test_checksums/t/006_pgbench_single.pl | 13 ++- .../test_checksums/t/007_pgbench_standby.pl | 14 +++- .../test_checksums/test_checksums--1.0.sql | 8 -- .../modules/test_checksums/test_checksums.c | 79 ------------------- 6 files changed, 48 insertions(+), 99 deletions(-) diff --git a/src/backend/postmaster/datachecksum_state.c b/src/backend/postmaster/datachecksum_state.c index 76004bcedc6..48326345dde 100644 --- a/src/backend/postmaster/datachecksum_state.c +++ b/src/backend/postmaster/datachecksum_state.c @@ -1197,8 +1197,15 @@ ProcessAllDatabases(void) result = ProcessDatabase(db); +#ifdef USE_INJECTION_POINTS /* Allow a test process to alter the result of the operation */ - INJECTION_POINT("datachecksumsworker-modify-db-result", &result); + if (IS_INJECTION_POINT_ATTACHED("datachecksumsworker-fail-db-result")) + { + result = DATACHECKSUMSWORKER_FAILED; + INJECTION_POINT_CACHED("datachecksumsworker-fail-db-result", + db->dbname); + } +#endif pgstat_progress_update_param(PROGRESS_DATACHECKSUMS_DBS_DONE, ++cumulative_total); @@ -1451,6 +1458,9 @@ DataChecksumsWorkerMain(Datum arg) BufferAccessStrategy strategy; bool aborted = false; int64 rels_done; +#ifdef USE_INJECTION_POINTS + bool retried = false; +#endif operation = ENABLE_DATACHECKSUMS; @@ -1566,7 +1576,19 @@ DataChecksumsWorkerMain(Datum arg) } list_free(CurrentTempTables); - INJECTION_POINT("datachecksumsworker-fake-temptable-wait", &numleft); +#ifdef USE_INJECTION_POINTS + if (IS_INJECTION_POINT_ATTACHED("datachecksumsworker-fake-temptable-wait")) + { + /* Make sure to just cause one retry */ + if (!retried && numleft == 0) + { + numleft = 1; + retried = true; + + INJECTION_POINT_CACHED("datachecksumsworker-fake-temptable-wait", NULL); + } + } +#endif if (numleft == 0) break; diff --git a/src/test/modules/test_checksums/t/005_injection.pl b/src/test/modules/test_checksums/t/005_injection.pl index 897f282a1f2..ff383cf6b9d 100644 --- a/src/test/modules/test_checksums/t/005_injection.pl +++ b/src/test/modules/test_checksums/t/005_injection.pl @@ -32,6 +32,7 @@ $node->start; # Set up test environment $node->safe_psql('postgres', 'CREATE EXTENSION test_checksums;'); +$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;'); # --------------------------------------------------------------------------- # Inducing failures and crashes in processing @@ -39,9 +40,9 @@ $node->safe_psql('postgres', 'CREATE EXTENSION test_checksums;'); # Force enabling checksums to fail by marking one of the databases as having # failed in processing. disable_data_checksums($node, wait => 1); -$node->safe_psql('postgres', 'SELECT dcw_inject_fail_database(true);'); +$node->safe_psql('postgres', "SELECT injection_points_attach('datachecksumsworker-fail-db-result','notice');"); enable_data_checksums($node, wait => 'off'); -$node->safe_psql('postgres', 'SELECT dcw_inject_fail_database(false);'); +$node->safe_psql('postgres', "SELECT injection_points_detach('datachecksumsworker-fail-db-result');"); # Make sure that disabling after a failure works disable_data_checksums($node); @@ -66,7 +67,7 @@ SKIP: # will force the processing to wait and retry in order to wait for it to # disappear. disable_data_checksums($node, wait => 1); - $node->safe_psql('postgres', 'SELECT dcw_fake_temptable(true);'); + $node->safe_psql('postgres', "SELECT injection_points_attach('datachecksumsworker-fake-temptable-wait', 'notice');"); enable_data_checksums($node, wait => 'on'); } diff --git a/src/test/modules/test_checksums/t/006_pgbench_single.pl b/src/test/modules/test_checksums/t/006_pgbench_single.pl index 0ab5b04b931..f83b39247ae 100644 --- a/src/test/modules/test_checksums/t/006_pgbench_single.pl +++ b/src/test/modules/test_checksums/t/006_pgbench_single.pl @@ -89,14 +89,19 @@ sub background_rw_pgbench # before and after state. sub flip_data_checksums { + my $temptablewait = 0; + # First, make sure the cluster is in the state we expect it to be test_checksum_state($node, $data_checksum_state); if ($data_checksum_state eq 'off') { # Coin-toss to see if we are injecting a retry due to a temptable - $node->safe_psql('postgres', 'SELECT dcw_fake_temptable();') - if cointoss(); + if (cointoss()) + { + $node->safe_psql('postgres', "SELECT injection_points_attach('datachecksumsworker-fake-temptable-wait', 'notice');"); + $temptablewait = 1; + } # log LSN right before we start changing checksums my $result = @@ -117,7 +122,8 @@ sub flip_data_checksums random_sleep() if ($extended); - $node->safe_psql('postgres', 'SELECT dcw_fake_temptable(false);'); + $node->safe_psql('postgres', "SELECT injection_points_detach('datachecksumsworker-fake-temptable-wait');") + if ($temptablewait); $data_checksum_state = 'on'; } elsif ($data_checksum_state eq 'on') @@ -165,6 +171,7 @@ log_statement = none ]); $node->start; $node->safe_psql('postgres', 'CREATE EXTENSION test_checksums;'); +$node->safe_psql('postgres', 'CREATE EXTENSION injection_points;'); # Create some content to have un-checksummed data in the cluster $node->safe_psql('postgres', "CREATE TABLE t AS SELECT generate_series(1, 100000) AS a;"); diff --git a/src/test/modules/test_checksums/t/007_pgbench_standby.pl b/src/test/modules/test_checksums/t/007_pgbench_standby.pl index b0d40d24005..1cc95916dda 100644 --- a/src/test/modules/test_checksums/t/007_pgbench_standby.pl +++ b/src/test/modules/test_checksums/t/007_pgbench_standby.pl @@ -99,6 +99,8 @@ sub background_pgbench # before and after state. sub flip_data_checksums { + my $temptablewait = 0; + # First, make sure the cluster is in the state we expect it to be test_checksum_state($node_primary, $data_checksum_state); test_checksum_state($node_standby, $data_checksum_state); @@ -106,8 +108,11 @@ sub flip_data_checksums if ($data_checksum_state eq 'off') { # Coin-toss to see if we are injecting a retry due to a temptable - $node_primary->safe_psql('postgres', 'SELECT dcw_fake_temptable();') - if cointoss(); + if (cointoss()) + { + $node_primary->safe_psql('postgres', "SELECT injection_points_attach('datachecksumsworker-fake-temptable-wait', 'notice');"); + $temptablewait = 1; + } # log LSN right before we start changing checksums my $result = @@ -153,8 +158,8 @@ sub flip_data_checksums random_sleep() if ($extended); wait_for_checksum_state($node_standby, 'on'); - $node_primary->safe_psql('postgres', - 'SELECT dcw_fake_temptable(false);'); + $node_primary->safe_psql('postgres', "SELECT injection_points_detach('datachecksumsworker-fake-temptable-wait');") + if ($temptablewait); $data_checksum_state = 'on'; } elsif ($data_checksum_state eq 'on') @@ -207,6 +212,7 @@ log_statement = none ]); $node_primary->start; $node_primary->safe_psql('postgres', 'CREATE EXTENSION test_checksums;'); +$node_primary->safe_psql('postgres', 'CREATE EXTENSION injection_points;'); # Create some content to have un-checksummed data in the cluster $node_primary->safe_psql('postgres', "CREATE TABLE t AS SELECT generate_series(1, 100000) AS a;"); diff --git a/src/test/modules/test_checksums/test_checksums--1.0.sql b/src/test/modules/test_checksums/test_checksums--1.0.sql index 90642d247fa..c674fee02bb 100644 --- a/src/test/modules/test_checksums/test_checksums--1.0.sql +++ b/src/test/modules/test_checksums/test_checksums--1.0.sql @@ -14,11 +14,3 @@ CREATE FUNCTION dcw_inject_launcher_delay(attach boolean DEFAULT true) CREATE FUNCTION dcw_inject_startup_delay(attach boolean DEFAULT true) RETURNS pg_catalog.void AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE FUNCTION dcw_inject_fail_database(attach boolean DEFAULT true) - RETURNS pg_catalog.void - AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE FUNCTION dcw_fake_temptable(attach boolean DEFAULT true) - RETURNS pg_catalog.void - AS 'MODULE_PATHNAME' LANGUAGE C; diff --git a/src/test/modules/test_checksums/test_checksums.c b/src/test/modules/test_checksums/test_checksums.c index e2b91f9c78c..c2eabc2821c 100644 --- a/src/test/modules/test_checksums/test_checksums.c +++ b/src/test/modules/test_checksums/test_checksums.c @@ -25,8 +25,6 @@ extern PGDLLEXPORT void dc_delay_barrier(const char *name, const void *private_d extern PGDLLEXPORT void dc_modify_db_result(const char *name, const void *private_data, void *arg); extern PGDLLEXPORT void dc_fake_temptable(const char *name, const void *private_data, void *arg); -extern PGDLLEXPORT void crash(const char *name, const void *private_data, void *arg); - /* * Test for delaying emission of procsignalbarriers. */ @@ -107,80 +105,3 @@ dcw_inject_startup_delay(PG_FUNCTION_ARGS) #endif PG_RETURN_VOID(); } - -#ifdef USE_INJECTION_POINTS -static uint32 db_fail = DATACHECKSUMSWORKER_FAILED; -#endif - -void -dc_modify_db_result(const char *name, const void *private_data, void *arg) -{ - DataChecksumsWorkerResult *res = (DataChecksumsWorkerResult *) arg; - uint32 new_res = *(uint32 *) private_data; - - *res = new_res; -} - -PG_FUNCTION_INFO_V1(dcw_inject_fail_database); -Datum -dcw_inject_fail_database(PG_FUNCTION_ARGS) -{ -#ifdef USE_INJECTION_POINTS - bool attach = PG_GETARG_BOOL(0); - - if (attach) - InjectionPointAttach("datachecksumsworker-modify-db-result", - "test_checksums", - "dc_modify_db_result", - &db_fail, - sizeof(uint32)); - else - InjectionPointDetach("datachecksumsworker-modify-db-result"); -#else - elog(ERROR, - "test is not working as intended when injection points are disabled"); -#endif - PG_RETURN_VOID(); -} - -/* - * Test to force waiting for existing temptables. - */ -void -dc_fake_temptable(const char *name, const void *private_data, void *arg) -{ - static bool first_pass = true; - int *numleft = (int *) arg; - - if (first_pass) - *numleft = 1; - first_pass = false; -} - -PG_FUNCTION_INFO_V1(dcw_fake_temptable); -Datum -dcw_fake_temptable(PG_FUNCTION_ARGS) -{ -#ifdef USE_INJECTION_POINTS - bool attach = PG_GETARG_BOOL(0); - - if (attach) - InjectionPointAttach("datachecksumsworker-fake-temptable-wait", - "test_checksums", - "dc_fake_temptable", - NULL, - 0); - else - InjectionPointDetach("datachecksumsworker-fake-temptable-wait"); -#else - elog(ERROR, - "test is not working as intended when injection points are disabled"); -#endif - PG_RETURN_VOID(); -} - -void -crash(const char *name, const void *private_data, void *arg) -{ - abort(); -} -- 2.39.3 (Apple Git-146)