]> Sergey Matveev's repositories - public-inbox.git/blobdiff - t/imapd.t
imap: remove dummies from sequence number FETCH
[public-inbox.git] / t / imapd.t
index 2c4315dec30fb19b003a790944ebb2c7e0227a0d..233be9f2c0a796b469d99dcd2ddfbe94deb12692 100644 (file)
--- a/t/imapd.t
+++ b/t/imapd.t
@@ -16,6 +16,9 @@ if ($can_compress) { # hope this gets fixed upstream, soon
        $imap_client = 'PublicInbox::IMAPClient';
 }
 
+require_ok 'PublicInbox::IMAP';
+my $first_range = '0';
+
 my $level = '-Lbasic';
 SKIP: {
        require_mods('Search::Xapian', 1);
@@ -87,19 +90,21 @@ 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');
 
-@raw = $mic->list;
+my @orig_list = @raw = $mic->list;
 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: $!");
@@ -320,6 +326,12 @@ Content-Type: message/rfc822\r
 Content-Disposition: attachment; filename="embed2x\.eml"\r
 \r
 EOF
+
+       my @hits = $mic->search('SENTON' => '18-Apr-2020');
+       is_deeply(\@hits, [ $uidnext ], 'search with date condition works');
+       ok($mic->examine($ng), 'EXAMINE on dummy');
+       @hits = $mic->search('SENTSINCE' => '18-Apr-2020');
+       is_deeply(\@hits, [], 'search on dummy with condition works');
 }); # each_inbox
 
 # message sequence numbers :<
@@ -336,8 +348,7 @@ is(scalar keys %$ret, 3, 'got all 3 messages');
        run_script(\@cmd, $env, $rdr) or BAIL_OUT('-learn rm');
 }
 my $r2 = $mic->fetch_hash('1:*', 'BODY.PEEK[]') or BAIL_OUT "FETCH $@";
-is(scalar keys %$r2, 3, 'still got all 3 messages');
-like($r2->{1}->{'BODY[]'}, qr/dummy message #1/, 'got dummy message 1');
+is(scalar keys %$r2, 2, 'did not get all 3 messages');
 is($r2->{2}->{'BODY[]'}, $ret->{2}->{RFC822}, 'message 2 unchanged');
 is($r2->{3}->{'BODY[]'}, $ret->{3}->{RFC822}, 'message 3 unchanged');
 $r2 = $mic->fetch_hash(2, 'BODY.PEEK[HEADER.FIELDS (message-id)]')
@@ -345,15 +356,38 @@ $r2 = $mic->fetch_hash(2, 'BODY.PEEK[HEADER.FIELDS (message-id)]')
 is($r2->{2}->{'BODY[HEADER.FIELDS (MESSAGE-ID)]'},
        'Message-ID: <20200418222508.GA13918@dcvr>'."\r\n\r\n",
        'BODY.PEEK[HEADER.FIELDS ...] drops .PEEK');
+
+{
+       my @new_list = $mic->list;
+       # tag differs in [-1]
+       like($orig_list[-1], qr/\A\S+ OK List done\r\n/, 'orig LIST');
+       like($new_list[-1], qr/\A\S+ OK List done\r\n/, 'new LIST');
+       pop @new_list;
+       pop @orig_list;
+       # TODO: not sure if sort order matters, imapd_refresh_finalize
+       # sorts, for now, but maybe clients don't care...
+       is_deeply(\@new_list, \@orig_list, 'LIST identical');
+}
 ok($mic->close, 'CLOSE works');
 ok(!$mic->close, 'CLOSE not idempotent');
 ok($mic->logout, 'logged out');
 
+{
+       my $c = tcp_connect($sock);
+       $c->autoflush(1);
+       like(<$c>, qr/\* OK/, 'got a greeting');
+       print $c "\r\n";
+       like(<$c>, qr/\A\* BAD Error in IMAP command/, 'empty line');
+       print $c "tagonly\r\n";
+       like(<$c>, qr/\Atagonly BAD Error in IMAP command/, 'tag-only line');
+}
+
 $td->kill;
 $td->join;
 is($?, 0, 'no error in exited process');
 open my $fh, '<', $err or BAIL_OUT("open $err failed: $!");
 my $eout = do { local $/; <$fh> };
 unlike($eout, qr/wide/i, 'no Wide character warnings');
+unlike($eout, qr/uninitialized/i, 'no uninitialized warnings');
 
 done_testing;