Consistently use "superuser" instead of "super user"
[pgsql.git] / src / bin / pg_checksums / t / 002_actions.pl
bloba18c104a94dae3b81f9acbbd4e2bb94e451c37b6
2 # Copyright (c) 2021, PostgreSQL Global Development Group
4 # Do basic sanity checks supported by pg_checksums using
5 # an initialized cluster.
7 use strict;
8 use warnings;
9 use PostgresNode;
10 use TestLib;
12 use Fcntl qw(:seek);
13 use Test::More tests => 63;
16 # Utility routine to create and check a table with corrupted checksums
17 # on a wanted tablespace. Note that this stops and starts the node
18 # multiple times to perform the checks, leaving the node started
19 # at the end.
20 sub check_relation_corruption
22 my $node = shift;
23 my $table = shift;
24 my $tablespace = shift;
25 my $pgdata = $node->data_dir;
27 $node->safe_psql(
28 'postgres',
29 "CREATE TABLE $table AS SELECT a FROM generate_series(1,10000) AS a;
30 ALTER TABLE $table SET (autovacuum_enabled=false);");
32 $node->safe_psql('postgres',
33 "ALTER TABLE " . $table . " SET TABLESPACE " . $tablespace . ";");
35 my $file_corrupted =
36 $node->safe_psql('postgres', "SELECT pg_relation_filepath('$table');");
37 my $relfilenode_corrupted = $node->safe_psql('postgres',
38 "SELECT relfilenode FROM pg_class WHERE relname = '$table';");
40 # Set page header and block size
41 my $pageheader_size = 24;
42 my $block_size = $node->safe_psql('postgres', 'SHOW block_size;');
43 $node->stop;
45 # Checksums are correct for single relfilenode as the table is not
46 # corrupted yet.
47 command_ok(
49 'pg_checksums', '--check',
50 '-D', $pgdata,
51 '--filenode', $relfilenode_corrupted
53 "succeeds for single relfilenode on tablespace $tablespace with offline cluster"
56 # Time to create some corruption
57 open my $file, '+<', "$pgdata/$file_corrupted";
58 seek($file, $pageheader_size, SEEK_SET);
59 syswrite($file, "\0\0\0\0\0\0\0\0\0");
60 close $file;
62 # Checksum checks on single relfilenode fail
63 $node->command_checks_all(
65 'pg_checksums', '--check',
66 '-D', $pgdata,
67 '--filenode', $relfilenode_corrupted
70 [qr/Bad checksums:.*1/],
71 [qr/checksum verification failed/],
72 "fails with corrupted data for single relfilenode on tablespace $tablespace"
75 # Global checksum checks fail as well
76 $node->command_checks_all(
77 [ 'pg_checksums', '--check', '-D', $pgdata ],
79 [qr/Bad checksums:.*1/],
80 [qr/checksum verification failed/],
81 "fails with corrupted data on tablespace $tablespace");
83 # Drop corrupted table again and make sure there is no more corruption.
84 $node->start;
85 $node->safe_psql('postgres', "DROP TABLE $table;");
86 $node->stop;
87 $node->command_ok([ 'pg_checksums', '--check', '-D', $pgdata ],
88 "succeeds again after table drop on tablespace $tablespace");
90 $node->start;
91 return;
94 # Initialize node with checksums disabled.
95 my $node = PostgresNode->new('node_checksum');
96 $node->init();
97 my $pgdata = $node->data_dir;
99 # Control file should know that checksums are disabled.
100 command_like(
101 [ 'pg_controldata', $pgdata ],
102 qr/Data page checksum version:.*0/,
103 'checksums disabled in control file');
105 # These are correct but empty files, so they should pass through.
106 append_to_file "$pgdata/global/99999", "";
107 append_to_file "$pgdata/global/99999.123", "";
108 append_to_file "$pgdata/global/99999_fsm", "";
109 append_to_file "$pgdata/global/99999_init", "";
110 append_to_file "$pgdata/global/99999_vm", "";
111 append_to_file "$pgdata/global/99999_init.123", "";
112 append_to_file "$pgdata/global/99999_fsm.123", "";
113 append_to_file "$pgdata/global/99999_vm.123", "";
115 # These are temporary files and folders with dummy contents, which
116 # should be ignored by the scan.
117 append_to_file "$pgdata/global/pgsql_tmp_123", "foo";
118 mkdir "$pgdata/global/pgsql_tmp";
119 append_to_file "$pgdata/global/pgsql_tmp/1.1", "foo";
120 append_to_file "$pgdata/global/pg_internal.init", "foo";
121 append_to_file "$pgdata/global/pg_internal.init.123", "foo";
123 # Enable checksums.
124 command_ok([ 'pg_checksums', '--enable', '--no-sync', '-D', $pgdata ],
125 "checksums successfully enabled in cluster");
127 # Successive attempt to enable checksums fails.
128 command_fails([ 'pg_checksums', '--enable', '--no-sync', '-D', $pgdata ],
129 "enabling checksums fails if already enabled");
131 # Control file should know that checksums are enabled.
132 command_like(
133 [ 'pg_controldata', $pgdata ],
134 qr/Data page checksum version:.*1/,
135 'checksums enabled in control file');
137 # Disable checksums again. Flush result here as that should be cheap.
138 command_ok(
139 [ 'pg_checksums', '--disable', '-D', $pgdata ],
140 "checksums successfully disabled in cluster");
142 # Successive attempt to disable checksums fails.
143 command_fails(
144 [ 'pg_checksums', '--disable', '--no-sync', '-D', $pgdata ],
145 "disabling checksums fails if already disabled");
147 # Control file should know that checksums are disabled.
148 command_like(
149 [ 'pg_controldata', $pgdata ],
150 qr/Data page checksum version:.*0/,
151 'checksums disabled in control file');
153 # Enable checksums again for follow-up tests.
154 command_ok([ 'pg_checksums', '--enable', '--no-sync', '-D', $pgdata ],
155 "checksums successfully enabled in cluster");
157 # Control file should know that checksums are enabled.
158 command_like(
159 [ 'pg_controldata', $pgdata ],
160 qr/Data page checksum version:.*1/,
161 'checksums enabled in control file');
163 # Checksums pass on a newly-created cluster
164 command_ok([ 'pg_checksums', '--check', '-D', $pgdata ],
165 "succeeds with offline cluster");
167 # Checksums are verified if no other arguments are specified
168 command_ok(
169 [ 'pg_checksums', '-D', $pgdata ],
170 "verifies checksums as default action");
172 # Specific relation files cannot be requested when action is --disable
173 # or --enable.
174 command_fails(
175 [ 'pg_checksums', '--disable', '--filenode', '1234', '-D', $pgdata ],
176 "fails when relfilenodes are requested and action is --disable");
177 command_fails(
178 [ 'pg_checksums', '--enable', '--filenode', '1234', '-D', $pgdata ],
179 "fails when relfilenodes are requested and action is --enable");
181 # Checks cannot happen with an online cluster
182 $node->start;
183 command_fails([ 'pg_checksums', '--check', '-D', $pgdata ],
184 "fails with online cluster");
186 # Check corruption of table on default tablespace.
187 check_relation_corruption($node, 'corrupt1', 'pg_default');
189 # Create tablespace to check corruptions in a non-default tablespace.
190 my $basedir = $node->basedir;
191 my $tablespace_dir = "$basedir/ts_corrupt_dir";
192 mkdir($tablespace_dir);
193 $tablespace_dir = TestLib::perl2host($tablespace_dir);
194 $node->safe_psql('postgres',
195 "CREATE TABLESPACE ts_corrupt LOCATION '$tablespace_dir';");
196 check_relation_corruption($node, 'corrupt2', 'ts_corrupt');
198 # Utility routine to check that pg_checksums is able to detect
199 # correctly-named relation files filled with some corrupted data.
200 sub fail_corrupt
202 my $node = shift;
203 my $file = shift;
204 my $pgdata = $node->data_dir;
206 # Create the file with some dummy data in it.
207 my $file_name = "$pgdata/global/$file";
208 append_to_file $file_name, "foo";
210 $node->command_checks_all(
211 [ 'pg_checksums', '--check', '-D', $pgdata ],
213 [qr/^$/],
214 [qr/could not read block 0 in file.*$file\":/],
215 "fails for corrupted data in $file");
217 # Remove file to prevent future lookup errors on conflicts.
218 unlink $file_name;
219 return;
222 # Stop instance for the follow-up checks.
223 $node->stop;
225 # Create a fake tablespace location that should not be scanned
226 # when verifying checksums.
227 mkdir "$tablespace_dir/PG_99_999999991/";
228 append_to_file "$tablespace_dir/PG_99_999999991/foo", "123";
229 command_ok([ 'pg_checksums', '--check', '-D', $pgdata ],
230 "succeeds with foreign tablespace");
232 # Authorized relation files filled with corrupted data cause the
233 # checksum checks to fail. Make sure to use file names different
234 # than the previous ones.
235 fail_corrupt($node, "99990");
236 fail_corrupt($node, "99990.123");
237 fail_corrupt($node, "99990_fsm");
238 fail_corrupt($node, "99990_init");
239 fail_corrupt($node, "99990_vm");
240 fail_corrupt($node, "99990_init.123");
241 fail_corrupt($node, "99990_fsm.123");
242 fail_corrupt($node, "99990_vm.123");