]> Sergey Matveev's repositories - public-inbox.git/blob - t/mbox_reader.t
mbox_reader: do not chomp non-blank EOL
[public-inbox.git] / t / mbox_reader.t
1 #!perl -w
2 # Copyright (C) 2020-2021 all contributors <meta@public-inbox.org>
3 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
4 use strict;
5 use v5.10.1;
6 use Test::More;
7 use PublicInbox::TestCommon;
8 use List::Util qw(shuffle);
9 use PublicInbox::Eml;
10 use Fcntl qw(SEEK_SET);
11 require_ok 'PublicInbox::MboxReader';
12 require_ok 'PublicInbox::LeiToMail';
13 my %raw = (
14         hdr_only => "From: header-only\@example.com\n\n",
15         small_from => "From: small-from\@example.com\n\nFrom hell\n",
16         small => "From: small\@example.com\n\nfrom hell\n",
17         big_hdr_only => "From: big-header\@example.com\n" .
18                 (('A: '.('a' x 72)."\n") x 1000)."\n",
19         big_body => "From: big-body\@example.com\n\n".
20                 (('b: '.('b' x 72)."\n") x 1000) .
21                 "From hell\n",
22         big_all => "From: big-all\@example.com\n".
23                 (("A: ".('a' x 72)."\n") x 1000). "\n" .
24                 (("b: ".('b' x 72)."\n") x 1000) .
25                 "From hell\n",
26 );
27
28 if ($ENV{TEST_EXTRA}) {
29         for my $fn (glob('t/*.eml'), glob('t/*/*.{patch,eml}')) {
30                 $raw{$fn} = eml_load($fn)->as_string;
31         }
32 }
33
34 my $reader = PublicInbox::MboxReader->new;
35 my $check_fmt = sub {
36         my $fmt = shift;
37         my @order = shuffle(keys %raw);
38         my $eml2mbox = PublicInbox::LeiToMail->can("eml2$fmt");
39         open my $fh, '+>', undef or BAIL_OUT "open: $!";
40         for my $k (@order) {
41                 my $eml = PublicInbox::Eml->new($raw{$k});
42                 my $buf = $eml2mbox->($eml);
43                 print $fh $$buf or BAIL_OUT "print $!";
44         }
45         seek($fh, 0, SEEK_SET) or BAIL_OUT "seek: $!";
46         $reader->$fmt($fh, sub {
47                 my ($eml) = @_;
48                 $eml->header_set('Status');
49                 $eml->header_set('Lines');
50                 my $cur = shift @order;
51                 my @cl = $eml->header_raw('Content-Length');
52                 if ($fmt =~ /\Amboxcl/) {
53                         is(scalar(@cl), 1, "Content-Length set $fmt $cur");
54                         my $raw = $eml->body_raw;
55                         my $adj = 0;
56                         if ($fmt eq 'mboxcl') {
57                                 my @from = ($raw =~ /^(From )/smg);
58                                 $adj = scalar(@from);
59                         }
60                         is(length($raw), $cl[0] - $adj,
61                                 "Content-Length is correct $fmt $cur");
62                         # clobber for ->as_string comparison below
63                         $eml->header_set('Content-Length');
64                 } else {
65                         is(scalar(@cl), 0, "Content-Length unset $fmt $cur");
66                 }
67                 my $orig = PublicInbox::Eml->new($raw{$cur});
68                 is($eml->as_string, $orig->as_string,
69                         "read back original $fmt $cur");
70         });
71 };
72 my @mbox = qw(mboxrd mboxo mboxcl mboxcl2);
73 for my $fmt (@mbox) { $check_fmt->($fmt) }
74 s/\n/\r\n/sg for (values %raw);
75 for my $fmt (@mbox) { $check_fmt->($fmt) }
76
77 {
78         my $no_blank_eom = <<'EOM';
79 From x@y Fri Oct  2 00:00:00 1993
80 a: b
81
82 body1
83 From x@y Fri Oct  2 00:00:00 1993
84 c: d
85
86 body2
87 EOM
88         # chop($no_blank_eom) eq "\n" or BAIL_OUT 'broken LF';
89         for my $variant (qw(mboxrd mboxo)) {
90                 my @x;
91                 open my $fh, '<', \$no_blank_eom or BAIL_OUT 'PerlIO::scalar';
92                 $reader->$variant($fh, sub { push @x, shift });
93                 is_deeply($x[0]->{bdy}, \"body1\n", 'LF preserved in 1st');
94                 is_deeply($x[1]->{bdy}, \"body2\n", 'no LF added in 2nd');
95         }
96 }
97
98 SKIP: {
99         use PublicInbox::Spawn qw(popen_rd);
100         my $fh = popen_rd([ $^X, '-E', <<'' ]);
101 say "From x@y Fri Oct  2 00:00:00 1993";
102 print "a: b\n\n", "x" x 70000, "\n\n";
103 say "From x@y Fri Oct  2 00:00:00 2010";
104 print "Final: bit\n\n", "Incomplete\n\n";
105 exit 1
106
107         my @x;
108         eval { $reader->mboxrd($fh, sub { push @x, shift->as_string }) };
109         like($@, qr/error closing mbox/, 'detects error reading from pipe');
110         is(scalar(@x), 1, 'only saw one message');
111         is(scalar(grep(/Final/, @x)), 0, 'no incomplete bit');
112 }
113
114 done_testing;