2 # Copyright (C) 2019-2021 all contributors <meta@public-inbox.org>
3 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
6 use PublicInbox::TestCommon;
7 require_mods(qw(DBD::SQLite Search::Xapian));
10 require PublicInbox::Search;
12 my ($tmpdir, $for_destroy) = tmpdir();
15 my $ibx = create_inbox 'test', version => 2, indexlevel => 'medium',
16 tmpdir => "$tmpdir/testbox", nproc => $nproc, sub {
18 my $eml = PublicInbox::Eml->new(<<'EOF');
21 Subject: this is a subject
22 Date: Fri, 02 Oct 1993 00:00:00 +0000
25 for my $i (1..$ndoc) {
26 $eml->header_set('Message-ID', "<m$i\@example.com>");
27 ok($im->add($eml), "message $i added");
29 open my $fh, '>', "$ibx->{inboxdir}/empty" or BAIL_OUT "open $!";
31 my $env = { PI_CONFIG => "$ibx->{inboxdir}/empty" };
32 my @shards = grep(m!/\d+\z!, glob("$ibx->{inboxdir}/xap*/*"));
33 is(scalar(@shards), $nproc - 1, 'got expected shards');
34 my $orig = $ibx->over->query_xover(1, $ndoc);
35 my %nums = map {; "$_->{num}" => 1 } @$orig;
36 my @xcpdb = qw(-xcpdb -q);
38 my $XapianDatabase = do {
40 $PublicInbox::Search::X{Database};
42 # ensure we can go up or down in shards, or stay the same:
43 for my $R (qw(2 4 1 3 3)) {
44 delete $ibx->{search}; # release old handles
45 my $cmd = [@xcpdb, "-R$R", $ibx->{inboxdir}];
46 push @$cmd, '--compact' if $R == 1 && have_xapian_compact;
47 ok(run_script($cmd, $env), "xcpdb -R$R");
48 my @new_shards = grep(m!/\d+\z!, glob("$ibx->{inboxdir}/xap*/*"));
49 is(scalar(@new_shards), $R, 'resharded to two shards');
50 my $mset = $ibx->search->mset('s:this');
51 my $msgs = $ibx->search->mset_to_smsg($ibx, $mset);
52 is(scalar(@$msgs), $ndoc, 'got expected docs after resharding');
53 my %by_mid = map {; "$_->{mid}" => $_ } @$msgs;
54 ok($by_mid{"m$_\@example.com"}, "$_ exists") for (1..$ndoc);
56 delete $ibx->{search}; # release old handles
58 # ensure docids in Xapian match NNTP article numbers
61 foreach my $d (@new_shards) {
62 my $xdb = $XapianDatabase->new($d);
63 $tot += $xdb->get_doccount;
64 my $it = $xdb->postlist_begin('');
65 my $end = $xdb->postlist_end('');
66 for (; $it != $end; $it++) {
67 my $docid = $it->get_docid;
68 if ($xdb->get_document($docid)) {
69 ok(delete($tmp{$docid}), "saw #$docid");
73 is(scalar keys %tmp, 0, 'all docids seen');