]> Sergey Matveev's repositories - public-inbox.git/blob - t/thread-cycle.t
d6545c6df9955104ef930cc1f0ea5fd7dc29b79b
[public-inbox.git] / t / thread-cycle.t
1 # Copyright (C) 2016-2020 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_ok('PublicInbox::SearchThread');
7 use Email::Simple;
8 my $mt = eval {
9         require Mail::Thread;
10         no warnings 'once';
11         $Mail::Thread::nosubject = 1;
12         $Mail::Thread::noprune = 1;
13 };
14
15 sub make_objs {
16         my @simples;
17         my $n = 0;
18         my @msgs = map {
19                 my $msg = $_;
20                 $msg->{ds} ||= ++$n;
21                 $msg->{references} =~ s/\s+/ /sg if $msg->{references};
22                 $msg->{blob} = '0'x40; # any dummy value will do, here
23                 my $simple = Email::Simple->create(header => [
24                         'Message-ID' => "<$msg->{mid}>",
25                         'References' => $msg->{references},
26                 ]);
27                 push @simples, $simple;
28                 bless $msg, 'PublicInbox::Smsg'
29         } @_;
30         (\@simples, \@msgs);
31 }
32
33 my ($simples, $smsgs) = make_objs(
34 # data from t/testbox-6 in Mail::Thread 2.55:
35         { mid => '20021124145312.GA1759@nlin.net' },
36         { mid => 'slrnau448m.7l4.markj+0111@cloaked.freeserve.co.uk',
37           references => '<20021124145312.GA1759@nlin.net>',
38         },
39         { mid => '15842.10677.577458.656565@jupiter.akutech-local.de',
40           references => '<20021124145312.GA1759@nlin.net>
41                         <slrnau448m.7l4.markj+0111@cloaked.freeserve.co.uk>',
42         },
43         { mid => '20021125171807.GK8236@somanetworks.com',
44           references => '<20021124145312.GA1759@nlin.net>
45                         <slrnau448m.7l4.markj+0111@cloaked.freeserve.co.uk>
46                         <15842.10677.577458.656565@jupiter.akutech-local.de>',
47         },
48         { mid => '15843.12163.554914.469248@jupiter.akutech-local.de',
49           references => '<20021124145312.GA1759@nlin.net>
50                         <slrnau448m.7l4.markj+0111@cloaked.freeserve.co.uk>
51                         <15842.10677.577458.656565@jupiter.akutech-local.de>
52                         <E18GPHf-0000zp-00@cloaked.freeserve.co.uk>',
53         },
54         { mid => 'E18GPHf-0000zp-00@cloaked.freeserve.co.uk',
55           references => '<20021124145312.GA1759@nlin.net>
56                         <slrnau448m.7l4.markj+0111@cloaked.freeserve.co.uk>
57                         <15842.10677.577458.656565@jupiter.akutech-local.de>'
58         }
59 );
60
61 my $st = thread_to_s($smsgs);
62
63 SKIP: {
64         skip 'Mail::Thread missing', 1 unless $mt;
65         check_mt($st, $simples, 'Mail::Thread output matches');
66 }
67
68 my @backwards = (
69         { mid => 1, references => '<2> <3> <4>' },
70         { mid => 4, references => '<2> <3>' },
71         { mid => 5, references => '<6> <7> <8> <3> <2>' },
72         { mid => 9, references => '<6> <3>' },
73         { mid => 10, references => '<8> <7> <6>' },
74         { mid => 2, references => '<6> <7> <8> <3>' },
75         { mid => 3, references => '<6> <7> <8>' },
76         { mid => 6, references => '<8> <7>' },
77         { mid => 7, references => '<8>' },
78         { mid => 8, references => '' }
79 );
80
81 ($simples, $smsgs) = make_objs(@backwards);
82 my $backward = thread_to_s($smsgs);
83 SKIP: {
84         skip 'Mail::Thread missing', 1 unless $mt;
85         check_mt($backward, $simples, 'matches Mail::Thread backwards');
86 }
87 ($simples, $smsgs) = make_objs(reverse @backwards);
88 my $forward = thread_to_s($smsgs);
89 unless ('Mail::Thread sorts by Date') {
90         SKIP: {
91                 skip 'Mail::Thread missing', 1 unless $mt;
92                 check_mt($forward, $simples, 'matches Mail::Thread forwards');
93         }
94 }
95 if ('sorting by Date') {
96         is("\n".$backward, "\n".$forward, 'forward and backward matches');
97 }
98
99 done_testing();
100
101 sub thread_to_s {
102         my ($msgs) = @_;
103         my $rootset = PublicInbox::SearchThread::thread($msgs, sub {
104                 [ sort { $a->{mid} cmp $b->{mid} } @{$_[0]} ] });
105         my $st = '';
106         my @q = map { (0, $_) } @$rootset;
107         while (@q) {
108                 my $level = shift @q;
109                 my $node = shift @q or next;
110                 $st .= (" "x$level). "$node->{mid}\n";
111                 my $cl = $level + 1;
112                 unshift @q, map { ($cl, $_) } @{$node->{children}};
113         }
114         $st;
115 }
116
117 sub check_mt {
118         my ($st, $simples, $msg) = @_;
119         my $mt = Mail::Thread->new(@$simples);
120         $mt->thread;
121         $mt->order(sub { sort { $a->messageid cmp $b->messageid } @_ });
122         my $check = '';
123         my @q = map { (0, $_) } $mt->rootset;
124         while (@q) {
125                 my $level = shift @q;
126                 my $node = shift @q or next;
127                 $check .= (" "x$level) . $node->messageid . "\n";
128                 unshift @q, $level + 1, $node->child, $level, $node->next;
129         }
130         is("\n".$check, "\n".$st, $msg);
131 }