unofficial mirror of meta@public-inbox.org
 help / color / mirror / Atom feed
* [PATCH 0/4] fix ENOSPC on writes
@ 2024-07-23 21:28 Eric Wong
  2024-07-23 21:28 ` [PATCH 1/4] t/msgmap: updates for Perl 5.12+ and copyrights Eric Wong
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Eric Wong @ 2024-07-23 21:28 UTC (permalink / raw)
  To: meta

2/4 is the actual fix to the bug reported by Robin, but the
others update tests and increase coverage for integration with
the v2 write path.

Eric Wong (4):
  t/msgmap: updates for Perl 5.12+ and copyrights
  msgmap: mid_insert: reraise on unexpected errors
  t/v2writable: test ENOSPC from fast-import
  t/v2writable: use 5.10.1 and autodie more

 lib/PublicInbox/Msgmap.pm |  6 +++-
 t/msgmap.t                | 25 ++++++++++---
 t/v2writable.t            | 76 +++++++++++++++++++++++++++++++--------
 3 files changed, 86 insertions(+), 21 deletions(-)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/4] t/msgmap: updates for Perl 5.12+ and copyrights
  2024-07-23 21:28 [PATCH 0/4] fix ENOSPC on writes Eric Wong
@ 2024-07-23 21:28 ` Eric Wong
  2024-07-23 21:28 ` [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors Eric Wong
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Eric Wong @ 2024-07-23 21:28 UTC (permalink / raw)
  To: meta

Test::More is redundant with TestCommon, and nothing here
conflicts with the unicode_strings feature in Perl v5.12.
---
 t/msgmap.t | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/t/msgmap.t b/t/msgmap.t
index a3b7200f..124d3b10 100644
--- a/t/msgmap.t
+++ b/t/msgmap.t
@@ -1,8 +1,7 @@
-# Copyright (C) 2015-2021 all contributors <meta@public-inbox.org>
+#!perl -w
+# Copyright (C) all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
-use strict;
-use warnings;
-use Test::More;
+use v5.12;
 use PublicInbox::TestCommon;
 require_mods('DBD::SQLite');
 use_ok 'PublicInbox::Msgmap';

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors
  2024-07-23 21:28 [PATCH 0/4] fix ENOSPC on writes Eric Wong
  2024-07-23 21:28 ` [PATCH 1/4] t/msgmap: updates for Perl 5.12+ and copyrights Eric Wong
@ 2024-07-23 21:28 ` Eric Wong
  2024-07-24  7:22   ` [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors, [PATCH 3/4] t/v2writable: test ENOSPC from fast-import Štěpán Němec
  2024-07-23 21:28 ` Eric Wong
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Eric Wong @ 2024-07-23 21:28 UTC (permalink / raw)
  To: meta

SQLITE_CONSTRAINT is the only SQLite error we really expect under
normal circumstances.  This avoids infinite loops when writing
to inboxes after hitting ENOSPC.

Reported-by: Robin H. Johnson <robbat2@orbis-terrarum.net>
Link: https://public-inbox.org/git/robbat2-20240722T060013-765939809Z@orbis-terrarum.net/
---
 lib/PublicInbox/Msgmap.pm |  6 +++++-
 t/msgmap.t                | 18 +++++++++++++++++-
 t/v2writable.t            | 18 +++++++++++++++++-
 3 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/lib/PublicInbox/Msgmap.pm b/lib/PublicInbox/Msgmap.pm
index cb4bb295..c4bc766d 100644
--- a/lib/PublicInbox/Msgmap.pm
+++ b/lib/PublicInbox/Msgmap.pm
@@ -12,6 +12,7 @@ use strict;
 use v5.10.1;
 use DBI;
 use DBD::SQLite;
+use DBD::SQLite::Constants qw(SQLITE_CONSTRAINT);
 use PublicInbox::Over;
 use Scalar::Util qw(blessed);
 
@@ -113,7 +114,10 @@ sub mid_insert {
 	my $sth = $self->{dbh}->prepare_cached(<<'');
 INSERT INTO msgmap (mid) VALUES (?)
 
-	return unless eval { $sth->execute($mid) };
+	unless (eval { $sth->execute($mid) }) {
+		return if $self->{dbh}->err == SQLITE_CONSTRAINT;
+		die $@;
+	}
 	my $num = $self->{dbh}->last_insert_id(undef, undef, 'msgmap', 'num');
 	$self->num_highwater($num) if defined($num);
 	$num;
diff --git a/t/msgmap.t b/t/msgmap.t
index 124d3b10..031854e0 100644
--- a/t/msgmap.t
+++ b/t/msgmap.t
@@ -3,6 +3,9 @@
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 use v5.12;
 use PublicInbox::TestCommon;
+use autodie;
+use Config;
+use PublicInbox::Spawn qw(popen_rd);
 require_mods('DBD::SQLite');
 use_ok 'PublicInbox::Msgmap';
 my ($tmpdir, $for_destroy) = tmpdir();
@@ -70,4 +73,17 @@ is(eval {
 	'ok'
 }, 'ok', 'atfork_* work on tmp_clone');
 
-done_testing();
+SKIP: {
+	my $strace = strace_inject;
+	open my $fh, '>', my $trace = "$tmpdir/trace.out";
+	my $rd = popen_rd([ $strace, '-p', $$, '-o', $trace,
+		'-e', 'inject=pwrite64:error=ENOSPC'], undef, { 2 => 1 });
+	$rd->poll_in(10) or die 'strace not ready';
+	is eval { $d->mid_insert('this-better-trigger-ENOSPC@error') },
+		undef, 'insert fails w/ ENOSPC';
+	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
+	kill 'TERM', $rd->attached_pid;
+	$rd->close;
+}
+
+done_testing;
diff --git a/t/v2writable.t b/t/v2writable.t
index 1b7e9e7d..a062d1b3 100644
--- a/t/v2writable.t
+++ b/t/v2writable.t
@@ -6,6 +6,8 @@ use Test::More;
 use PublicInbox::Eml;
 use PublicInbox::ContentHash qw(content_digest content_hash);
 use PublicInbox::TestCommon;
+use PublicInbox::Spawn qw(popen_rd);
+use Config;
 use Cwd qw(abs_path);
 require_git(2.6);
 require_mods(qw(DBD::SQLite Xapian));
@@ -335,4 +337,18 @@ ok($@, 'V2Writable fails on non-existent dir');
 	is($mode, 0664, sprintf('0%03o', $mode).' is 0664');
 }
 
-done_testing();
+SKIP: {
+	my $strace = strace_inject;
+	my $eml = eml_load 't/plack-qp.eml';
+	open my $fh, '>', my $trace = "$inboxdir/trace.out";
+	my $rd = popen_rd([ $strace, '-p', $$, '-o', $trace,
+		'-e', 'inject=pwrite64:error=ENOSPC'], undef, { 2 => 1 });
+	$rd->poll_in(10) or die 'strace not ready';
+	ok ! eval { $im->add($eml) }, 'v2w->add fails on ENOSPC';
+	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
+	$im->done;
+	kill 'TERM', $rd->attached_pid;
+	$rd->close;
+}
+
+done_testing;

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/4] t/v2writable: test ENOSPC from fast-import
  2024-07-23 21:28 [PATCH 0/4] fix ENOSPC on writes Eric Wong
  2024-07-23 21:28 ` [PATCH 1/4] t/msgmap: updates for Perl 5.12+ and copyrights Eric Wong
  2024-07-23 21:28 ` [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors Eric Wong
@ 2024-07-23 21:28 ` Eric Wong
  2024-07-23 21:28 ` [PATCH 4/4] t/v2writable: use 5.10.1 and autodie more Eric Wong
  2024-07-26 21:31 ` [PATCH v2 0/4] fix ENOSPC on writes Eric Wong
  4 siblings, 0 replies; 13+ messages in thread
From: Eric Wong @ 2024-07-23 21:28 UTC (permalink / raw)
  To: meta

This also ensures we can recover after the ENOSPC condition
is resolved.
---
 t/v2writable.t | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/t/v2writable.t b/t/v2writable.t
index a062d1b3..93385456 100644
--- a/t/v2writable.t
+++ b/t/v2writable.t
@@ -9,6 +9,7 @@ use PublicInbox::TestCommon;
 use PublicInbox::Spawn qw(popen_rd);
 use Config;
 use Cwd qw(abs_path);
+use autodie qw(kill open read);
 require_git(2.6);
 require_mods(qw(DBD::SQLite Xapian));
 local $ENV{HOME} = abs_path('t');
@@ -340,15 +341,46 @@ ok($@, 'V2Writable fails on non-existent dir');
 SKIP: {
 	my $strace = strace_inject;
 	my $eml = eml_load 't/plack-qp.eml';
+	my $gfi_err = "$inboxdir/gfi.err";
 	open my $fh, '>', my $trace = "$inboxdir/trace.out";
 	my $rd = popen_rd([ $strace, '-p', $$, '-o', $trace,
 		'-e', 'inject=pwrite64:error=ENOSPC'], undef, { 2 => 1 });
 	$rd->poll_in(10) or die 'strace not ready';
-	ok ! eval { $im->add($eml) }, 'v2w->add fails on ENOSPC';
+	ok ! eval {
+		open my $olderr, '>&', \*STDERR;
+		open STDERR, '>>', $gfi_err;
+		$im->add($eml);
+		open STDERR, '>&', $olderr;
+	}, 'v2w->add fails on ENOSPC';
 	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
 	$im->done;
 	kill 'TERM', $rd->attached_pid;
 	$rd->close;
+
+	$im->add($eml) or xbail 'cannot add message to start fast-import';
+	my $pid = $im->{im}->{io}->attached_pid or xbail 'no import pid';
+	open $fh, '>', $trace;
+
+	$rd = popen_rd([$strace, '-p', $pid, '-o', $trace,
+		'-e', 'inject=write:error=ENOSPC:when=1'],
+		undef, { 2 => 1 });
+	$rd->poll_in(10) or die 'strace not ready';
+	ok !eval { $im->done }, 'done fails with ENOSPC';
+	ok $@, '$@ set on ENOSPC';
+	kill 'TERM', $rd->attached_pid;
+
+	open $fh, '<', $gfi_err;
+	read $fh, my $errbuf, -s $fh;
+	like $errbuf, qr/fatal:/, 'fatal git error noted';
+	open $fh, '>', $gfi_err;
+
+	$rd->close;
+
+	$im->add($eml) or xbail '->add fail after fixing ENOSPC';
+	$im->done;
+	ok !$im->add($eml), '->add detects existing message';
+	$im->done;
+	is -s $fh, 0, 'nothing new fast-import stderr';
 }
 
 done_testing;

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 4/4] t/v2writable: use 5.10.1 and autodie more
  2024-07-23 21:28 [PATCH 0/4] fix ENOSPC on writes Eric Wong
                   ` (2 preceding siblings ...)
  2024-07-23 21:28 ` Eric Wong
@ 2024-07-23 21:28 ` Eric Wong
  2024-07-26 21:31 ` [PATCH v2 0/4] fix ENOSPC on writes Eric Wong
  4 siblings, 0 replies; 13+ messages in thread
From: Eric Wong @ 2024-07-23 21:28 UTC (permalink / raw)
  To: meta

Switching to Perl v5.12 will require more review due to
unicode_strings, but 5.10.1 is an easy change and we can rely
more on autodie to simplify error checking.
---
 t/v2writable.t | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/t/v2writable.t b/t/v2writable.t
index 93385456..c016b049 100644
--- a/t/v2writable.t
+++ b/t/v2writable.t
@@ -1,15 +1,14 @@
-# Copyright (C) 2018-2021 all contributors <meta@public-inbox.org>
+#!perl -w
+# Copyright (C) all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
-use strict;
-use warnings;
-use Test::More;
+use v5.10.1; # FIXME: check 5.12 unicode_strings compat
 use PublicInbox::Eml;
 use PublicInbox::ContentHash qw(content_digest content_hash);
 use PublicInbox::TestCommon;
 use PublicInbox::Spawn qw(popen_rd);
 use Config;
 use Cwd qw(abs_path);
-use autodie qw(kill open read);
+use autodie qw(chmod close kill open read);
 require_git(2.6);
 require_mods(qw(DBD::SQLite Xapian));
 local $ENV{HOME} = abs_path('t');
@@ -157,16 +156,15 @@ SELECT COUNT(*) FROM over WHERE num > 0
 	my $out = "$inboxdir/stdout.log";
 	my $group = 'inbox.comp.test.v2writable';
 	my $pi_config = "$inboxdir/pi_config";
-	open my $fh, '>', $pi_config or die "open: $!\n";
-	print $fh <<EOF
+	open my $fh, '>', $pi_config;
+	print $fh <<EOF;
 [publicinbox "test-v2writable"]
 	inboxdir = $inboxdir
 	version = 2
 	address = test\@example.com
 	newsgroup = $group
 EOF
-	;
-	close $fh or die "close: $!\n";
+	close $fh;
 	my $sock = tcp_server();
 	my $len;
 	my $cmd = [ '-nntpd', '-W0', "--stdout=$out", "--stderr=$err" ];
@@ -320,15 +318,15 @@ ok($@, 'V2Writable fails on non-existent dir');
 	$v2w->{parallel} = 0;
 	$v2w->init_inbox(0);
 	my $alt = "$tmp->{inboxdir}/all.git/objects/info/alternates";
-	open my $fh, '>>', $alt or die $!;
-	print $fh "$inboxdir/all.git/objects\n" or die $!;
-	chmod(0664, $fh) or die "fchmod: $!";
-	close $fh or die $!;
-	open $fh, '<', $alt or die $!;
+	open my $fh, '>>', $alt;
+	print $fh "$inboxdir/all.git/objects\n";
+	chmod 0664, $fh;
+	close $fh;
+	open $fh, '<', $alt;
 	my $before = do { local $/; <$fh> };
 
 	ok($v2w->{mg}->add_epoch(3), 'init a new epoch');
-	open $fh, '<', $alt or die $!;
+	open $fh, '<', $alt;
 	my $after = do { local $/; <$fh> };
 	ok(index($after, $before) > 0,
 		'old contents preserved after adding epoch');

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors, [PATCH 3/4] t/v2writable: test ENOSPC from fast-import
  2024-07-23 21:28 ` [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors Eric Wong
@ 2024-07-24  7:22   ` Štěpán Němec
  2024-07-25  0:38     ` Eric Wong
  0 siblings, 1 reply; 13+ messages in thread
From: Štěpán Němec @ 2024-07-24  7:22 UTC (permalink / raw)
  To: Eric Wong; +Cc: meta

Just a few nits in the new test messages, if I may:

[2/4]:
On Tue, 23 Jul 2024 21:28:35 +0000
Eric Wong wrote:

> SQLITE_CONSTRAINT is the only SQLite error we really expect under
> normal circumstances.  This avoids infinite loops when writing
> to inboxes after hitting ENOSPC.
[...]
> diff --git a/t/msgmap.t b/t/msgmap.t
[...]
> @@ -70,4 +73,17 @@ is(eval {
>  	'ok'
>  }, 'ok', 'atfork_* work on tmp_clone');
>  
> -done_testing();
> +SKIP: {
> +	my $strace = strace_inject;
> +	open my $fh, '>', my $trace = "$tmpdir/trace.out";
> +	my $rd = popen_rd([ $strace, '-p', $$, '-o', $trace,
> +		'-e', 'inject=pwrite64:error=ENOSPC'], undef, { 2 => 1 });
> +	$rd->poll_in(10) or die 'strace not ready';
> +	is eval { $d->mid_insert('this-better-trigger-ENOSPC@error') },
> +		undef, 'insert fails w/ ENOSPC';
> +	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
                                     ^^^^^^^^^^^^^^^^^
> +	kill 'TERM', $rd->attached_pid;
> +	$rd->close;
> +}
> +
> +done_testing;
> diff --git a/t/v2writable.t b/t/v2writable.t
[...]
> @@ -335,4 +337,18 @@ ok($@, 'V2Writable fails on non-existent dir');
>  	is($mode, 0664, sprintf('0%03o', $mode).' is 0664');
>  }
>  
> -done_testing();
> +SKIP: {
> +	my $strace = strace_inject;
> +	my $eml = eml_load 't/plack-qp.eml';
> +	open my $fh, '>', my $trace = "$inboxdir/trace.out";
> +	my $rd = popen_rd([ $strace, '-p', $$, '-o', $trace,
> +		'-e', 'inject=pwrite64:error=ENOSPC'], undef, { 2 => 1 });
> +	$rd->poll_in(10) or die 'strace not ready';
> +	ok ! eval { $im->add($eml) }, 'v2w->add fails on ENOSPC';
> +	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
                                     ^^^^^^^^^^^^^^^^^

[3/4]:
On Tue, 23 Jul 2024 21:28:36 +0000
Eric Wong wrote:

> This also ensures we can recover after the ENOSPC condition
> is resolved.
> ---
>  t/v2writable.t | 34 +++++++++++++++++++++++++++++++++-
>  1 file changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/t/v2writable.t b/t/v2writable.t
> index a062d1b3..93385456 100644
> --- a/t/v2writable.t
> +++ b/t/v2writable.t
[...]
> @@ -340,15 +341,46 @@ ok($@, 'V2Writable fails on non-existent dir');
[...]
> +	$rd->poll_in(10) or die 'strace not ready';
> +	ok !eval { $im->done }, 'done fails with ENOSPC';
> +	ok $@, '$@ set on ENOSPC';
                ^^^^^^^^^^^^^^^^
If I'm correct in assuming that no semantic nuance is
intended between the 'set $@ for ENOSPC' and '$@ set on
ENOSPC' variants, I suggest unifying on the latter (the
unequivocal passive reads clearer than the
imperative-looking 'set $@').

[...]

> +	$im->add($eml) or xbail '->add fail after fixing ENOSPC';

s/fail/fails/ ?

> +	$im->done;
> +	ok !$im->add($eml), '->add detects existing message';
> +	$im->done;
> +	is -s $fh, 0, 'nothing new fast-import stderr';

s/new/new on/ ?

Thanks.

-- 
Štěpán

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors, [PATCH 3/4] t/v2writable: test ENOSPC from fast-import
  2024-07-24  7:22   ` [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors, [PATCH 3/4] t/v2writable: test ENOSPC from fast-import Štěpán Němec
@ 2024-07-25  0:38     ` Eric Wong
  2024-07-25  6:42       ` Štěpán Němec
  0 siblings, 1 reply; 13+ messages in thread
From: Eric Wong @ 2024-07-25  0:38 UTC (permalink / raw)
  To: Štěpán Němec; +Cc: meta

Štěpán Němec <stepnem@smrk.net> wrote:
> Just a few nits in the new test messages, if I may:
> 
> [2/4]:
> > +	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
>                                      ^^^^^^^^^^^^^^^^^
> 
> [3/4]:
> > +	$rd->poll_in(10) or die 'strace not ready';
> > +	ok !eval { $im->done }, 'done fails with ENOSPC';
> > +	ok $@, '$@ set on ENOSPC';
>                 ^^^^^^^^^^^^^^^^
> If I'm correct in assuming that no semantic nuance is
> intended between the 'set $@ for ENOSPC' and '$@ set on
> ENOSPC' variants, I suggest unifying on the latter (the
> unequivocal passive reads clearer than the
> imperative-looking 'set $@').

The former ensures $@ matches qr/ disk is full/,
while the latter merely ensures $@ is set to a true value.

Arguably, the former could be '$@ reports ENOSPC'  *shrug*

> > +	$im->add($eml) or xbail '->add fail after fixing ENOSPC';
> 
> s/fail/fails/ ?
> 
> > +	$im->done;
> > +	ok !$im->add($eml), '->add detects existing message';
> > +	$im->done;
> > +	is -s $fh, 0, 'nothing new fast-import stderr';
> 
> s/new/new on/ ?

Will fix for v2.  Thanks.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors, [PATCH 3/4] t/v2writable: test ENOSPC from fast-import
  2024-07-25  0:38     ` Eric Wong
@ 2024-07-25  6:42       ` Štěpán Němec
  0 siblings, 0 replies; 13+ messages in thread
From: Štěpán Němec @ 2024-07-25  6:42 UTC (permalink / raw)
  To: Eric Wong; +Cc: meta

On Thu, 25 Jul 2024 00:38:24 +0000
Eric Wong wrote:

> Štěpán Němec <stepnem@smrk.net> wrote:
>> Just a few nits in the new test messages, if I may:
>> 
>> [2/4]:
>> > +	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
>>                                      ^^^^^^^^^^^^^^^^^
>> 
>> [3/4]:
>> > +	$rd->poll_in(10) or die 'strace not ready';
>> > +	ok !eval { $im->done }, 'done fails with ENOSPC';
>> > +	ok $@, '$@ set on ENOSPC';
>>                 ^^^^^^^^^^^^^^^^
>> If I'm correct in assuming that no semantic nuance is
>> intended between the 'set $@ for ENOSPC' and '$@ set on
>> ENOSPC' variants, I suggest unifying on the latter (the
>> unequivocal passive reads clearer than the
>> imperative-looking 'set $@').
>
> The former ensures $@ matches qr/ disk is full/,
> while the latter merely ensures $@ is set to a true value.
>
> Arguably, the former could be '$@ reports ENOSPC'  *shrug*

Indeed; 'set for' vs. 'set on' seems too subtle.

Thanks!

-- 
Štěpán

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 0/4] fix ENOSPC on writes
  2024-07-23 21:28 [PATCH 0/4] fix ENOSPC on writes Eric Wong
                   ` (3 preceding siblings ...)
  2024-07-23 21:28 ` [PATCH 4/4] t/v2writable: use 5.10.1 and autodie more Eric Wong
@ 2024-07-26 21:31 ` Eric Wong
  2024-07-26 21:31   ` [PATCH v2 1/4] t/msgmap: updates for Perl 5.12+ and copyrights Eric Wong
                     ` (3 more replies)
  4 siblings, 4 replies; 13+ messages in thread
From: Eric Wong @ 2024-07-26 21:31 UTC (permalink / raw)
  To: meta

v2 addresses grammar nits by Štěpán.

2/4 is the actual fix to the bug reported by Robin, but the
others update tests and increase coverage for integration with
the v2writable code path.

Eric Wong (4):
  t/msgmap: updates for Perl 5.12+ and copyrights
  msgmap: mid_insert: reraise on unexpected errors
  t/v2writable: test ENOSPC from fast-import
  t/v2writable: use 5.10.1 and autodie more

 lib/PublicInbox/Msgmap.pm |  6 +++-
 t/msgmap.t                | 25 ++++++++++---
 t/v2writable.t            | 76 +++++++++++++++++++++++++++++++--------
 3 files changed, 86 insertions(+), 21 deletions(-)

Range-diff against v1:
-:  -------- > 1:  c72c8a39 t/msgmap: updates for Perl 5.12+ and copyrights
1:  f1a53f30 ! 2:  c4ca4d41 msgmap: mid_insert: reraise on unexpected errors
    @@ t/msgmap.t: is(eval {
     +	$rd->poll_in(10) or die 'strace not ready';
     +	is eval { $d->mid_insert('this-better-trigger-ENOSPC@error') },
     +		undef, 'insert fails w/ ENOSPC';
    -+	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
    ++	like $@, qr/ disk is full/, '$@ reports ENOSPC';
     +	kill 'TERM', $rd->attached_pid;
     +	$rd->close;
     +}
2:  6de9c07c ! 3:  4f59948b t/v2writable: test ENOSPC from fast-import
    @@ t/v2writable.t: ok($@, 'V2Writable fails on non-existent dir');
      		'-e', 'inject=pwrite64:error=ENOSPC'], undef, { 2 => 1 });
      	$rd->poll_in(10) or die 'strace not ready';
     -	ok ! eval { $im->add($eml) }, 'v2w->add fails on ENOSPC';
    +-	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
     +	ok ! eval {
     +		open my $olderr, '>&', \*STDERR;
     +		open STDERR, '>>', $gfi_err;
     +		$im->add($eml);
     +		open STDERR, '>&', $olderr;
     +	}, 'v2w->add fails on ENOSPC';
    - 	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
    ++	like $@, qr/ disk is full/, '$@ reports ENOSPC';
      	$im->done;
      	kill 'TERM', $rd->attached_pid;
      	$rd->close;
    @@ t/v2writable.t: ok($@, 'V2Writable fails on non-existent dir');
     +
     +	$rd->close;
     +
    -+	$im->add($eml) or xbail '->add fail after fixing ENOSPC';
    ++	$im->add($eml) or xbail '->add fails after fixing ENOSPC';
     +	$im->done;
     +	ok !$im->add($eml), '->add detects existing message';
     +	$im->done;
    -+	is -s $fh, 0, 'nothing new fast-import stderr';
    ++	is -s $fh, 0, 'nothing new in fast-import stderr';
      }
      
      done_testing;
3:  f7d286d4 = 4:  fba5535f t/v2writable: use 5.10.1 and autodie more

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/4] t/msgmap: updates for Perl 5.12+ and copyrights
  2024-07-26 21:31 ` [PATCH v2 0/4] fix ENOSPC on writes Eric Wong
@ 2024-07-26 21:31   ` Eric Wong
  2024-07-26 21:31   ` [PATCH v2 2/4] msgmap: mid_insert: reraise on unexpected errors Eric Wong
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Eric Wong @ 2024-07-26 21:31 UTC (permalink / raw)
  To: meta

Test::More is redundant with TestCommon, and nothing here
conflicts with the unicode_strings feature in Perl v5.12.
---
 t/msgmap.t | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/t/msgmap.t b/t/msgmap.t
index a3b7200f..124d3b10 100644
--- a/t/msgmap.t
+++ b/t/msgmap.t
@@ -1,8 +1,7 @@
-# Copyright (C) 2015-2021 all contributors <meta@public-inbox.org>
+#!perl -w
+# Copyright (C) all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
-use strict;
-use warnings;
-use Test::More;
+use v5.12;
 use PublicInbox::TestCommon;
 require_mods('DBD::SQLite');
 use_ok 'PublicInbox::Msgmap';

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/4] msgmap: mid_insert: reraise on unexpected errors
  2024-07-26 21:31 ` [PATCH v2 0/4] fix ENOSPC on writes Eric Wong
  2024-07-26 21:31   ` [PATCH v2 1/4] t/msgmap: updates for Perl 5.12+ and copyrights Eric Wong
@ 2024-07-26 21:31   ` Eric Wong
  2024-07-26 21:31   ` [PATCH v2 3/4] t/v2writable: test ENOSPC from fast-import Eric Wong
  2024-07-26 21:31   ` [PATCH v2 4/4] t/v2writable: use 5.10.1 and autodie more Eric Wong
  3 siblings, 0 replies; 13+ messages in thread
From: Eric Wong @ 2024-07-26 21:31 UTC (permalink / raw)
  To: meta; +Cc: Robin H . Johnson

SQLITE_CONSTRAINT is the only SQLite error we really expect under
normal circumstances.  This avoids infinite loops when writing
to inboxes after hitting ENOSPC.

Reported-by: Robin H. Johnson <robbat2@orbis-terrarum.net>
Link: https://public-inbox.org/git/robbat2-20240722T060013-765939809Z@orbis-terrarum.net/
---
 lib/PublicInbox/Msgmap.pm |  6 +++++-
 t/msgmap.t                | 18 +++++++++++++++++-
 t/v2writable.t            | 18 +++++++++++++++++-
 3 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/lib/PublicInbox/Msgmap.pm b/lib/PublicInbox/Msgmap.pm
index cb4bb295..c4bc766d 100644
--- a/lib/PublicInbox/Msgmap.pm
+++ b/lib/PublicInbox/Msgmap.pm
@@ -12,6 +12,7 @@ use strict;
 use v5.10.1;
 use DBI;
 use DBD::SQLite;
+use DBD::SQLite::Constants qw(SQLITE_CONSTRAINT);
 use PublicInbox::Over;
 use Scalar::Util qw(blessed);
 
@@ -113,7 +114,10 @@ sub mid_insert {
 	my $sth = $self->{dbh}->prepare_cached(<<'');
 INSERT INTO msgmap (mid) VALUES (?)
 
-	return unless eval { $sth->execute($mid) };
+	unless (eval { $sth->execute($mid) }) {
+		return if $self->{dbh}->err == SQLITE_CONSTRAINT;
+		die $@;
+	}
 	my $num = $self->{dbh}->last_insert_id(undef, undef, 'msgmap', 'num');
 	$self->num_highwater($num) if defined($num);
 	$num;
diff --git a/t/msgmap.t b/t/msgmap.t
index 124d3b10..fb9c2d93 100644
--- a/t/msgmap.t
+++ b/t/msgmap.t
@@ -3,6 +3,9 @@
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
 use v5.12;
 use PublicInbox::TestCommon;
+use autodie;
+use Config;
+use PublicInbox::Spawn qw(popen_rd);
 require_mods('DBD::SQLite');
 use_ok 'PublicInbox::Msgmap';
 my ($tmpdir, $for_destroy) = tmpdir();
@@ -70,4 +73,17 @@ is(eval {
 	'ok'
 }, 'ok', 'atfork_* work on tmp_clone');
 
-done_testing();
+SKIP: {
+	my $strace = strace_inject;
+	open my $fh, '>', my $trace = "$tmpdir/trace.out";
+	my $rd = popen_rd([ $strace, '-p', $$, '-o', $trace,
+		'-e', 'inject=pwrite64:error=ENOSPC'], undef, { 2 => 1 });
+	$rd->poll_in(10) or die 'strace not ready';
+	is eval { $d->mid_insert('this-better-trigger-ENOSPC@error') },
+		undef, 'insert fails w/ ENOSPC';
+	like $@, qr/ disk is full/, '$@ reports ENOSPC';
+	kill 'TERM', $rd->attached_pid;
+	$rd->close;
+}
+
+done_testing;
diff --git a/t/v2writable.t b/t/v2writable.t
index 1b7e9e7d..a062d1b3 100644
--- a/t/v2writable.t
+++ b/t/v2writable.t
@@ -6,6 +6,8 @@ use Test::More;
 use PublicInbox::Eml;
 use PublicInbox::ContentHash qw(content_digest content_hash);
 use PublicInbox::TestCommon;
+use PublicInbox::Spawn qw(popen_rd);
+use Config;
 use Cwd qw(abs_path);
 require_git(2.6);
 require_mods(qw(DBD::SQLite Xapian));
@@ -335,4 +337,18 @@ ok($@, 'V2Writable fails on non-existent dir');
 	is($mode, 0664, sprintf('0%03o', $mode).' is 0664');
 }
 
-done_testing();
+SKIP: {
+	my $strace = strace_inject;
+	my $eml = eml_load 't/plack-qp.eml';
+	open my $fh, '>', my $trace = "$inboxdir/trace.out";
+	my $rd = popen_rd([ $strace, '-p', $$, '-o', $trace,
+		'-e', 'inject=pwrite64:error=ENOSPC'], undef, { 2 => 1 });
+	$rd->poll_in(10) or die 'strace not ready';
+	ok ! eval { $im->add($eml) }, 'v2w->add fails on ENOSPC';
+	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
+	$im->done;
+	kill 'TERM', $rd->attached_pid;
+	$rd->close;
+}
+
+done_testing;

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 3/4] t/v2writable: test ENOSPC from fast-import
  2024-07-26 21:31 ` [PATCH v2 0/4] fix ENOSPC on writes Eric Wong
  2024-07-26 21:31   ` [PATCH v2 1/4] t/msgmap: updates for Perl 5.12+ and copyrights Eric Wong
  2024-07-26 21:31   ` [PATCH v2 2/4] msgmap: mid_insert: reraise on unexpected errors Eric Wong
@ 2024-07-26 21:31   ` Eric Wong
  2024-07-26 21:31   ` [PATCH v2 4/4] t/v2writable: use 5.10.1 and autodie more Eric Wong
  3 siblings, 0 replies; 13+ messages in thread
From: Eric Wong @ 2024-07-26 21:31 UTC (permalink / raw)
  To: meta

This also ensures we can recover after the ENOSPC condition
is resolved.
---
 t/v2writable.t | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/t/v2writable.t b/t/v2writable.t
index a062d1b3..0493f90e 100644
--- a/t/v2writable.t
+++ b/t/v2writable.t
@@ -9,6 +9,7 @@ use PublicInbox::TestCommon;
 use PublicInbox::Spawn qw(popen_rd);
 use Config;
 use Cwd qw(abs_path);
+use autodie qw(kill open read);
 require_git(2.6);
 require_mods(qw(DBD::SQLite Xapian));
 local $ENV{HOME} = abs_path('t');
@@ -340,15 +341,46 @@ ok($@, 'V2Writable fails on non-existent dir');
 SKIP: {
 	my $strace = strace_inject;
 	my $eml = eml_load 't/plack-qp.eml';
+	my $gfi_err = "$inboxdir/gfi.err";
 	open my $fh, '>', my $trace = "$inboxdir/trace.out";
 	my $rd = popen_rd([ $strace, '-p', $$, '-o', $trace,
 		'-e', 'inject=pwrite64:error=ENOSPC'], undef, { 2 => 1 });
 	$rd->poll_in(10) or die 'strace not ready';
-	ok ! eval { $im->add($eml) }, 'v2w->add fails on ENOSPC';
-	like $@, qr/ disk is full/, 'set $@ for ENOSPC';
+	ok ! eval {
+		open my $olderr, '>&', \*STDERR;
+		open STDERR, '>>', $gfi_err;
+		$im->add($eml);
+		open STDERR, '>&', $olderr;
+	}, 'v2w->add fails on ENOSPC';
+	like $@, qr/ disk is full/, '$@ reports ENOSPC';
 	$im->done;
 	kill 'TERM', $rd->attached_pid;
 	$rd->close;
+
+	$im->add($eml) or xbail 'cannot add message to start fast-import';
+	my $pid = $im->{im}->{io}->attached_pid or xbail 'no import pid';
+	open $fh, '>', $trace;
+
+	$rd = popen_rd([$strace, '-p', $pid, '-o', $trace,
+		'-e', 'inject=write:error=ENOSPC:when=1'],
+		undef, { 2 => 1 });
+	$rd->poll_in(10) or die 'strace not ready';
+	ok !eval { $im->done }, 'done fails with ENOSPC';
+	ok $@, '$@ set on ENOSPC';
+	kill 'TERM', $rd->attached_pid;
+
+	open $fh, '<', $gfi_err;
+	read $fh, my $errbuf, -s $fh;
+	like $errbuf, qr/fatal:/, 'fatal git error noted';
+	open $fh, '>', $gfi_err;
+
+	$rd->close;
+
+	$im->add($eml) or xbail '->add fails after fixing ENOSPC';
+	$im->done;
+	ok !$im->add($eml), '->add detects existing message';
+	$im->done;
+	is -s $fh, 0, 'nothing new in fast-import stderr';
 }
 
 done_testing;

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 4/4] t/v2writable: use 5.10.1 and autodie more
  2024-07-26 21:31 ` [PATCH v2 0/4] fix ENOSPC on writes Eric Wong
                     ` (2 preceding siblings ...)
  2024-07-26 21:31   ` [PATCH v2 3/4] t/v2writable: test ENOSPC from fast-import Eric Wong
@ 2024-07-26 21:31   ` Eric Wong
  3 siblings, 0 replies; 13+ messages in thread
From: Eric Wong @ 2024-07-26 21:31 UTC (permalink / raw)
  To: meta

Switching to Perl v5.12 will require more review due to
unicode_strings, but 5.10.1 is an easy change and we can rely
more on autodie to simplify error checking.
---
 t/v2writable.t | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/t/v2writable.t b/t/v2writable.t
index 0493f90e..496eba2c 100644
--- a/t/v2writable.t
+++ b/t/v2writable.t
@@ -1,15 +1,14 @@
-# Copyright (C) 2018-2021 all contributors <meta@public-inbox.org>
+#!perl -w
+# Copyright (C) all contributors <meta@public-inbox.org>
 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
-use strict;
-use warnings;
-use Test::More;
+use v5.10.1; # FIXME: check 5.12 unicode_strings compat
 use PublicInbox::Eml;
 use PublicInbox::ContentHash qw(content_digest content_hash);
 use PublicInbox::TestCommon;
 use PublicInbox::Spawn qw(popen_rd);
 use Config;
 use Cwd qw(abs_path);
-use autodie qw(kill open read);
+use autodie qw(chmod close kill open read);
 require_git(2.6);
 require_mods(qw(DBD::SQLite Xapian));
 local $ENV{HOME} = abs_path('t');
@@ -157,16 +156,15 @@ SELECT COUNT(*) FROM over WHERE num > 0
 	my $out = "$inboxdir/stdout.log";
 	my $group = 'inbox.comp.test.v2writable';
 	my $pi_config = "$inboxdir/pi_config";
-	open my $fh, '>', $pi_config or die "open: $!\n";
-	print $fh <<EOF
+	open my $fh, '>', $pi_config;
+	print $fh <<EOF;
 [publicinbox "test-v2writable"]
 	inboxdir = $inboxdir
 	version = 2
 	address = test\@example.com
 	newsgroup = $group
 EOF
-	;
-	close $fh or die "close: $!\n";
+	close $fh;
 	my $sock = tcp_server();
 	my $len;
 	my $cmd = [ '-nntpd', '-W0', "--stdout=$out", "--stderr=$err" ];
@@ -320,15 +318,15 @@ ok($@, 'V2Writable fails on non-existent dir');
 	$v2w->{parallel} = 0;
 	$v2w->init_inbox(0);
 	my $alt = "$tmp->{inboxdir}/all.git/objects/info/alternates";
-	open my $fh, '>>', $alt or die $!;
-	print $fh "$inboxdir/all.git/objects\n" or die $!;
-	chmod(0664, $fh) or die "fchmod: $!";
-	close $fh or die $!;
-	open $fh, '<', $alt or die $!;
+	open my $fh, '>>', $alt;
+	print $fh "$inboxdir/all.git/objects\n";
+	chmod 0664, $fh;
+	close $fh;
+	open $fh, '<', $alt;
 	my $before = do { local $/; <$fh> };
 
 	ok($v2w->{mg}->add_epoch(3), 'init a new epoch');
-	open $fh, '<', $alt or die $!;
+	open $fh, '<', $alt;
 	my $after = do { local $/; <$fh> };
 	ok(index($after, $before) > 0,
 		'old contents preserved after adding epoch');

^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-07-26 21:43 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-23 21:28 [PATCH 0/4] fix ENOSPC on writes Eric Wong
2024-07-23 21:28 ` [PATCH 1/4] t/msgmap: updates for Perl 5.12+ and copyrights Eric Wong
2024-07-23 21:28 ` [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors Eric Wong
2024-07-24  7:22   ` [PATCH 2/4] msgmap: mid_insert: reraise on unexpected errors, [PATCH 3/4] t/v2writable: test ENOSPC from fast-import Štěpán Němec
2024-07-25  0:38     ` Eric Wong
2024-07-25  6:42       ` Štěpán Němec
2024-07-23 21:28 ` Eric Wong
2024-07-23 21:28 ` [PATCH 4/4] t/v2writable: use 5.10.1 and autodie more Eric Wong
2024-07-26 21:31 ` [PATCH v2 0/4] fix ENOSPC on writes Eric Wong
2024-07-26 21:31   ` [PATCH v2 1/4] t/msgmap: updates for Perl 5.12+ and copyrights Eric Wong
2024-07-26 21:31   ` [PATCH v2 2/4] msgmap: mid_insert: reraise on unexpected errors Eric Wong
2024-07-26 21:31   ` [PATCH v2 3/4] t/v2writable: test ENOSPC from fast-import Eric Wong
2024-07-26 21:31   ` [PATCH v2 4/4] t/v2writable: use 5.10.1 and autodie more Eric Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).