1 2# Copyright (c) 2021, PostgreSQL Global Development Group 3 4use strict; 5use warnings; 6 7use PostgresNode; 8use TestLib; 9use Test::More tests => 76; 10 11# Test set-up 12my ($node, $port); 13$node = get_new_node('test'); 14$node->init; 15$node->start; 16$port = $node->port; 17 18# Load the amcheck extension, upon which pg_amcheck depends 19$node->safe_psql('postgres', q(CREATE EXTENSION amcheck)); 20 21######################################### 22# Test non-existent databases 23 24# Failing to connect to the initial database is an error. 25$node->command_checks_all( 26 [ 'pg_amcheck', 'qqq' ], 27 1, [qr/^$/], 28 [qr/FATAL: database "qqq" does not exist/], 29 'checking a non-existent database'); 30 31# Failing to resolve a database pattern is an error by default. 32$node->command_checks_all( 33 [ 'pg_amcheck', '-d', 'qqq', '-d', 'postgres' ], 34 1, 35 [qr/^$/], 36 [qr/pg_amcheck: error: no connectable databases to check matching "qqq"/], 37 'checking an unresolvable database pattern'); 38 39# But only a warning under --no-strict-names 40$node->command_checks_all( 41 [ 'pg_amcheck', '--no-strict-names', '-d', 'qqq', '-d', 'postgres' ], 42 0, 43 [qr/^$/], 44 [ 45 qr/pg_amcheck: warning: no connectable databases to check matching "qqq"/ 46 ], 47 'checking an unresolvable database pattern under --no-strict-names'); 48 49# Check that a substring of an existent database name does not get interpreted 50# as a matching pattern. 51$node->command_checks_all( 52 [ 'pg_amcheck', '-d', 'post', '-d', 'postgres' ], 53 1, 54 [qr/^$/], 55 [ 56 qr/pg_amcheck: error: no connectable databases to check matching "post"/ 57 ], 58 'checking an unresolvable database pattern (substring of existent database)' 59); 60 61# Check that a superstring of an existent database name does not get interpreted 62# as a matching pattern. 63$node->command_checks_all( 64 [ 'pg_amcheck', '-d', 'postgresql', '-d', 'postgres' ], 65 1, 66 [qr/^$/], 67 [ 68 qr/pg_amcheck: error: no connectable databases to check matching "postgresql"/ 69 ], 70 'checking an unresolvable database pattern (superstring of existent database)' 71); 72 73######################################### 74# Test connecting with a non-existent user 75 76# Failing to connect to the initial database due to bad username is an error. 77$node->command_checks_all([ 'pg_amcheck', '-U', 'no_such_user', 'postgres' ], 78 1, [qr/^$/], [], 'checking with a non-existent user'); 79 80######################################### 81# Test checking databases without amcheck installed 82 83# Attempting to check a database by name where amcheck is not installed should 84# raise a warning. If all databases are skipped, having no relations to check 85# raises an error. 86$node->command_checks_all( 87 [ 'pg_amcheck', 'template1' ], 88 1, 89 [qr/^$/], 90 [ 91 qr/pg_amcheck: warning: skipping database "template1": amcheck is not installed/, 92 qr/pg_amcheck: error: no relations to check/ 93 ], 94 'checking a database by name without amcheck installed, no other databases' 95); 96 97# Again, but this time with another database to check, so no error is raised. 98$node->command_checks_all( 99 [ 'pg_amcheck', '-d', 'template1', '-d', 'postgres' ], 100 0, 101 [qr/^$/], 102 [ 103 qr/pg_amcheck: warning: skipping database "template1": amcheck is not installed/ 104 ], 105 'checking a database by name without amcheck installed, with other databases' 106); 107 108# Again, but by way of checking all databases 109$node->command_checks_all( 110 [ 'pg_amcheck', '--all' ], 111 0, 112 [qr/^$/], 113 [ 114 qr/pg_amcheck: warning: skipping database "template1": amcheck is not installed/ 115 ], 116 'checking a database by pattern without amcheck installed, with other databases' 117); 118 119######################################### 120# Test unreasonable patterns 121 122# Check three-part unreasonable pattern that has zero-length names 123$node->command_checks_all( 124 [ 'pg_amcheck', '-d', 'postgres', '-t', '..' ], 125 1, 126 [qr/^$/], 127 [ 128 qr/pg_amcheck: error: no connectable databases to check matching "\.\."/ 129 ], 130 'checking table pattern ".."'); 131 132# Again, but with non-trivial schema and relation parts 133$node->command_checks_all( 134 [ 'pg_amcheck', '-d', 'postgres', '-t', '.foo.bar' ], 135 1, 136 [qr/^$/], 137 [ 138 qr/pg_amcheck: error: no connectable databases to check matching "\.foo\.bar"/ 139 ], 140 'checking table pattern ".foo.bar"'); 141 142# Check two-part unreasonable pattern that has zero-length names 143$node->command_checks_all( 144 [ 'pg_amcheck', '-d', 'postgres', '-t', '.' ], 145 1, 146 [qr/^$/], 147 [qr/pg_amcheck: error: no heap tables to check matching "\."/], 148 'checking table pattern "."'); 149 150######################################### 151# Test checking non-existent databases, schemas, tables, and indexes 152 153# Use --no-strict-names and a single existent table so we only get warnings 154# about the failed pattern matches 155$node->command_checks_all( 156 [ 157 'pg_amcheck', '--no-strict-names', 158 '-t', 'no_such_table', 159 '-t', 'no*such*table', 160 '-i', 'no_such_index', 161 '-i', 'no*such*index', 162 '-r', 'no_such_relation', 163 '-r', 'no*such*relation', 164 '-d', 'no_such_database', 165 '-d', 'no*such*database', 166 '-r', 'none.none', 167 '-r', 'none.none.none', 168 '-r', 'this.is.a.really.long.dotted.string', 169 '-r', 'postgres.none.none', 170 '-r', 'postgres.long.dotted.string', 171 '-r', 'postgres.pg_catalog.none', 172 '-r', 'postgres.none.pg_class', 173 '-t', 'postgres.pg_catalog.pg_class', # This exists 174 ], 175 0, 176 [qr/^$/], 177 [ 178 qr/pg_amcheck: warning: no heap tables to check matching "no_such_table"/, 179 qr/pg_amcheck: warning: no heap tables to check matching "no\*such\*table"/, 180 qr/pg_amcheck: warning: no btree indexes to check matching "no_such_index"/, 181 qr/pg_amcheck: warning: no btree indexes to check matching "no\*such\*index"/, 182 qr/pg_amcheck: warning: no relations to check matching "no_such_relation"/, 183 qr/pg_amcheck: warning: no relations to check matching "no\*such\*relation"/, 184 qr/pg_amcheck: warning: no heap tables to check matching "no\*such\*table"/, 185 qr/pg_amcheck: warning: no connectable databases to check matching "no_such_database"/, 186 qr/pg_amcheck: warning: no connectable databases to check matching "no\*such\*database"/, 187 qr/pg_amcheck: warning: no relations to check matching "none\.none"/, 188 qr/pg_amcheck: warning: no connectable databases to check matching "none\.none\.none"/, 189 qr/pg_amcheck: warning: no connectable databases to check matching "this\.is\.a\.really\.long\.dotted\.string"/, 190 qr/pg_amcheck: warning: no relations to check matching "postgres\.none\.none"/, 191 qr/pg_amcheck: warning: no relations to check matching "postgres\.long\.dotted\.string"/, 192 qr/pg_amcheck: warning: no relations to check matching "postgres\.pg_catalog\.none"/, 193 qr/pg_amcheck: warning: no relations to check matching "postgres\.none\.pg_class"/, 194 qr/pg_amcheck: warning: no connectable databases to check matching "no_such_database"/, 195 qr/pg_amcheck: warning: no connectable databases to check matching "no\*such\*database"/, 196 qr/pg_amcheck: warning: no connectable databases to check matching "none\.none\.none"/, 197 qr/pg_amcheck: warning: no connectable databases to check matching "this\.is\.a\.really\.long\.dotted\.string"/, 198 ], 199 'many unmatched patterns and one matched pattern under --no-strict-names' 200); 201 202######################################### 203# Test checking otherwise existent objects but in databases where they do not exist 204 205$node->safe_psql( 206 'postgres', q( 207 CREATE TABLE public.foo (f integer); 208 CREATE INDEX foo_idx ON foo(f); 209)); 210$node->safe_psql('postgres', q(CREATE DATABASE another_db)); 211 212$node->command_checks_all( 213 [ 214 'pg_amcheck', '-d', 215 'postgres', '--no-strict-names', 216 '-t', 'template1.public.foo', 217 '-t', 'another_db.public.foo', 218 '-t', 'no_such_database.public.foo', 219 '-i', 'template1.public.foo_idx', 220 '-i', 'another_db.public.foo_idx', 221 '-i', 'no_such_database.public.foo_idx', 222 ], 223 1, 224 [qr/^$/], 225 [ 226 qr/pg_amcheck: warning: skipping database "template1": amcheck is not installed/, 227 qr/pg_amcheck: warning: no heap tables to check matching "template1\.public\.foo"/, 228 qr/pg_amcheck: warning: no heap tables to check matching "another_db\.public\.foo"/, 229 qr/pg_amcheck: warning: no connectable databases to check matching "no_such_database\.public\.foo"/, 230 qr/pg_amcheck: warning: no btree indexes to check matching "template1\.public\.foo_idx"/, 231 qr/pg_amcheck: warning: no btree indexes to check matching "another_db\.public\.foo_idx"/, 232 qr/pg_amcheck: warning: no connectable databases to check matching "no_such_database\.public\.foo_idx"/, 233 qr/pg_amcheck: error: no relations to check/, 234 ], 235 'checking otherwise existent objets in the wrong databases'); 236 237 238######################################### 239# Test schema exclusion patterns 240 241# Check with only schema exclusion patterns 242$node->command_checks_all( 243 [ 244 'pg_amcheck', '--all', '--no-strict-names', '-S', 245 'public', '-S', 'pg_catalog', '-S', 246 'pg_toast', '-S', 'information_schema', 247 ], 248 1, 249 [qr/^$/], 250 [ 251 qr/pg_amcheck: warning: skipping database "template1": amcheck is not installed/, 252 qr/pg_amcheck: error: no relations to check/ 253 ], 254 'schema exclusion patterns exclude all relations'); 255 256# Check with schema exclusion patterns overriding relation and schema inclusion patterns 257$node->command_checks_all( 258 [ 259 'pg_amcheck', '--all', '--no-strict-names', '-s', 260 'public', '-s', 'pg_catalog', '-s', 261 'pg_toast', '-s', 'information_schema', '-t', 262 'pg_catalog.pg_class', '-S*' 263 ], 264 1, 265 [qr/^$/], 266 [ 267 qr/pg_amcheck: warning: skipping database "template1": amcheck is not installed/, 268 qr/pg_amcheck: error: no relations to check/ 269 ], 270 'schema exclusion pattern overrides all inclusion patterns'); 271