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