Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vkPfW-00Ej0D-1O for pgsql-hackers@arkaria.postgresql.org; Mon, 26 Jan 2026 16:42:27 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vkPfU-0092wP-0s for pgsql-hackers@arkaria.postgresql.org; Mon, 26 Jan 2026 16:42:24 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vkPfT-0092wH-0b for pgsql-hackers@lists.postgresql.org; Mon, 26 Jan 2026 16:42:24 +0000 Received: from fhigh-a2-smtp.messagingengine.com ([103.168.172.153]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1vkPfQ-00000000ZNs-08XM for pgsql-hackers@lists.postgresql.org; Mon, 26 Jan 2026 16:42:23 +0000 Received: from phl-compute-04.internal (phl-compute-04.internal [10.202.2.44]) by mailfhigh.phl.internal (Postfix) with ESMTP id 4DFF91400022; Mon, 26 Jan 2026 11:42:18 -0500 (EST) Received: from phl-frontend-03 ([10.202.2.162]) by phl-compute-04.internal (MEProxy); Mon, 26 Jan 2026 11:42:18 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anarazel.de; h= cc:cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm2; t=1769445738; x=1769532138; bh=oMLpDTc84q M2PL5O4f43Q2CN8XFP0qof0xB7tPXtxqo=; b=PuHGiTHjrc9D1wsygAsgXA8tKt kNTKolACziAJJs0UHzfAJpqh/I/g/aYAFDfEzwRnT48hAIkUGGdS9MIe6sjzFDsE SqckqvedEcSzNkPD81GEwePd6+NMuudNnz8aaILFe2TQcT0jvUX0J70zAFi8ah8B V06cyNrvFd2P4zK506LDhKGih3i8cgWqqHCGUtRbtUFXuGBxM1hBsVMSdKWWrhUq tvoNanKhAa7Kbx2/iGW3K9aetPNd/bPHjGB7a+/JRNeiQ0qvTDH2KH6AY/Fwr+W1 fQEf0RiWlr4t573bDmvxZ9kjyBH/2gWI0+NTviXx8eH+78qNhXlw+pK3bWRQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t= 1769445738; x=1769532138; bh=oMLpDTc84qM2PL5O4f43Q2CN8XFP0qof0xB 7tPXtxqo=; b=HfIMuqFWy8olsPON4xBJRqFceVk8i6qii0mVIs3NtuzoE1YuHNd btdm/RaEBPJEJLhSSsrevDqOyOl7KdYsT/nc7VSPDcyUEciE7WC0EOShxlMQNLD8 HtIIobbmaY+6IgqbRSC3fL+kDvTbyki418R5ByZ73ONOYo4U41nl9t9GxlXmJ9H+ IwUX1RKmffqGbQJ+TYu7/TTLHsfAkM1dzzM6EVSacVez4rzMhonB9rHWxtSBcFid FRnXM/u52x14fYzwsCvaYN0twViCKFjYCq5Xcc/u94LVsJ+i6onf4/HD3n6R/R3H IAhUVm1/l8EACZjf+dwuC0BQx/OSY2wXmUQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgdduheekudekucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhepfffhvfevuffkfhggtggujgesthdtsfdttddtvdenucfhrhhomheptehnughrvghs ucfhrhgvuhhnugcuoegrnhgurhgvshesrghnrghrrgiivghlrdguvgeqnecuggftrfgrth htvghrnhepjedttefhhedthfegffdtteffgfdvvdelhfffheffheegvdevlefgieektefh feeinecuffhomhgrihhnpehpohhsthhgrhgvshhqlhdrohhrghdptghluhhsthgvrhdrph hmpdhuthhilhhsrdhpmhenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgr ihhlfhhrohhmpegrnhgurhgvshesrghnrghrrgiivghlrdguvgdpnhgspghrtghpthhtoh epfedpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepsgihrghvuhiikedusehgmhgr ihhlrdgtohhmpdhrtghpthhtohepphhoshhtghhrvghssehjvghlthgvfhdrnhhlpdhrtg hpthhtohepphhgshhqlhdqhhgrtghkvghrsheslhhishhtshdrphhoshhtghhrvghsqhhl rdhorhhg X-ME-Proxy: Feedback-ID: id4a34324:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 26 Jan 2026 11:42:17 -0500 (EST) Date: Mon, 26 Jan 2026 11:42:16 -0500 From: Andres Freund To: Jelte Fennema-Nio Cc: PostgreSQL Hackers , Nazir Bilal Yavuz Subject: Re: meson: Make test output much more useful on failure (both in CI and locally) Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi, On 2026-01-26 11:13:57 +0100, Jelte Fennema-Nio wrote: > I've gotten totally fed up with the amount of clicking I need to do > every time a test fails in CI to find out what exactly failed. The > output that meson gives in its main output is completely useless > currently. This doesn't really seem meson specific, right? It just seems about the output of our own test tooling? Meson can't really output something that we hide from it... I agree that what we currently do is pretty unhelpful. > Subject: [PATCH v1 1/5] meson: Include pg_regress diffs in meson output This isn't about meson, it's about adding a new argument to pg_regress. I think we'd need to limit the size of the output here somewhat. If e.g. the server crashes, you end up with all subsequent tests failing and printing out a couple hundred kB of pointless diff output. > @@ -1521,22 +1523,40 @@ results_differ(const char *testname, const char *resultsfile, const char *defaul > * append to the diffs summary file. > */ > > - /* Write diff header */ > - difffile = fopen(difffilename, "a"); > + difffile = fopen(difffilename, "a+"); > if (difffile) > { > + fseek(difffile, 0, SEEK_END); > + startpos = ftell(difffile); > fprintf(difffile, > "diff %s %s %s\n", > pretty_diff_opts, best_expect_file, resultsfile); > + fflush(difffile); > + > + /* Run diff */ > + snprintf(cmd, sizeof(cmd), > + "diff %s \"%s\" \"%s\" >> \"%s\"", > + pretty_diff_opts, best_expect_file, resultsfile, difffilename); > + run_diff(cmd, difffilename); > + > + /* Emit diff as TAP diagnostics if requested */ > + if (print_diffs) > + { > + char line[1024]; > + > + fseek(difffile, startpos, SEEK_SET); > + while (fgets(line, sizeof(line), difffile)) > + { > + size_t len = strlen(line); > + > + if (len > 0 && line[len - 1] == '\n') > + line[len - 1] = '\0'; > + diag("%s", line); > + } > + } > fclose(difffile); > } I'm a bit confused. Why are we rerunning diffs and appending to the diff file? > From c1db07a8bba54e6b903766585f1b521ef526de12 Mon Sep 17 00:00:00 2001 > From: Jelte Fennema-Nio > Date: Mon, 26 Jan 2026 09:09:11 +0100 > Subject: [PATCH v1 2/5] perl tap: Show failed command output > > This adds the output of failed commands to the TAP output. Before a > failed libpq_pipeline test would look like this: > > Failed test 'libpq_pipeline cancel' > at /home/jelte/work/postgres-3/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl line 55. > > Now you can actually see the reason of the failure: > > Failed test 'libpq_pipeline cancel' > at /home/jelte/work/postgres-3/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl line 55. > ----- command failed ----- > libpq_pipeline -r 700 cancel port=14309 host=/tmp/htMib451qD dbname='postgres' max_protocol_version=latest > --------- stderr --------- > test cancellations... > libpq_pipeline:315: unexpected number of rows received: 1 > -------------------------- > --- > src/test/perl/PostgreSQL/Test/Utils.pm | 36 +++++++++++++++++++++++--- > 1 file changed, 32 insertions(+), 4 deletions(-) > > diff --git a/src/test/perl/PostgreSQL/Test/Utils.pm b/src/test/perl/PostgreSQL/Test/Utils.pm > index ff843eecc6e..bd1e981c6f0 100644 > --- a/src/test/perl/PostgreSQL/Test/Utils.pm > +++ b/src/test/perl/PostgreSQL/Test/Utils.pm > @@ -955,8 +955,22 @@ sub command_ok > { > local $Test::Builder::Level = $Test::Builder::Level + 1; > my ($cmd, $test_name) = @_; > - my $result = run_log($cmd); > - ok($result, $test_name); > + # Doesn't rely on detecting end of file on the file descriptors, > + # which can fail, causing the process to hang, notably on Msys > + # when used with 'pg_ctl start' > + my $stdoutfile = File::Temp->new(); > + my $stderrfile = File::Temp->new(); I'm afraid that the creation of this many additional tempfiles would slow down the tests on some platforms... > + my $result = IPC::Run::run $cmd, '>' => $stdoutfile, '2>' => $stderrfile; > + ok($result, $test_name) or do > + { > + my $stdout = slurp_file($stdoutfile); > + my $stderr = slurp_file($stderrfile); > + diag("----- command failed -----"); > + diag(join(" ", @$cmd)); > + diag("--------- stdout ---------"), diag($stdout) if $stdout; > + diag("--------- stderr ---------"), diag($stderr) if $stderr; > + diag("--------------------------"); > + }; Outputting the entire file seems to again have the danger of completely swamping the output. > return; > } > > @@ -972,8 +986,22 @@ sub command_fails > { > local $Test::Builder::Level = $Test::Builder::Level + 1; > my ($cmd, $test_name) = @_; > - my $result = run_log($cmd); > - ok(!$result, $test_name); > + # Doesn't rely on detecting end of file on the file descriptors, > + # which can fail, causing the process to hang, notably on Msys > + # when used with 'pg_ctl start' Huh? Any more details? > + my $stdoutfile = File::Temp->new(); > + my $stderrfile = File::Temp->new(); > + my $result = IPC::Run::run $cmd, '>' => $stdoutfile, '2>' => $stderrfile; > + ok(!$result, $test_name) or do > + { > + my $stdout = slurp_file($stdoutfile); > + my $stderr = slurp_file($stderrfile); > + diag("-- command succeeded unexpectedly --"); > + diag(join(" ", @$cmd)); > + diag("-------------- stdout --------------"), diag($stdout) if $stdout; > + diag("-------------- stderr --------------"), diag($stderr) if $stderr; > + diag("------------------------------------"); > + }; I don't think it makes sense to duplicate the logic for this multiple times. > From c88f1fbf6462da56a1f0739dd83a6284d6bdd389 Mon Sep 17 00:00:00 2001 > From: Jelte Fennema-Nio > Date: Mon, 26 Jan 2026 09:32:15 +0100 > Subject: [PATCH v1 3/5] perl tap: Show die reason in TAP output >... > diff --git a/src/test/perl/PostgreSQL/Test/Utils.pm b/src/test/perl/PostgreSQL/Test/Utils.pm > index bd1e981c6f0..df328d0f571 100644 > --- a/src/test/perl/PostgreSQL/Test/Utils.pm > +++ b/src/test/perl/PostgreSQL/Test/Utils.pm > @@ -206,6 +206,14 @@ INIT > # test may still fail, but it's more likely to report useful facts. > $SIG{PIPE} = 'IGNORE'; > > + # Emit die messages as TAP diagnostics so they appear in test output. > + $SIG{__DIE__} = sub { > + return if $^S; # Ignore dies inside eval > + my $msg = shift; > + chomp $msg; > + diag("die: $msg"); > + }; > + This looked familiar - turns out I had complained about this in the past and then forgotten about it :( https://www.postgresql.org/message-id/20220222181924.eehi7o4pmneeb4hm%40alap3.anarazel.de At least at the time I found it necessary to separately test for $^S, to avoid triggering the logic for syntax errors. Not sure why I concluded that though. In a reply Andrew suggested to use done_testing(), which avoids the pointless "Tests were run but no plan was declared and done_testing() was not seen." which does seem like an improvement. > From a6b324678293d65f3a417b8f66889b3f3f6a9c29 Mon Sep 17 00:00:00 2001 > From: Jelte Fennema-Nio > Date: Mon, 26 Jan 2026 10:04:44 +0100 > Subject: [PATCH v1 4/5] perl tap: Include caller in die messages of psql > > This way by looking at the error output you can actually figure out > where it occured, instead of just knowing that is in the very often > called psql function. I think this is too localized a fix. Right now every die in a .pm file has this issue. The easiest fix would probably be to just replace all uses of die in .pm files with croak (which we already, inconsistently, use). stderr: # die: error running SQL: 'psql::1: ERROR: syntax error at or near "I" # LINE 1: I am the worst # ^' # while running 'psql --no-psqlrc --no-align --tuples-only --quiet --dbname port=20878 host=/tmp/K5V48mzFx9 dbname='postgres' --file - --variable ON_ERROR_STOP=1' with sql 'I am the worst' at /home/andres/src/postgresql/src/bin/scripts/t/020_createdb.pl line 19. Note that the failure now is reported as coming from the actual test file. We could also use Test::More->builder->croak(), but that's a heck of a lot longer, and would require us to be more liberal about sprinkling local $Test::Builder::Level = $Test::Builder::Level + 1; around. I don't see an improvement in the output either. In contrast Carp.pm just looks for a caller outside of the current package. If we are worried about errors across Cluster.pm/Utils.pm, we could just fix that in one place by using @CARP_NOT. Maybe there's a way to do that more centrally? Greetings, Andres Freund