From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 9552C1F63E for ; Mon, 30 Jan 2023 22:50:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1675119007; bh=bBnrd8VPPNY/hPqqvH+a1zr4jWyzKoFEU2YqZcHseH0=; h=From:To:Subject:Date:From; b=vSq2vkLEbvm1JK95rVpClQLE6OhK2HzwrqgFwi0wnzy/rt6rWnwRRhWoYgp2/dSVA WqQI/wW9hRbnuegr2CgHOToqHEryXR1xS51M9pf/WfN5uW38oLtVpwfKTgmw6uQfUT LgMstUs9NQebNkJzsr7eBxVcjl7WxsKwvPVFhlOk= From: Eric Wong To: meta@public-inbox.org Subject: [PATCH] tests: make require_git and require_cmd easier-to-use Date: Mon, 30 Jan 2023 22:50:07 +0000 Message-Id: <20230130225007.3835300-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: We'll rely on defined(wantarray) to implicitly skip subtests, and memoize these to reduce syscalls, since tests should be short-lived enough to not be affected by new installations or removals of git/xapian-compact/curl/etc... --- lib/PublicInbox/TestCommon.pm | 38 +++++++++++++++++++---------------- t/admin.t | 4 ++-- t/config.t | 5 ++--- t/convert-compact.t | 5 ++--- t/git.t | 5 +++-- t/imapd.t | 5 ++--- t/import.t | 9 +++++---- t/index-git-times.t | 5 ++--- t/init.t | 8 ++++---- t/nntpd.t | 2 +- t/v2mirror.t | 4 ++-- xt/git-http-backend.t | 8 +++----- xt/httpd-async-stream.t | 8 ++++---- xt/imapd-mbsync-oimap.t | 9 +++++---- xt/pop3d-mpop.t | 8 ++++---- 15 files changed, 62 insertions(+), 61 deletions(-) diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm index b36c71a6..1fe7931e 100644 --- a/lib/PublicInbox/TestCommon.pm +++ b/lib/PublicInbox/TestCommon.pm @@ -93,31 +93,35 @@ sub tcp_connect { } sub require_cmd ($;$) { - my ($cmd, $maybe) = @_; + my ($cmd, $nr) = @_; require PublicInbox::Spawn; - my $bin = PublicInbox::Spawn::which($cmd); + state %CACHE; + my $bin = $CACHE{$cmd} //= PublicInbox::Spawn::which($cmd); return $bin if $bin; - $maybe ? 0 : plan(skip_all => "$cmd missing from PATH for $0"); + return plan(skip_all => "$cmd missing from PATH for $0") if !$nr; + defined(wantarray) ? undef : skip("$cmd missing, skipping $nr tests") } -sub have_xapian_compact () { - require_cmd($ENV{XAPIAN_COMPACT} || 'xapian-compact', 1); +sub have_xapian_compact (;$) { + require_cmd($ENV{XAPIAN_COMPACT} || 'xapian-compact', @_ ? $_[0] : ()); } sub require_git ($;$) { - my ($req, $maybe) = @_; - my ($req_maj, $req_min, $req_sub) = split(/\./, $req); - my ($cur_maj, $cur_min, $cur_sub) = (xqx([qw(git --version)]) - =~ /version (\d+)\.(\d+)(?:\.(\d+))?/); + my ($req, $nr) = @_; + state ($cur_int, $cur_ver); + $cur_int //= do { + chomp($cur_ver = xqx([qw(git --version)])); + my @v = ($cur_ver =~ /version (\d+)\.(\d+)(?:\.(\d+))?/); + ($v[0] << 24) | ($v[1] << 16) | ($v[2] // 0); + }; + my ($req_maj, $req_min, $req_sub) = split(/\./, $req); my $req_int = ($req_maj << 24) | ($req_min << 16) | ($req_sub // 0); - my $cur_int = ($cur_maj << 24) | ($cur_min << 16) | ($cur_sub // 0); - if ($cur_int < $req_int) { - return 0 if $maybe; - plan skip_all => - "git $req+ required, have $cur_maj.$cur_min.$cur_sub"; - } - 1; + + return 1 if $cur_int >= $req_int; + return plan skip_all => "git $req+ required, have $cur_ver" if !$nr; + defined(wantarray) ? undef : + skip("git $req+ required (have $cur_ver), skipping $nr tests") } my %IPv6_VERSION = ( @@ -570,7 +574,7 @@ SKIP: { my $test_opt = shift // {}; local $lei_cwdfh; opendir $lei_cwdfh, '.' or xbail "opendir .: $!"; - require_git(2.6, 1) or skip('git 2.6+ required for lei test', 2); + require_git(2.6, 1); my $mods = $test_opt->{mods} // [ 'lei' ]; require_mods(@$mods, 2); diff --git a/t/admin.t b/t/admin.t index 8d09bfc1..20e3deb7 100644 --- a/t/admin.t +++ b/t/admin.t @@ -1,5 +1,5 @@ #!perl -w -# Copyright (C) 2019-2021 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ use strict; use v5.10.1; @@ -13,7 +13,7 @@ my ($res, $err, $v); my $v2ibx; SKIP: { require_mods(qw(DBD::SQLite), 5); - require_git(2.6, 1) or skip 5, 'git too old'; + require_git(2.6, 5); $v2ibx = create_inbox 'v2', indexlevel => 'basic', version => 2, -no_gc => 1, sub { my ($v2w, $ibx) = @_; diff --git a/t/config.t b/t/config.t index 7e753cbe..ba83e63f 100644 --- a/t/config.t +++ b/t/config.t @@ -1,4 +1,4 @@ -# Copyright (C) 2014-2021 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ use strict; use v5.10.1; @@ -245,8 +245,7 @@ EOF SKIP: { # XXX wildcard match requires git 2.26+ - require_git('1.8.5', 2) or - skip 'git 1.8.5+ required for --url-match', 2; + require_git('1.8.5', 2); my $f = "$tmpdir/urlmatch"; open my $fh, '>', $f or BAIL_OUT $!; print $fh < +# Copyright (C) all contributors # License: AGPL-3.0+ use strict; use v5.10.1; @@ -8,8 +8,7 @@ use PublicInbox::TestCommon; use PublicInbox::Import; require_git(2.6); require_mods(qw(DBD::SQLite Search::Xapian)); -have_xapian_compact or - plan skip_all => 'xapian-compact missing for '.__FILE__; +have_xapian_compact; my ($tmpdir, $for_destroy) = tmpdir(); my $ibx = create_inbox 'v1', indexlevel => 'medium', tmpdir => "$tmpdir/v1", pre_cb => sub { diff --git a/t/git.t b/t/git.t index d8957e42..dfa5eab2 100644 --- a/t/git.t +++ b/t/git.t @@ -1,7 +1,8 @@ +#!perl -w # Copyright (C) all contributors # License: AGPL-3.0+ use strict; -use Test::More; +use v5.10.1; use PublicInbox::TestCommon; my ($dir, $for_destroy) = tmpdir(); use PublicInbox::Import; @@ -134,7 +135,7 @@ if (1) { } SKIP: { - require_git(2.6, 7) or skip('need git 2.6+ for --batch-all-objects', 7); + require_git(2.6, 7); my ($alt, $alt_obj) = tmpdir(); my $hash_obj = [ 'git', "--git-dir=$alt", qw(hash-object -w --stdin) ]; PublicInbox::Import::init_bare($alt); diff --git a/t/imapd.t b/t/imapd.t index cbd6c1b9..c7dc01a5 100644 --- a/t/imapd.t +++ b/t/imapd.t @@ -3,7 +3,7 @@ # License: AGPL-3.0+ # end-to-end IMAP tests, see unit tests in t/imap.t, too use strict; -use Test::More; +use v5.10.1; use Time::HiRes (); use PublicInbox::TestCommon; use PublicInbox::Config; @@ -438,8 +438,7 @@ ok($mic->logout, 'logged out'); SKIP: { use_ok 'PublicInbox::InboxIdle'; - require_git('1.8.5', 1) or - skip('git 1.8.5+ needed for --urlmatch', 4); + require_git '1.8.5', 4; my $old_env = { HOME => $ENV{HOME} }; my $home = "$tmpdir/watch_home"; mkdir $home or BAIL_OUT $!; diff --git a/t/import.t b/t/import.t index 4ba74022..f1d61dae 100644 --- a/t/import.t +++ b/t/import.t @@ -1,8 +1,8 @@ +#!perl -w # Copyright (C) all contributors # License: AGPL-3.0+ +use v5.10.1; use strict; -use warnings; -use Test::More; use PublicInbox::Eml; use PublicInbox::Smsg; use PublicInbox::Git; @@ -26,10 +26,11 @@ hello world EOF my $v2 = require_git(2.6, 1); -my $smsg = bless {}, 'PublicInbox::Smsg' if $v2; +my $smsg = $v2 ? bless({}, 'PublicInbox::Smsg') : undef; like($im->add($mime, undef, $smsg), qr/\A:[0-9]+\z/, 'added one message'); -if ($v2) { +SKIP: { + skip 'git 2.6+ required', 3 if !$v2; like($smsg->{blob}, qr/\A[a-f0-9]{40,64}\z/, 'got last object_id'); my @cmd = ('git', "--git-dir=$git->{git_dir}", qw(hash-object --stdin)); open my $in, '+<', undef or BAIL_OUT "open(+<): $!"; diff --git a/t/index-git-times.t b/t/index-git-times.t index 52173396..ffe9223c 100644 --- a/t/index-git-times.t +++ b/t/index-git-times.t @@ -1,9 +1,8 @@ #!perl -w -# Copyright (C) 2020-2021 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ use strict; use v5.10.1; -use Test::More; use PublicInbox::TestCommon; use PublicInbox::Config; use PublicInbox::Admin; @@ -74,7 +73,7 @@ my $smsg; is($res->[0]->{ds}, $smsg->{ds}, 'Xapian search on datestamp'); } SKIP: { - require_git(2.6, 1) or skip('git 2.6+ required for v2', 10); + require_git(2.6, 10); my $v2dir = "$tmpdir/v2"; run_script(['-convert', $v1dir, $v2dir]) or die 'v2 conversion failed'; diff --git a/t/init.t b/t/init.t index 460c83f3..46258e45 100644 --- a/t/init.t +++ b/t/init.t @@ -1,8 +1,8 @@ -# Copyright (C) 2014-2021 all contributors +#!perl -w +# Copyright (C) all contributors # License: AGPL-3.0+ use strict; -use warnings; -use Test::More; +use v5.10.1; use PublicInbox::Config; use PublicInbox::TestCommon; use PublicInbox::Admin; @@ -117,7 +117,7 @@ sub quiet_fail { SKIP: { require_mods(qw(DBD::SQLite Search::Xapian), 2); - require_git(2.6, 1) or skip "git 2.6+ required", 2; + require_git(2.6, 2); use_ok 'PublicInbox::Msgmap'; local $ENV{PI_DIR} = "$tmpdir/.public-inbox/"; local $ENV{PI_EMERGENCY} = "$tmpdir/.public-inbox/emergency"; diff --git a/t/nntpd.t b/t/nntpd.t index 84a60574..dbbc37b8 100644 --- a/t/nntpd.t +++ b/t/nntpd.t @@ -413,7 +413,7 @@ sub test_watch { use_ok 'PublicInbox::Watch'; use_ok 'PublicInbox::InboxIdle'; use_ok 'PublicInbox::Config'; - require_git('1.8.5', 1) or skip('git 1.8.5+ needed for --urlmatch', 4); + require_git('1.8.5', 4); my $old_env = { HOME => $ENV{HOME} }; my $home = "$tmpdir/watch_home"; mkdir $home or BAIL_OUT $!; diff --git a/t/v2mirror.t b/t/v2mirror.t index f9074e45..c1c66d45 100644 --- a/t/v2mirror.t +++ b/t/v2mirror.t @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2021 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ use strict; use v5.10.1; @@ -330,7 +330,7 @@ SKIP: { require_mods('Email::MIME', 1); # for legacy revision # using plackup to test old PublicInbox::WWW since -httpd from # back then relied on some packages we no longer depend on - my $plackup = which('plackup') or skip('no plackup in path', 1); + my $plackup = require_cmd('plackup', 1) or skip('no plackup in path', 1); require PublicInbox::Lock; chomp $oldrev; my ($base) = ($0 =~ m!\b([^/]+)\.[^\.]+\z!); diff --git a/xt/git-http-backend.t b/xt/git-http-backend.t index 1f3ba063..d78fe79f 100644 --- a/xt/git-http-backend.t +++ b/xt/git-http-backend.t @@ -1,14 +1,13 @@ +#!perl -w # Copyright (C) all contributors # License: AGPL-3.0+ # # Ensure buffering behavior in -httpd doesn't cause runaway memory use # or data corruption use strict; -use warnings; -use Test::More; +use v5.10.1; use POSIX qw(setsid); use PublicInbox::TestCommon; -use PublicInbox::Spawn qw(which); my $git_dir = $ENV{GIANT_GIT_DIR}; plan 'skip_all' => 'GIANT_GIT_DIR not defined' unless $git_dir; @@ -77,8 +76,7 @@ SKIP: { # make sure Last-Modified + If-Modified-Since works with curl my $nr = 6; skip 'no description', $nr unless -f "$git_dir/description"; my $mtime = (stat(_))[9]; - my $curl = which('curl'); - skip 'curl(1) not found', $nr unless $curl; + my $curl = require_cmd('curl', 1) or skip 'curl(1) not found', $nr; my $url = "http://$host:$port/description"; my $dst = "$tmpdir/desc"; is(xsys($curl, qw(-RsSf), '-o', $dst, $url), 0, 'curl -R'); diff --git a/xt/httpd-async-stream.t b/xt/httpd-async-stream.t index c7039f3e..0658c691 100644 --- a/xt/httpd-async-stream.t +++ b/xt/httpd-async-stream.t @@ -1,17 +1,17 @@ #!perl -w -# Copyright (C) 2020-2021 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ # Expensive test to validate compression and TLS. use strict; -use Test::More; +use v5.10.1; use PublicInbox::TestCommon; use PublicInbox::DS qw(now); -use PublicInbox::Spawn qw(which popen_rd); +use PublicInbox::Spawn qw(popen_rd); use Digest::MD5; use POSIX qw(_exit); my $inboxdir = $ENV{GIANT_INBOX_DIR}; plan skip_all => "GIANT_INBOX_DIR not defined for $0" unless $inboxdir; -my $curl = which('curl') or plan skip_all => "curl(1) missing for $0"; +my $curl = require_cmd('curl'); my ($tmpdir, $for_destroy) = tmpdir(); require_mods(qw(DBD::SQLite)); my $JOBS = $ENV{TEST_JOBS} // 4; diff --git a/xt/imapd-mbsync-oimap.t b/xt/imapd-mbsync-oimap.t index 0baf5b4c..b0281105 100644 --- a/xt/imapd-mbsync-oimap.t +++ b/xt/imapd-mbsync-oimap.t @@ -1,12 +1,12 @@ #!perl -w -# Copyright (C) 2020-2021 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ # ensure mbsync and offlineimap compatibility use strict; use v5.10.1; use File::Path qw(mkpath); use PublicInbox::TestCommon; -use PublicInbox::Spawn qw(which spawn); +use PublicInbox::Spawn qw(spawn); require_mods(qw(-imapd)); my $inboxdir = $ENV{GIANT_INBOX_DIR}; (defined($inboxdir) && -d $inboxdir) or @@ -42,7 +42,8 @@ my %pids; SKIP: { mkpath([map { "$tmpdir/oimapdir/$_" } qw(cur new tmp)]); - my $oimap = which('offlineimap') or skip 'no offlineimap(1)', 1; + my $oimap = require_cmd('offlineimap', 1) or + skip 'no offlineimap(1)', 1; open my $fh, '>', "$tmpdir/.offlineimaprc" or BAIL_OUT "open: $!"; print $fh <', "$tmpdir/.mbsyncrc" or BAIL_OUT "open: $!"; print $fh < "GIANT_INBOX_DIR not defined for $0"; plan skip_all => "bad characters in $inboxdir" if $inboxdir =~ m![^\w\.\-/]!; -my $uuidgen = which('uuidgen') or plan skip_all => 'uuidgen(1) missing'; +my $uuidgen = require_cmd('uuidgen'); +my $mpop = require_cmd('mpop'); require_mods(qw(DBD::SQLite)); require_git('2.6'); # for v2 require_mods(qw(File::FcntlLock)) if $^O !~ /\A(?:linux|freebsd)\z/; @@ -41,8 +42,7 @@ chomp(my $uuid = xqx([$uuidgen])); make_path("$tmpdir/home/.config/mpop", map { "$tmpdir/md/$_" } qw(new cur tmp)); -SKIP: { - my $mpop = which('mpop') or skip('mpop(1) missing', 1); +{ open my $fh, '>', "$tmpdir/home/.config/mpop/config" or xbail "open $!"; chmod 0600, $fh;