From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH 04/14] tests: attempt compatibility w/ busybox lsof
Date: Wed, 13 Dec 2023 00:50:09 +0000 [thread overview]
Message-ID: <20231213005019.26912-5-e@80x24.org> (raw)
In-Reply-To: <20231213005019.26912-1-e@80x24.org>
BusyBox lsof(1) ignores the `-p PID' argument and shows
the open files for every process it knows about. BusyBox
lsof also lacks the `NODE' column of the non-BusyBox
implementation, so we'll rely on /proc/PID/fd/ in those
cases since the deleted file checks are Linux-only and
it's common to have procfs is mounted on /proc on Linux.
---
lib/PublicInbox/TestCommon.pm | 23 ++++++++++++++++++++++-
t/ds-leak.t | 5 +----
t/httpd-corner.t | 31 +++++++++++--------------------
t/nntpd.t | 16 +++++++---------
t/v2reindex.t | 5 ++---
5 files changed, 43 insertions(+), 37 deletions(-)
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm
index 27a758e4..9c413f43 100644
--- a/lib/PublicInbox/TestCommon.pm
+++ b/lib/PublicInbox/TestCommon.pm
@@ -29,7 +29,7 @@ BEGIN {
tcp_host_port test_lei lei lei_ok $lei_out $lei_err $lei_opt
test_httpd xbail require_cmd is_xdeeply tail_f
ignore_inline_c_missing no_pollerfd no_coredump cfg_new
- strace strace_inject);
+ strace strace_inject lsof_pid);
require Test::More;
my @methods = grep(!/\W/, @Test::More::EXPORT);
eval(join('', map { "*$_=\\&Test::More::$_;" } @methods));
@@ -951,6 +951,26 @@ sub test_httpd ($$;$$) {
}
};
+# TODO: support fstat(1) on OpenBSD, lsof already works on FreeBSD + Linux
+# don't use this for deleted file checks, we only check that on Linux atm
+# and we can readlink /proc/PID/fd/* directly
+sub lsof_pid ($;$) {
+ my ($pid, $rdr) = @_;
+ state $lsof = require_cmd('lsof', 1);
+ $lsof or skip 'lsof missing/broken', 1;
+ my @out = xqx([$lsof, '-p', $pid], undef, $rdr);
+ if ($?) {
+ undef $lsof;
+ skip "lsof -p PID broken \$?=$?", 1;
+ }
+ my @cols = split ' ', $out[0];
+ if (($cols[7] // '') eq 'NODE') { # normal lsof
+ @out;
+ } else { # busybox lsof ignores -p, so we DIY it
+ grep /\b$pid\b/, @out;
+ }
+}
+
sub no_pollerfd ($) {
my ($pid) = @_;
my ($re, @cmd);
@@ -966,6 +986,7 @@ sub no_pollerfd ($) {
my @of = xqx(\@cmd, {}, {2 => \(my $e)});
my $err = $?;
skip "$bin broken? (\$?=$err) ($e)", 1 if $err;
+ @of = grep /\b$pid\b/, @of; # busybox lsof ignores -p
is(grep(/$re/, @of), 0, "no $re FDs") or diag explain(\@of);
}
}
diff --git a/t/ds-leak.t b/t/ds-leak.t
index 179997eb..f39985e0 100644
--- a/t/ds-leak.t
+++ b/t/ds-leak.t
@@ -29,11 +29,8 @@ if ('close-on-exec for epoll and kqueue') {
is($l, undef, 'cloexec works and sleep(1) is running');
SKIP: {
- my $lsof = require_cmd('lsof', 1) or skip 'lsof missing', 1;
my $rdr = { 2 => \(my $null) };
- my @of = grep(/$evfd_re/, xqx([$lsof, '-p', $pid], {}, $rdr));
- my $err = $?;
- skip "lsof broken ? (\$?=$err)", 1 if $err;
+ my @of = grep /$evfd_re/, lsof_pid $pid, $rdr;
is_deeply(\@of, [], 'no FDs leaked to subprocess');
};
if (defined $pid) {
diff --git a/t/httpd-corner.t b/t/httpd-corner.t
index da1c24b9..35c88600 100644
--- a/t/httpd-corner.t
+++ b/t/httpd-corner.t
@@ -639,30 +639,21 @@ SKIP: {
};
SKIP: {
- skip 'only testing lsof(8) output on Linux', 1 if $^O ne 'linux';
- my $lsof = require_cmd('lsof', 1) or skip 'no lsof in PATH', 1;
- my $null_in = '';
- my $rdr = { 2 => \(my $null_err), 0 => \$null_in };
- my @lsof = xqx([$lsof, '-p', $td->{pid}], undef, $rdr);
- my $d = [ grep(/\(deleted\)/, @lsof) ];
- is_deeply($d, [], 'no lingering deleted inputs') or diag explain($d);
+ skip 'only testing /proc/PID/fd on Linux', 1 if $^O ne 'linux';
+ my $fd_dir = "/proc/$td->{pid}/fd";
+ -d $fd_dir or skip '/proc/$PID/fd missing', 1;
+ my @child = grep defined, map readlink, glob "$fd_dir/*";
+ my @d = grep /\(deleted\)/, @child;
+ is_deeply(\@d, [], 'no lingering deleted inputs') or diag explain(\@d);
# filter out pipes inherited from the parent
- my @this = xqx([$lsof, '-p', $$], undef, $rdr);
- my $bad;
- my $extract_inodes = sub {
- map {;
- my @f = split(' ', $_);
- my $inode = $f[-2];
- $bad = $_ if $inode !~ /\A[0-9]+\z/;
- $inode => 1;
- } grep (/\bpipe\b/, @_);
- };
- my %child = $extract_inodes->(@lsof);
+ my @this = grep defined, map readlink, glob "/proc/$$/fd/*";
+ my $extract_inodes = sub { map { $_ => 1 } grep /\bpipe\b/, @_ };
+ my %child = $extract_inodes->(@child);
my %parent = $extract_inodes->(@this);
- skip("inode not in expected format: $bad", 1) if defined($bad);
delete @child{(keys %parent)};
- is_deeply([], [keys %child], 'no extra pipes with -W0');
+ is_deeply([], [keys %child], 'no extra pipes with -W0') or
+ diag explain([child => \%child, parent => \%parent]);
};
# ensure compatibility with other PSGI servers
diff --git a/t/nntpd.t b/t/nntpd.t
index ffe0fd8c..0f3ef596 100644
--- a/t/nntpd.t
+++ b/t/nntpd.t
@@ -14,7 +14,6 @@ use PublicInbox::DS;
my $version = $ENV{PI_TEST_VERSION} || 1;
require_git('2.6') if $version == 2;
use_ok 'PublicInbox::Msgmap';
-my $lsof = require_cmd('lsof', 1);
my $fast_idle = eval { require Linux::Inotify2; 1 } //
eval { require IO::KQueue; 1 };
@@ -332,9 +331,7 @@ Date: Fri, 02 Oct 1993 00:00:00 +0000
($ENV{TEST_RUN_MODE} // 2)) {
skip 'Xapian.pm pre-loaded (by xt/check-run.t?)', 1;
}
- $lsof or skip 'lsof missing', 1;
- my @of = xqx([$lsof, '-p', $td->{pid}], undef, $noerr);
- skip('lsof broken', 1) if (!scalar(@of) || $?);
+ my @of = lsof_pid $td->{pid}, $noerr;
my @xap = grep m!\bXapian\b!, @of;
is_deeply(\@xap, [], 'Xapian not loaded in nntpd') or
diag explain(\@of);
@@ -364,12 +361,13 @@ Date: Fri, 02 Oct 1993 00:00:00 +0000
tick($fast_idle ? 0.1 : 2.1);
$art = $n->article($ex->header('Message-ID'));
ok($art, 'new article retrieved after compact');
- $lsof or skip 'lsof missing', 1;
- ($^O =~ /\A(?:linux)\z/) or
+ $^O eq 'linux' or
skip "lsof /(deleted)/ check untested on $^O", 1;
- my @lsof = xqx([$lsof, '-p', $td->{pid}], undef, $noerr);
- my $d = [ grep(/\(deleted\)/, grep(!/batch-command\.err/, @lsof)) ];
- is_deeply($d, [], 'no deleted files') or diag explain($d);
+ my $fd = "/proc/$td->{pid}/fd";
+ -d $fd or skip '/proc/PID/fd missing', 1;
+ my @of = map readlink, glob "$fd/*";
+ my @d = grep /\(deleted\)/, grep !/batch-command\.err/, @of;
+ is_deeply(\@d, [], 'no deleted files') or diag explain(\@d);
};
SKIP: { test_watch($tmpdir, $host_port, $group) };
{
diff --git a/t/v2reindex.t b/t/v2reindex.t
index 406c0517..8c49e154 100644
--- a/t/v2reindex.t
+++ b/t/v2reindex.t
@@ -1,4 +1,4 @@
-# Copyright (C) 2018-2021 all contributors <meta@public-inbox.org>
+# Copyright (C) all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
use strict; use v5.10.1; use PublicInbox::TestCommon;
use PublicInbox::Eml;
@@ -549,9 +549,8 @@ is($err, '', 'no errors from --xapian-only');
undef $for_destroy;
SKIP: {
skip 'only testing lsof(8) output on Linux', 1 if $^O ne 'linux';
- my $lsof = require_cmd('lsof', 1) or skip 'no lsof in PATH', 1;
my $rdr = { 2 => \(my $null_err) };
- my @d = grep(m!/xap[0-9]+/!, xqx([$lsof, '-p', $$], undef, $rdr));
+ my @d = grep m!/xap[0-9]+/!, lsof_pid $$, $rdr;
is_deeply(\@d, [], 'no deleted index files') or diag explain(\@d);
}
done_testing();
next prev parent reply other threads:[~2023-12-13 0:50 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-13 0:50 [PATCH 00/14] Alpine Linux support Eric Wong
2023-12-13 0:50 ` [PATCH 01/14] t/io: strace is optional on Linux Eric Wong
2023-12-13 0:50 ` [PATCH 02/14] tests: account for missing git-http-backend Eric Wong
2023-12-13 0:50 ` [PATCH 03/14] t/cindex*: skip --join when join(1) is missing Eric Wong
2023-12-13 0:50 ` Eric Wong [this message]
2023-12-13 0:50 ` [PATCH 05/14] lei inspect: drop unneeded strftime import Eric Wong
2023-12-13 0:50 ` [PATCH 06/14] treewide: avoid strftime %k for portability Eric Wong
2023-12-13 0:50 ` [PATCH 07/14] xap_helper_cxx: decouple from Inline::C Eric Wong
2023-12-13 0:50 ` [PATCH 08/14] xap_helper_cxx: support clang w/o `c++' executable Eric Wong
2023-12-13 0:50 ` [PATCH 09/14] install: updates for Alpine Linux and apk Eric Wong
2023-12-13 0:50 ` [PATCH 10/14] test_common: extract oct_is from search.t Eric Wong
2023-12-13 0:50 ` [PATCH 11/14] t/convert-compact: allow S_ISGID bit Eric Wong
2023-12-13 0:50 ` [PATCH 12/14] www_coderepo: fix read buffering Eric Wong
2023-12-13 0:50 ` [PATCH 13/14] gzip_filter: use OO ->zflush dispatch Eric Wong
2023-12-13 0:50 ` [PATCH 14/14] t/lei-import: relax EIO regexp Eric Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://public-inbox.org/README
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231213005019.26912-5-e@80x24.org \
--to=e@80x24.org \
--cc=meta@public-inbox.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).