]> Sergey Matveev's repositories - public-inbox.git/blob - t/v2reindex.t
t/v[12]reindex.t: Verify the num highwater is as expected
[public-inbox.git] / t / v2reindex.t
1 # Copyright (C) 2018 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3 use strict;
4 use warnings;
5 use Test::More;
6 use PublicInbox::MIME;
7 use PublicInbox::ContentId qw(content_digest);
8 use File::Temp qw/tempdir/;
9 use File::Path qw(remove_tree);
10
11 foreach my $mod (qw(DBD::SQLite Search::Xapian)) {
12         eval "require $mod";
13         plan skip_all => "$mod missing for v2reindex.t" if $@;
14 }
15 use_ok 'PublicInbox::V2Writable';
16 my $mainrepo = tempdir('pi-v2reindex-XXXXXX', TMPDIR => 1, CLEANUP => 1);
17 my $ibx_config = {
18         mainrepo => $mainrepo,
19         name => 'test-v2writable',
20         version => 2,
21         -primary_address => 'test@example.com',
22         indexlevel => 'full',
23 };
24 my $mime = PublicInbox::MIME->create(
25         header => [
26                 From => 'a@example.com',
27                 To => 'test@example.com',
28                 Subject => 'this is a subject',
29                 Date => 'Fri, 02 Oct 1993 00:00:00 +0000',
30         ],
31         body => "hello world\n",
32 );
33 local $ENV{NPROC} = 2;
34 my $minmax;
35 my $msgmap;
36 my ($mark1, $mark2, $mark3, $mark4);
37 {
38         my %config = %$ibx_config;
39         my $ibx = PublicInbox::Inbox->new(\%config);
40         my $im = PublicInbox::V2Writable->new($ibx, 1);
41         my $im0 = $im->importer();
42         foreach my $i (1..10) {
43                 $mime->header_set('Message-Id', "<$i\@example.com>");
44                 ok($im->add($mime), "message $i added");
45                 if ($i == 4) {
46                         $mark1 = $im0->get_mark($im0->{tip});
47                         $im->remove($mime);
48                         $mark2 = $im0->get_mark($im0->{tip});
49                 }
50         }
51
52         if ('test remove later') {
53                 $mark3 = $im0->get_mark($im0->{tip});
54                 $mime->header_set('Message-Id', "<5\@example.com>");
55                 $im->remove($mime);
56                 $mark4 = $im0->get_mark($im0->{tip});
57         }
58
59         $im->done;
60         $minmax = [ $ibx->mm->minmax ];
61         ok(defined $minmax->[0] && defined $minmax->[1], 'minmax defined');
62         is_deeply($minmax, [ 1, 10 ], 'minmax as expected');
63         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
64
65         my ($min, $max) = @$minmax;
66         $msgmap = $ibx->mm->msg_range(\$min, $max);
67         is_deeply($msgmap, [
68                           [1, '1@example.com' ],
69                           [2, '2@example.com' ],
70                           [3, '3@example.com' ],
71                           [6, '6@example.com' ],
72                           [7, '7@example.com' ],
73                           [8, '8@example.com' ],
74                           [9, '9@example.com' ],
75                           [10, '10@example.com' ],
76                   ], 'msgmap as expected');
77 }
78
79 {
80         my %config = %$ibx_config;
81         my $ibx = PublicInbox::Inbox->new(\%config);
82         my $im = PublicInbox::V2Writable->new($ibx, 1);
83         eval { $im->index_sync({reindex => 1}) };
84         is($@, '', 'no error from reindexing');
85         $im->done;
86
87         delete $ibx->{mm};
88         is_deeply([ $ibx->mm->minmax ], $minmax, 'minmax unchanged');
89         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
90
91         my ($min, $max) = $ibx->mm->minmax;
92         is_deeply($ibx->mm->msg_range(\$min, $max), $msgmap, 'msgmap unchanged');
93 }
94
95 my $xap = "$mainrepo/xap".PublicInbox::Search::SCHEMA_VERSION();
96 remove_tree($xap);
97 ok(!-d $xap, 'Xapian directories removed');
98 {
99         my %config = %$ibx_config;
100         my $ibx = PublicInbox::Inbox->new(\%config);
101         my $im = PublicInbox::V2Writable->new($ibx, 1);
102         eval { $im->index_sync({reindex => 1}) };
103         is($@, '', 'no error from reindexing');
104         $im->done;
105         ok(-d $xap, 'Xapian directories recreated');
106
107         delete $ibx->{mm};
108         is_deeply([ $ibx->mm->minmax ], $minmax, 'minmax unchanged');
109         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
110
111         my ($min, $max) = $ibx->mm->minmax;
112         is_deeply($ibx->mm->msg_range(\$min, $max), $msgmap, 'msgmap unchanged');
113 }
114
115 ok(unlink "$mainrepo/msgmap.sqlite3", 'remove msgmap');
116 remove_tree($xap);
117 ok(!-d $xap, 'Xapian directories removed again');
118 {
119         my @warn;
120         local $SIG{__WARN__} = sub { push @warn, @_ };
121         my %config = %$ibx_config;
122         my $ibx = PublicInbox::Inbox->new(\%config);
123         my $im = PublicInbox::V2Writable->new($ibx, 1);
124         eval { $im->index_sync({reindex => 1}) };
125         is($@, '', 'no error from reindexing without msgmap');
126         is(scalar(@warn), 0, 'no warnings from reindexing');
127         $im->done;
128         ok(-d $xap, 'Xapian directories recreated');
129         delete $ibx->{mm};
130         is_deeply([ $ibx->mm->minmax ], $minmax, 'minmax unchanged');
131         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
132
133         my ($min, $max) = $ibx->mm->minmax;
134         is_deeply($ibx->mm->msg_range(\$min, $max), $msgmap, 'msgmap unchanged');
135 }
136
137 my %sizes;
138 ok(unlink "$mainrepo/msgmap.sqlite3", 'remove msgmap');
139 remove_tree($xap);
140 ok(!-d $xap, 'Xapian directories removed again');
141 {
142         my @warn;
143         local $SIG{__WARN__} = sub { push @warn, @_ };
144         my %config = %$ibx_config;
145         my $ibx = PublicInbox::Inbox->new(\%config);
146         my $im = PublicInbox::V2Writable->new($ibx, 1);
147         eval { $im->index_sync({reindex => 1}) };
148         is($@, '', 'no error from reindexing without msgmap');
149         is_deeply(\@warn, [], 'no warnings');
150         $im->done;
151         ok(-d $xap, 'Xapian directories recreated');
152         delete $ibx->{mm};
153         is_deeply([ $ibx->mm->minmax ], $minmax, 'minmax unchanged');
154         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
155         my $mset = $ibx->search->query('"hello world"', {mset=>1});
156         isnt($mset->size, 0, "phrase search succeeds on indexlevel=full");
157         for (<"$xap/*/*">) { $sizes{$ibx->{indexlevel}} += -s _ if -f $_ }
158
159         my ($min, $max) = $ibx->mm->minmax;
160         is_deeply($ibx->mm->msg_range(\$min, $max), $msgmap, 'msgmap unchanged');
161 }
162
163 ok(unlink "$mainrepo/msgmap.sqlite3", 'remove msgmap');
164 remove_tree($xap);
165 ok(!-d $xap, 'Xapian directories removed again');
166 {
167         my @warn;
168         local $SIG{__WARN__} = sub { push @warn, @_ };
169         my %config = %$ibx_config;
170         $config{indexlevel} = 'medium';
171         my $ibx = PublicInbox::Inbox->new(\%config);
172         my $im = PublicInbox::V2Writable->new($ibx);
173         eval { $im->index_sync({reindex => 1}) };
174         is($@, '', 'no error from reindexing without msgmap');
175         is_deeply(\@warn, [], 'no warnings');
176         $im->done;
177         ok(-d $xap, 'Xapian directories recreated');
178         delete $ibx->{mm};
179         is_deeply([ $ibx->mm->minmax ], $minmax, 'minmax unchanged');
180         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
181
182         if (0) {
183                 # not sure why, but Xapian seems to fallback to terms and
184                 # phrase searches still work
185                 delete $ibx->{search};
186                 my $mset = $ibx->search->query('"hello world"', {mset=>1});
187                 is($mset->size, 0, 'phrase search does not work on medium');
188         }
189
190         my $mset = $ibx->search->query('hello world', {mset=>1});
191         isnt($mset->size, 0, "normal search works on indexlevel=medium");
192         for (<"$xap/*/*">) { $sizes{$ibx->{indexlevel}} += -s _ if -f $_ }
193         ok($sizes{full} > $sizes{medium}, 'medium is smaller than full');
194
195
196         my ($min, $max) = $ibx->mm->minmax;
197         is_deeply($ibx->mm->msg_range(\$min, $max), $msgmap, 'msgmap unchanged');
198 }
199
200 ok(unlink "$mainrepo/msgmap.sqlite3", 'remove msgmap');
201 remove_tree($xap);
202 ok(!-d $xap, 'Xapian directories removed again');
203 {
204         my @warn;
205         local $SIG{__WARN__} = sub { push @warn, @_ };
206         my %config = %$ibx_config;
207         $config{indexlevel} = 'basic';
208         my $ibx = PublicInbox::Inbox->new(\%config);
209         my $im = PublicInbox::V2Writable->new($ibx);
210         eval { $im->index_sync({reindex => 1}) };
211         is($@, '', 'no error from reindexing without msgmap');
212         is_deeply(\@warn, [], 'no warnings');
213         $im->done;
214         ok(-d $xap, 'Xapian directories recreated');
215         delete $ibx->{mm};
216         is_deeply([ $ibx->mm->minmax ], $minmax, 'minmax unchanged');
217         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
218         my $mset = $ibx->search->query('hello', {mset=>1});
219         is($mset->size, 0, "search fails on indexlevel='basic'");
220         for (<"$xap/*/*">) { $sizes{$ibx->{indexlevel}} += -s _ if -f $_ }
221         ok($sizes{medium} > $sizes{basic}, 'basic is smaller than medium');
222
223         my ($min, $max) = $ibx->mm->minmax;
224         is_deeply($ibx->mm->msg_range(\$min, $max), $msgmap, 'msgmap unchanged');
225 }
226
227
228 # An incremental indexing test
229 ok(unlink "$mainrepo/msgmap.sqlite3", 'remove msgmap');
230 remove_tree($xap);
231 ok(!-d $xap, 'Xapian directories removed again');
232 {
233         my @warn;
234         local $SIG{__WARN__} = sub { push @warn, @_ };
235         my %config = %$ibx_config;
236         my $ibx = PublicInbox::Inbox->new(\%config);
237         # mark1 4 simple additions in the same index_sync
238         $ibx->{ref_head} = $mark1;
239         my $im = PublicInbox::V2Writable->new($ibx);
240         eval { $im->index_sync() };
241         is($@, '', 'no error from reindexing without msgmap');
242         is_deeply(\@warn, [], 'no warnings');
243         $im->done;
244         my ($min, $max) = $ibx->mm->minmax;
245         is($min, 1, 'min as expected');
246         is($max, 4, 'max as expected');
247         is($ibx->mm->num_highwater, 4, 'num_highwater as expected');
248         is_deeply($ibx->mm->msg_range(\$min, $max),
249                   [
250                    [1, '1@example.com' ],
251                    [2, '2@example.com' ],
252                    [3, '3@example.com' ],
253                    [4, '4@example.com' ],
254                   ], 'msgmap as expected' );
255 }
256 {
257         my @warn;
258         local $SIG{__WARN__} = sub { push @warn, @_ };
259         my %config = %$ibx_config;
260         my $ibx = PublicInbox::Inbox->new(\%config);
261         # mark2 A delete separated from an add in the same index_sync
262         $ibx->{ref_head} = $mark2;
263         my $im = PublicInbox::V2Writable->new($ibx);
264         eval { $im->index_sync() };
265         is($@, '', 'no error from reindexing without msgmap');
266         is_deeply(\@warn, [], 'no warnings');
267         $im->done;
268         my ($min, $max) = $ibx->mm->minmax;
269         is($min, 1, 'min as expected');
270         is($max, 3, 'max as expected');
271         is($ibx->mm->num_highwater, 4, 'num_highwater as expected');
272         is_deeply($ibx->mm->msg_range(\$min, $max),
273                   [
274                    [1, '1@example.com' ],
275                    [2, '2@example.com' ],
276                    [3, '3@example.com' ],
277                   ], 'msgmap as expected' );
278 }
279 {
280         my @warn;
281         local $SIG{__WARN__} = sub { push @warn, @_ };
282         my %config = %$ibx_config;
283         my $ibx = PublicInbox::Inbox->new(\%config);
284         # mark3 adds following the delete at mark2
285         $ibx->{ref_head} = $mark3;
286         my $im = PublicInbox::V2Writable->new($ibx);
287         eval { $im->index_sync() };
288         is($@, '', 'no error from reindexing without msgmap');
289         is_deeply(\@warn, [], 'no warnings');
290         $im->done;
291         my ($min, $max) = $ibx->mm->minmax;
292         is($min, 1, 'min as expected');
293         is($max, 10, 'max as expected');
294         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
295         is_deeply($ibx->mm->msg_range(\$min, $max),
296                   [
297                    [1, '1@example.com' ],
298                    [2, '2@example.com' ],
299                    [3, '3@example.com' ],
300                    [5, '5@example.com' ],
301                    [6, '6@example.com' ],
302                    [7, '7@example.com' ],
303                    [8, '8@example.com' ],
304                    [9, '9@example.com' ],
305                    [10, '10@example.com' ],
306                   ], 'msgmap as expected' );
307 }
308 {
309         my @warn;
310         local $SIG{__WARN__} = sub { push @warn, @_ };
311         my %config = %$ibx_config;
312         my $ibx = PublicInbox::Inbox->new(\%config);
313         # mark4 A delete of an older message
314         $ibx->{ref_head} = $mark4;
315         my $im = PublicInbox::V2Writable->new($ibx);
316         eval { $im->index_sync() };
317         is($@, '', 'no error from reindexing without msgmap');
318         is_deeply(\@warn, [], 'no warnings');
319         $im->done;
320         my ($min, $max) = $ibx->mm->minmax;
321         is($min, 1, 'min as expected');
322         is($max, 10, 'max as expected');
323         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
324         is_deeply($ibx->mm->msg_range(\$min, $max),
325                   [
326                    [1, '1@example.com' ],
327                    [2, '2@example.com' ],
328                    [3, '3@example.com' ],
329                    [6, '6@example.com' ],
330                    [7, '7@example.com' ],
331                    [8, '8@example.com' ],
332                    [9, '9@example.com' ],
333                    [10, '10@example.com' ],
334                   ], 'msgmap as expected' );
335 }
336
337
338 # Another incremental indexing test
339 ok(unlink "$mainrepo/msgmap.sqlite3", 'remove msgmap');
340 remove_tree($xap);
341 ok(!-d $xap, 'Xapian directories removed again');
342 {
343         my @warn;
344         local $SIG{__WARN__} = sub { push @warn, @_ };
345         my %config = %$ibx_config;
346         my $ibx = PublicInbox::Inbox->new(\%config);
347         # mark2 an add and it's delete in the same index_sync
348         $ibx->{ref_head} = $mark2;
349         my $im = PublicInbox::V2Writable->new($ibx);
350         eval { $im->index_sync() };
351         is($@, '', 'no error from reindexing without msgmap');
352         is_deeply(\@warn, [], 'no warnings');
353         $im->done;
354         my ($min, $max) = $ibx->mm->minmax;
355         is($min, 1, 'min as expected');
356         is($max, 3, 'max as expected');
357         is($ibx->mm->num_highwater, 4, 'num_highwater as expected');
358         is_deeply($ibx->mm->msg_range(\$min, $max),
359                   [
360                    [1, '1@example.com' ],
361                    [2, '2@example.com' ],
362                    [3, '3@example.com' ],
363                   ], 'msgmap as expected' );
364 }
365 {
366         my @warn;
367         local $SIG{__WARN__} = sub { push @warn, @_ };
368         my %config = %$ibx_config;
369         my $ibx = PublicInbox::Inbox->new(\%config);
370         # mark3 adds following the delete at mark2
371         $ibx->{ref_head} = $mark3;
372         my $im = PublicInbox::V2Writable->new($ibx);
373         eval { $im->index_sync() };
374         is($@, '', 'no error from reindexing without msgmap');
375         is_deeply(\@warn, [], 'no warnings');
376         $im->done;
377         my ($min, $max) = $ibx->mm->minmax;
378         is($min, 1, 'min as expected');
379         is($max, 10, 'max as expected');
380         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
381         is_deeply($ibx->mm->msg_range(\$min, $max),
382                   [
383                    [1, '1@example.com' ],
384                    [2, '2@example.com' ],
385                    [3, '3@example.com' ],
386                    [5, '5@example.com' ],
387                    [6, '6@example.com' ],
388                    [7, '7@example.com' ],
389                    [8, '8@example.com' ],
390                    [9, '9@example.com' ],
391                    [10, '10@example.com' ],
392                   ], 'msgmap as expected' );
393 }
394 {
395         my @warn;
396         local $SIG{__WARN__} = sub { push @warn, @_ };
397         my %config = %$ibx_config;
398         my $ibx = PublicInbox::Inbox->new(\%config);
399         # mark4 A delete of an older message
400         $ibx->{ref_head} = $mark4;
401         my $im = PublicInbox::V2Writable->new($ibx);
402         eval { $im->index_sync() };
403         is($@, '', 'no error from reindexing without msgmap');
404         is_deeply(\@warn, [], 'no warnings');
405         $im->done;
406         my ($min, $max) = $ibx->mm->minmax;
407         is($min, 1, 'min as expected');
408         is($max, 10, 'max as expected');
409         is($ibx->mm->num_highwater, 10, 'num_highwater as expected');
410         is_deeply($ibx->mm->msg_range(\$min, $max),
411                   [
412                    [1, '1@example.com' ],
413                    [2, '2@example.com' ],
414                    [3, '3@example.com' ],
415                    [6, '6@example.com' ],
416                    [7, '7@example.com' ],
417                    [8, '8@example.com' ],
418                    [9, '9@example.com' ],
419                    [10, '10@example.com' ],
420                   ], 'msgmap as expected' );
421 }
422
423 done_testing();