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