]> Sergey Matveev's repositories - public-inbox.git/blobdiff - t/nntpd.t
nntp: support slow blob retrievals
[public-inbox.git] / t / nntpd.t
index 66aa48f1e67946def9ef5005222f191f00f6b91e..c681b01c3d9d4eb40036ae9f8e98543c2f1bd07b 100644 (file)
--- a/t/nntpd.t
+++ b/t/nntpd.t
@@ -4,19 +4,23 @@ use strict;
 use warnings;
 use Test::More;
 use PublicInbox::TestCommon;
+use PublicInbox::Spawn qw(which);
 require_mods(qw(DBD::SQLite));
-require PublicInbox::SearchIdx;
-require PublicInbox::Msgmap;
 require PublicInbox::InboxWritable;
-use Email::Simple;
+use PublicInbox::Eml;
 use IO::Socket;
 use Socket qw(IPPROTO_TCP TCP_NODELAY);
 use Net::NNTP;
 use Sys::Hostname;
+use POSIX qw(_exit);
+use Digest::SHA;
 
 # FIXME: make easier to test both versions
-my $version = $ENV{PI_TEST_VERSION} || 2;
+my $version = $ENV{PI_TEST_VERSION} || 1;
 require_git('2.6') if $version == 2;
+my $lsof = which('lsof');
+my $fast_idle = eval { require Linux::Inotify2; 1 } //
+               eval { require IO::KQueue; 1 };
 
 my ($tmpdir, $for_destroy) = tmpdir();
 my $home = "$tmpdir/pi-home";
@@ -54,11 +58,11 @@ $ibx = PublicInbox::Inbox->new($ibx);
        my $len;
 
        $ibx = PublicInbox::InboxWritable->new($ibx);
-       my $im = $ibx->importer;
+       my $im = $ibx->importer(0);
 
        # ensure successful message delivery
        {
-               my $mime = Email::MIME->new(<<EOF);
+               my $mime = PublicInbox::Eml->new(<<EOF);
 To: =?utf-8?Q?El=C3=A9anor?= <you\@example.com>
 From: =?utf-8?Q?El=C3=A9anor?= <me\@example.com>
 Cc: $addr
@@ -74,12 +78,15 @@ EOF
                my $list_id = $addr;
                $list_id =~ s/@/./;
                $mime->header_set('List-Id', "<$list_id>");
-               $len = length($mime->as_string);
+               my $str = $mime->as_string;
+               $str =~ s/(?<!\r)\n/\r\n/sg;
+               $len = length($str);
+               undef $str;
                $im->add($mime);
                $im->done;
                if ($version == 1) {
-                       my $s = PublicInbox::SearchIdx->new($ibx, 1);
-                       $s->index_sync;
+                       ok(run_script(['-index', $ibx->{inboxdir}]),
+                               'indexed v1');
                }
        }
 
@@ -242,7 +249,7 @@ EOF
                ok($date <= $t1, 'valid date before stop');
        }
        if ('leafnode interop') {
-               my $for_leafnode = PublicInbox::MIME->new(<<"");
+               my $for_leafnode = PublicInbox::Eml->new(<<"");
 From: longheader\@example.com
 To: $addr
 Subject: none
@@ -253,8 +260,8 @@ Date: Fri, 02 Oct 1993 00:00:00 +0000
                $im->add($for_leafnode);
                $im->done;
                if ($version == 1) {
-                       my $s = PublicInbox::SearchIdx->new($ibx, 1);
-                       $s->index_sync;
+                       ok(run_script(['-index', $ibx->{inboxdir}]),
+                               'indexed v1');
                }
                my $hdr = $n->head("<$long_hdr>");
                my $expect = qr/\AMessage-ID: /i . qr/\Q<$long_hdr>\E/;
@@ -282,34 +289,74 @@ Date: Fri, 02 Oct 1993 00:00:00 +0000
        # pipelined requests:
        {
                my $nreq = 90;
+               my $nart = 2;
                syswrite($s, "GROUP $group\r\n");
                my $res = <$s>;
                my $rdr = fork;
                if ($rdr == 0) {
-                       use POSIX qw(_exit);
                        for (1..$nreq) {
                                <$s> =~ /\A224 / or _exit(1);
                                <$s> =~ /\A1/ or _exit(2);
                                <$s> eq ".\r\n" or _exit(3);
                        }
+                       my %sums;
+                       for (1..$nart) {
+                               <$s> =~ /\A220 / or _exit(4);
+                               my $dig = Digest::SHA->new(1);
+                               while (my $l = <$s>) {
+                                       last if $l eq ".\r\n";
+                                       $dig->add($l);
+                               }
+                               $dig = $dig->hexdigest;
+                               $sums{$dig}++;
+                       }
+                       if ($nart) {
+                               scalar(keys(%sums)) == 1 or _exit(5);
+                               (values(%sums))[0] == $nart or _exit(6);
+                       }
                        _exit(0);
                }
                for (1..$nreq) {
                        syswrite($s, "XOVER 1\r\n");
                }
+               syswrite($s, "ARTICLE 1\r\n" x $nart);
                is($rdr, waitpid($rdr, 0), 'reader done');
                is($? >> 8, 0, 'no errors');
        }
+       my $noerr = { 2 => \(my $null) };
        SKIP: {
                if ($INC{'Search/Xapian.pm'} && ($ENV{TEST_RUN_MODE}//2)) {
                        skip 'Search/Xapian.pm pre-loaded (by t/run.perl?)', 1;
                }
-               my $rdr = { 2 => \(my $null) };
-               my @of = xqx(['lsof', '-p', $td->{pid}], undef, $rdr);
+               $lsof or skip 'lsof missing', 1;
+               my @of = xqx([$lsof, '-p', $td->{pid}], undef, $noerr);
                skip('lsof broken', 1) if (!scalar(@of) || $?);
                my @xap = grep m!Search/Xapian!, @of;
                is_deeply(\@xap, [], 'Xapian not loaded in nntpd');
        }
+       # -compact requires Xapian
+       SKIP: {
+               require_mods('Search::Xapian', 2);
+               which('xapian-compact') or skip 'xapian-compact missing', 2;
+               is(xsys(qw(git config), "--file=$home/.public-inbox/config",
+                               "publicinbox.$group.indexlevel", 'medium'),
+                       0, 'upgraded indexlevel');
+               my $ex = eml_load('t/data/0001.patch');
+               is($n->article($ex->header('Message-ID')), undef,
+                       'article did not exist');
+               $im->add($ex);
+               $im->done;
+               ok(run_script([qw(-index --reindex -c), $ibx->{inboxdir}],
+                               undef, $noerr), '-compacted');
+               select(undef, undef, undef, $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
+                       skip "lsof /(deleted)/ check untested on $^O", 1;
+               my @of = xqx([$lsof, '-p', $td->{pid}], undef, $noerr);
+               is(scalar(grep(/\(deleted\)/, @of)), 0, 'no deleted files');
+       };
        {
                setsockopt($s, IPPROTO_TCP, TCP_NODELAY, 1);
                syswrite($s, 'HDR List-id 1-');
@@ -326,15 +373,14 @@ Date: Fri, 02 Oct 1993 00:00:00 +0000
                        'got 5xx response for unoptimized HDR');
                is(scalar @r, 1, 'only one response line');
        }
-
        $n = $s = undef;
        $td->join;
-       my $eout = eval {
-               local $/;
+       is($?, 0, 'no error in exited process');
+       my $eout = do {
                open my $fh, '<', $err or die "open $err failed: $!";
+               local $/;
                <$fh>;
        };
-       is($?, 0, 'no error in exited process');
        unlike($eout, qr/wide/i, 'no Wide character warnings');
 }