Add error pattern checks for some TAP tests for non-existing objects
[pgsql.git] / src / bin / pg_ctl / t / 004_logrotate.pl
blobd78360e6d1ae1dc2a7b26e2b8ce439b0fabbdf36
2 # Copyright (c) 2021-2025, PostgreSQL Global Development Group
4 use strict;
5 use warnings FATAL => 'all';
7 use PostgreSQL::Test::Cluster;
8 use PostgreSQL::Test::Utils;
9 use Test::More;
10 use Time::HiRes qw(usleep);
12 # Extract the file name of a $format from the contents of
13 # current_logfiles.
14 sub fetch_file_name
16 my $logfiles = shift;
17 my $format = shift;
18 my @lines = split(/\n/, $logfiles);
19 my $filename = undef;
20 foreach my $line (@lines)
22 if ($line =~ /$format (.*)$/gm)
24 $filename = $1;
28 return $filename;
31 # Check for a pattern in the logs associated to one format.
32 sub check_log_pattern
34 local $Test::Builder::Level = $Test::Builder::Level + 1;
36 my $format = shift;
37 my $logfiles = shift;
38 my $pattern = shift;
39 my $node = shift;
40 my $lfname = fetch_file_name($logfiles, $format);
42 my $max_attempts = 10 * $PostgreSQL::Test::Utils::timeout_default;
44 my $logcontents;
45 for (my $attempts = 0; $attempts < $max_attempts; $attempts++)
47 $logcontents = slurp_file($node->data_dir . '/' . $lfname);
48 last if $logcontents =~ m/$pattern/;
49 usleep(100_000);
52 like($logcontents, qr/$pattern/,
53 "found expected log file content for $format");
55 # While we're at it, test pg_current_logfile() function
56 is( $node->safe_psql('postgres', "SELECT pg_current_logfile('$format')"),
57 $lfname,
58 "pg_current_logfile() gives correct answer with $format");
59 return;
62 # Set up node with logging collector
63 my $node = PostgreSQL::Test::Cluster->new('primary');
64 $node->init();
65 $node->append_conf(
66 'postgresql.conf', qq(
67 logging_collector = on
68 log_destination = 'stderr, csvlog, jsonlog'
69 # these ensure stability of test results:
70 log_rotation_age = 0
71 lc_messages = 'C'
72 ));
74 $node->start();
76 # Verify that log output gets to the file
78 $node->psql('postgres', 'SELECT 1/0');
80 # might need to retry if logging collector process is slow...
81 my $max_attempts = 10 * $PostgreSQL::Test::Utils::timeout_default;
83 my $current_logfiles;
84 for (my $attempts = 0; $attempts < $max_attempts; $attempts++)
86 eval {
87 $current_logfiles = slurp_file($node->data_dir . '/current_logfiles');
89 last unless $@;
90 usleep(100_000);
92 die $@ if $@;
94 note "current_logfiles = $current_logfiles";
96 like(
97 $current_logfiles,
98 qr|^stderr log/postgresql-.*log
99 csvlog log/postgresql-.*csv
100 jsonlog log/postgresql-.*json$|,
101 'current_logfiles is sane');
103 check_log_pattern('stderr', $current_logfiles, 'division by zero', $node);
104 check_log_pattern('csvlog', $current_logfiles, 'division by zero', $node);
105 check_log_pattern('jsonlog', $current_logfiles, 'division by zero', $node);
107 # Sleep 2 seconds and ask for log rotation; this should result in
108 # output into a different log file name.
109 sleep(2);
110 $node->logrotate();
112 # pg_ctl logrotate doesn't wait for rotation request to be completed.
113 # Allow a bit of time for it to happen.
114 my $new_current_logfiles;
115 for (my $attempts = 0; $attempts < $max_attempts; $attempts++)
117 $new_current_logfiles = slurp_file($node->data_dir . '/current_logfiles');
118 last if $new_current_logfiles ne $current_logfiles;
119 usleep(100_000);
122 note "now current_logfiles = $new_current_logfiles";
124 like(
125 $new_current_logfiles,
126 qr|^stderr log/postgresql-.*log
127 csvlog log/postgresql-.*csv
128 jsonlog log/postgresql-.*json$|,
129 'new current_logfiles is sane');
131 # Verify that log output gets to this file, too
132 $node->psql('postgres', 'fee fi fo fum');
134 check_log_pattern('stderr', $new_current_logfiles, 'syntax error', $node);
135 check_log_pattern('csvlog', $new_current_logfiles, 'syntax error', $node);
136 check_log_pattern('jsonlog', $new_current_logfiles, 'syntax error', $node);
138 $node->stop();
140 done_testing();