diff options
author | Eric Wong <e@yhbt.net> | 2020-06-10 07:04:40 +0000 |
---|---|---|
committer | Eric Wong <e@yhbt.net> | 2020-06-13 07:55:45 +0000 |
commit | cfae078171fc1453be0795e4ba5f0252627ebba3 (patch) | |
tree | 743f0b1b5cf356bf018b5619619edd362dcdd0a8 /t | |
parent | 48180dbb004b5f59b2e80613b6fa2e5e869316f1 (diff) | |
download | public-inbox-cfae078171fc1453be0795e4ba5f0252627ebba3.tar.gz |
Finish up the IMAP-only portion of iterative config reloading, which allows us to create all sub-ranges of an inbox up front. The InboxIdler still uses ->each_inbox which will struggle with 100K inboxes. Having messages in the top-level newsgroup name of an inbox will still waste bandwidth for clients which want to do full syncs once there's a rollover to a new 50K range. So instead, make every inbox accessible exclusively via 50K slices in the form of "$NEWSGROUP.$UID_MIN-$UID_END". This introduces the DummyInbox, which makes $NEWSGROUP and every parent component a selectable, empty inbox. This aids navigation with mutt and possibly other MUAs. Finally, the xt/perf-imap-list maintainer test is broken, now, so remove it. The grep perlfunc is already proven effective, and we'll have separate tests for mocking out ~100k inboxes.
Diffstat (limited to 't')
-rw-r--r-- | t/imap.t | 33 | ||||
-rw-r--r-- | t/imapd.t | 22 |
2 files changed, 42 insertions, 13 deletions
@@ -6,16 +6,39 @@ use strict; use Test::More; use PublicInbox::IMAP; use PublicInbox::IMAPD; +use PublicInbox::TestCommon; +require_mods(qw(DBD::SQLite)); +require_git 2.6; -{ # make sure we get '%' globbing right +my ($tmpdir, $for_destroy) = tmpdir(); +my $cfgfile = "$tmpdir/config"; +{ + open my $fh, '>', $cfgfile or BAIL_OUT $!; + print $fh <<EOF or BAIL_OUT $!; +[publicinbox "a"] + inboxdir = $tmpdir/a + newsgroup = x.y.z +[publicinbox "b"] + inboxdir = $tmpdir/b + newsgroup = x.z.y +[publicinbox "c"] + inboxdir = $tmpdir/c + newsgroup = IGNORE.THIS +EOF + close $fh or BAIL_OUT $!; + local $ENV{PI_CONFIG} = $cfgfile; + for my $x (qw(a b c)) { + ok(run_script(['-init', '-Lbasic', '-V2', $x, "$tmpdir/$x", + "https://example.com/$x", "$x\@example.com"]), + "init $x"); + } + my $imapd = PublicInbox::IMAPD->new; my @w; local $SIG{__WARN__} = sub { push @w, @_ }; - my @n = map { { newsgroup => $_ } } (qw(x.y.z x.z.y IGNORE.THIS)); - my $self = { imapd => { grouplist => \@n } }; - PublicInbox::IMAPD::refresh_inboxlist($self->{imapd}); + $imapd->refresh_groups; + my $self = { imapd => $imapd }; is(scalar(@w), 1, 'got a warning for upper-case'); like($w[0], qr/IGNORE\.THIS/, 'warned about upper-case'); - my $res = PublicInbox::IMAP::cmd_list($self, 'tag', 'x', '%'); is(scalar($$res =~ tr/\n/\n/), 2, 'only one result'); like($$res, qr/ x\r\ntag OK/, 'saw expected'); @@ -16,6 +16,9 @@ if ($can_compress) { # hope this gets fixed upstream, soon $imap_client = 'PublicInbox::IMAPClient'; } +require_ok 'PublicInbox::IMAP'; +my $first_range = '1-'.PublicInbox::IMAP::UID_BLOCK(); + my $level = '-Lbasic'; SKIP: { require_mods('Search::Xapian', 1); @@ -87,11 +90,13 @@ ok(!$mic->examine('foo') && ($e = $@), 'EXAMINE non-existent'); like($e, qr/\bNO\b/, 'got a NO on EXAMINE for non-existent'); ok(!$mic->select('foo') && ($e = $@), 'EXAMINE non-existent'); like($e, qr/\bNO\b/, 'got a NO on EXAMINE for non-existent'); -ok($mic->select('inbox.i1'), 'SELECT succeeds'); -ok($mic->examine('INBOX.i1'), 'EXAMINE succeeds'); -my @raw = $mic->status('inbox.i1', qw(Messages uidnext uidvalidity)); +my $mailbox1 = "inbox.i1.$first_range"; +ok($mic->select('inbox.i1'), 'SELECT on parent succeeds'); +ok($mic->select($mailbox1), 'SELECT succeeds'); +ok($mic->examine($mailbox1), 'EXAMINE succeeds'); +my @raw = $mic->status($mailbox1, qw(Messages uidnext uidvalidity)); is(scalar(@raw), 2, 'got status response'); -like($raw[0], qr/\A\*\x20STATUS\x20inbox\.i1\x20 +like($raw[0], qr/\A\*\x20STATUS\x20inbox\.i1\.$first_range\x20 \(MESSAGES\x20\d+\x20UIDNEXT\x20\d+\x20UIDVALIDITY\x20\d+\)\r\n/sx); like($raw[1], qr/\A\S+ OK /, 'finished status response'); @@ -99,7 +104,7 @@ like($raw[1], qr/\A\S+ OK /, 'finished status response'); like($raw[0], qr/^\* LIST \(.*?\) "\." inbox/, 'got an inbox'); like($raw[-1], qr/^\S+ OK /, 'response ended with OK'); -is(scalar(@raw), scalar(@V) + 2, 'default LIST response'); +is(scalar(@raw), scalar(@V) + 4, 'default LIST response'); @raw = $mic->list('', 'inbox.i1'); is(scalar(@raw), 2, 'limited LIST response'); like($raw[0], qr/^\* LIST \(.*?\) "\." inbox/, @@ -199,7 +204,7 @@ SKIP: { skip 'Mail::IMAPClient too old for ->compress', 2 if !$can_compress; my $c = $imap_client->new(%mic_opt); ok($c && $c->compress, 'compress enabled'); - ok($c->examine('inbox.i1'), 'EXAMINE succeeds after COMPRESS'); + ok($c->examine($mailbox1), 'EXAMINE succeeds after COMPRESS'); $ret = $c->search('uid 1:*') or BAIL_OUT "SEARCH FAIL $@"; is_deeply($ret, [ 1 ], 'search UID 1:* works after compression'); } @@ -216,11 +221,12 @@ $pi_config->each_inbox(sub { my $ng = $ibx->{newsgroup}; my $mic = $imap_client->new(%mic_opt); ok($mic && $mic->login && $mic->IsAuthenticated, "authed $name"); - my $uidnext = $mic->uidnext($ng); # we'll fetch BODYSTRUCTURE on this + my $mb = "$ng.$first_range"; + my $uidnext = $mic->uidnext($mb); # we'll fetch BODYSTRUCTURE on this ok($uidnext, 'got uidnext for later fetch'); is_deeply([$mic->has_capability('IDLE')], ['IDLE'], "IDLE capa $name"); ok(!$mic->idle, "IDLE fails w/o SELECT/EXAMINE $name"); - ok($mic->examine($ng), "EXAMINE $ng succeeds"); + ok($mic->examine($mb), "EXAMINE $ng succeeds"); ok(my $idle_tag = $mic->idle, "IDLE succeeds on $ng"); open(my $fh, '<', 't/data/message_embed.eml') or BAIL_OUT("open: $!"); |