+ $rw_commit->();
+ my $msg = $ro->reopen->
+ query('m:testmessage@example.com', {limit => 1})->[0];
+ is(defined($msg), 1, 'found testmessage@example.com');
+ if (defined $msg) {
+ is($mime->header('Subject'), $msg->{subject},
+ 'UTF-8 subject preserved');
+ }
+});
+
+# names and addresses
+{
+ my $mset = $ro->query('t:list@example.com', {mset => 1});
+ is($mset->size, 9, 'searched To: successfully');
+ foreach my $m ($mset->items) {
+ my $smsg = $ro->{over_ro}->get_art($m->get_docid);
+ like($smsg->{to}, qr/\blist\@example\.com\b/, 'to appears');
+ my $doc = $m->get_document;
+ my $col = PublicInbox::Search::BYTES();
+ my $bytes = PublicInbox::Smsg::get_val($doc, $col);
+ like($bytes, qr/\A[0-9]+\z/, '$bytes stored as digit');
+ ok($bytes > 0, '$bytes is > 0');
+ is($bytes, $smsg->{bytes}, 'bytes Xapian value matches Over');
+
+ $col = PublicInbox::Search::UID();
+ my $uid = PublicInbox::Smsg::get_val($doc, $col);
+ is($uid, $smsg->{num}, 'UID column matches {num}');
+ is($uid, $m->get_docid, 'UID column matches docid');
+ }
+
+ $mset = $ro->query('tc:list@example.com', {mset => 1});
+ is($mset->size, 9, 'searched To+Cc: successfully');
+ foreach my $m ($mset->items) {
+ my $smsg = $ro->{over_ro}->get_art($m->get_docid);
+ my $tocc = join("\n", $smsg->{to}, $smsg->{cc});
+ like($tocc, qr/\blist\@example\.com\b/, 'tocc appears');
+ }
+
+ foreach my $pfx ('tcf:', 'c:') {
+ my $mset = $ro->query($pfx . 'foo@example.com', { mset => 1 });
+ is($mset->items, 1, "searched $pfx successfully for Cc:");
+ foreach my $m ($mset->items) {
+ my $smsg = $ro->{over_ro}->get_art($m->get_docid);
+ like($smsg->{cc}, qr/\bfoo\@example\.com\b/,
+ 'cc appears');
+ }
+ }
+
+ foreach my $pfx ('', 'tcf:', 'f:') {
+ my $res = $ro->query($pfx . 'Laggy');
+ is(scalar(@$res), 1,
+ "searched $pfx successfully for From:");
+ foreach my $smsg (@$res) {
+ like($smsg->{from_name}, qr/Laggy Sender/,
+ "From appears with $pfx");
+ }
+ }
+}
+
+{
+ $rw_commit->();
+ $ro->reopen;
+ my $res = $ro->query('b:hello');
+ is(scalar(@$res), 0, 'no match on body search only');
+ $res = $ro->query('bs:smith');
+ is(scalar(@$res), 0,
+ 'no match on body+subject search for From');
+
+ $res = $ro->query('q:theatre');
+ is(scalar(@$res), 1, 'only one quoted body');
+ like($res->[0]->{from_name}, qr/\AQuoter/,
+ 'got quoted body') if (scalar(@$res));
+
+ $res = $ro->query('nq:theatre');
+ is(scalar @$res, 1, 'only one non-quoted body');
+ like($res->[0]->{from_name}, qr/\ANon-Quoter/,
+ 'got non-quoted body') if (scalar(@$res));
+
+ foreach my $pfx (qw(b: bs:)) {
+ $res = $ro->query($pfx . 'theatre');
+ is(scalar @$res, 2, "searched both bodies for $pfx");
+ like($res->[0]->{from_name}, qr/\ANon-Quoter/,
+ "non-quoter first for $pfx") if scalar(@$res);
+ }
+}
+
+$ibx->with_umask(sub {
+ my $amsg = eml_load 't/search-amsg.eml';
+ my $oid = ('0'x40);
+ my $smsg = bless { blob => $oid }, 'PublicInbox::Smsg';
+ ok($rw->add_message($amsg, $smsg), 'added attachment');
+ $rw_commit->();
+ $ro->reopen;
+ my $n = $ro->query('n:attached_fart.txt');
+ is(scalar @$n, 1, 'got result for n:');
+ my $res = $ro->query('part_deux.txt');
+ is(scalar @$res, 1, 'got result without n:');
+ is($n->[0]->{mid}, $res->[0]->{mid},
+ 'same result with and without') if scalar(@$res);
+ my $txt = $ro->query('"inside another"');
+ is(scalar @$txt, 1, 'found inside another');
+ is($txt->[0]->{mid}, $res->[0]->{mid},
+ 'search inside text attachments works') if scalar(@$txt);
+
+ my $art;
+ if (scalar(@$n) >= 1) {
+ my $mid = $n->[0]->{mid};
+ my ($id, $prev);
+ $art = $ro->{over_ro}->next_by_mid($mid, \$id, \$prev);
+ ok($art, 'article exists in OVER DB');
+ }
+ $rw->_msgmap_init;
+ $rw->unindex_eml($oid, $amsg);
+ $rw->commit_txn_lazy;
+ SKIP: {
+ skip('$art not defined', 1) unless defined $art;
+ is($ro->{over_ro}->get_art($art->{num}), undef,
+ 'gone from OVER DB');
+ };
+});