blib/lib/Mail/Box/Test.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 117 | 149 | 78.5 |
branch | 31 | 62 | 50.0 |
condition | 0 | 3 | 0.0 |
subroutine | 19 | 22 | 86.3 |
pod | 0 | 9 | 0.0 |
total | 167 | 245 | 68.1 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | # Copyrights 2001-2023 by [Mark Overmeer]. | ||||||
2 | # For other contributors see ChangeLog. | ||||||
3 | # See the manual pages for details on the licensing terms. | ||||||
4 | # Pod stripped from pm file by OODoc 2.03. | ||||||
5 | # This code is part of distribution Mail-Box. Meta-POD processed with | ||||||
6 | # OODoc into POD and HTML manual-pages. See README.md | ||||||
7 | # Copyright Mark Overmeer. Licensed under the same terms as Perl itself. | ||||||
8 | |||||||
9 | package Mail::Box::Test; | ||||||
10 | 42 | 42 | 24930 | use vars '$VERSION'; | |||
42 | 333 | ||||||
42 | 3312 | ||||||
11 | $VERSION = '3.010'; | ||||||
12 | |||||||
13 | 42 | 42 | 295 | use base 'Exporter'; | |||
42 | 79 | ||||||
42 | 5875 | ||||||
14 | |||||||
15 | 42 | 42 | 324 | use strict; | |||
42 | 93 | ||||||
42 | 1159 | ||||||
16 | 42 | 42 | 237 | use warnings; | |||
42 | 152 | ||||||
42 | 1544 | ||||||
17 | |||||||
18 | 42 | 42 | 22037 | use File::Copy 'copy'; | |||
42 | 203660 | ||||||
42 | 3780 | ||||||
19 | 42 | 42 | 324 | use List::Util 'first'; | |||
42 | 106 | ||||||
42 | 5613 | ||||||
20 | 42 | 42 | 20112 | use IO::File; # to overrule open() | |||
42 | 407073 | ||||||
42 | 6227 | ||||||
21 | 42 | 42 | 2029 | use File::Spec; | |||
42 | 1605 | ||||||
42 | 7433 | ||||||
22 | 42 | 42 | 33359 | use File::Temp 'tempdir'; | |||
42 | 491898 | ||||||
42 | 2747 | ||||||
23 | 42 | 42 | 323 | use Cwd qw(getcwd); | |||
42 | 81 | ||||||
42 | 1898 | ||||||
24 | 42 | 42 | 19019 | use Sys::Hostname qw(hostname); | |||
42 | 43145 | ||||||
42 | 2402 | ||||||
25 | 42 | 42 | 27079 | use Test::More; | |||
42 | 2708261 | ||||||
42 | 389 | ||||||
26 | |||||||
27 | |||||||
28 | our @EXPORT = | ||||||
29 | qw/clean_dir copy_dir | ||||||
30 | unpack_mbox2mh unpack_mbox2maildir | ||||||
31 | compare_lists listdir | ||||||
32 | compare_message_prints reproducable_text | ||||||
33 | compare_thread_dumps | ||||||
34 | |||||||
35 | $folderdir | ||||||
36 | $workdir | ||||||
37 | $src $unixsrc $winsrc | ||||||
38 | $fn $unixfn $winfn | ||||||
39 | $cpy $cpyfn | ||||||
40 | $raw_html_data | ||||||
41 | $crlf_platform $windows | ||||||
42 | /; | ||||||
43 | |||||||
44 | our ($logfile, $folderdir); | ||||||
45 | our ($src, $unixsrc, $winsrc); | ||||||
46 | our ($fn, $unixfn, $winfn); | ||||||
47 | our ($cpy, $cpyfn); | ||||||
48 | our ($crlf_platform, $windows); | ||||||
49 | our $workdir; | ||||||
50 | |||||||
51 | BEGIN { | ||||||
52 | 42 | 42 | 25026 | $windows = $^O =~ m/mswin32/i; | |||
53 | 42 | 163 | $crlf_platform = $windows; | ||||
54 | |||||||
55 | 42 | 711 | $folderdir = File::Spec->catdir('t','folders'); | ||||
56 | 42 | 326 | $workdir = tempdir(CLEANUP => 1); | ||||
57 | |||||||
58 | |||||||
59 | 42 | 35311 | $logfile = File::Spec->catfile(getcwd(), 'run-log'); | ||||
60 | 42 | 228 | $unixfn = 'mbox.src'; | ||||
61 | 42 | 120 | $winfn = 'mbox.win'; | ||||
62 | 42 | 125 | $cpyfn = 'mbox.cpy'; | ||||
63 | |||||||
64 | 42 | 286 | $unixsrc = File::Spec->catfile($folderdir, $unixfn); | ||||
65 | 42 | 342 | $winsrc = File::Spec->catfile($folderdir, $winfn); | ||||
66 | 42 | 423 | $cpy = File::Spec->catfile($workdir, $cpyfn); | ||||
67 | |||||||
68 | 42 | 50 | 322 | ($src, $fn) = $windows ? ($winsrc, $winfn) : ($unixsrc, $unixfn); | |||
69 | |||||||
70 | # ensure to test the Perl Parser not the C-Parser (separate distribution) | ||||||
71 | 42 | 23094 | require Mail::Box::Parser::Perl; | ||||
72 | 42 | 912889 | Mail::Box::Parser->defaultParserType( 'Mail::Box::Parser::Perl' ); | ||||
73 | } | ||||||
74 | |||||||
75 | # | ||||||
76 | # CLEAN_DIR | ||||||
77 | # Clean a directory structure, typically created by unpack_mbox() | ||||||
78 | # | ||||||
79 | |||||||
80 | sub clean_dir($); | ||||||
81 | sub clean_dir($) | ||||||
82 | 11 | 11 | 0 | 166 | { my $dir = shift; | ||
83 | 11 | 50 | local *DIR; | ||||
84 | 11 | 50 | 618 | opendir DIR, $dir or return; | |||
85 | |||||||
86 | 0 | 0 | 0 | my @items = map { m/(.*)/ && "$dir/$1" } # untainted | |||
0 | 0 | ||||||
87 | grep !/^\.\.?$/, readdir DIR; | ||||||
88 | 0 | 0 | foreach (@items) | ||||
89 | 0 | 0 | 0 | { if(-d) { clean_dir $_ } | |||
0 | 0 | ||||||
90 | 0 | 0 | else { unlink $_ } | ||||
91 | } | ||||||
92 | |||||||
93 | 0 | 0 | closedir DIR; | ||||
94 | 0 | 0 | rmdir $dir; | ||||
95 | } | ||||||
96 | |||||||
97 | # | ||||||
98 | # COPY_DIR FROM, TO | ||||||
99 | # Copy directory to other place (not recursively), cleaning the | ||||||
100 | # destination first. | ||||||
101 | # | ||||||
102 | |||||||
103 | sub copy_dir($$) | ||||||
104 | 0 | 0 | 0 | 0 | { my ($orig, $dest) = @_; | ||
105 | |||||||
106 | 0 | 0 | clean_dir($dest); | ||||
107 | |||||||
108 | 0 | 0 | 0 | mkdir $dest | |||
109 | or die "Cannot create copy destination $dest: $!\n"; | ||||||
110 | |||||||
111 | 0 | 0 | 0 | opendir ORIG, $orig | |||
112 | or die "Cannot open directory $orig: $!\n"; | ||||||
113 | |||||||
114 | 0 | 0 | 0 | 0 | foreach my $name (map { !m/^\.\.?$/ && m/(.*)/ ? $1 : () } readdir ORIG) | ||
0 | 0 | ||||||
115 | 0 | 0 | { my $from = File::Spec->catfile($orig, $name); | ||||
116 | 0 | 0 | 0 | next if -d $from; | |||
117 | |||||||
118 | 0 | 0 | my $to = File::Spec->catfile($dest, $name); | ||||
119 | 0 | 0 | 0 | copy($from, $to) or die "Couldn't copy $from,$to: $!\n"; | |||
120 | } | ||||||
121 | |||||||
122 | 0 | 0 | close ORIG; | ||||
123 | } | ||||||
124 | |||||||
125 | # UNPACK_MBOX2MH | ||||||
126 | # Unpack an mbox-file into an MH-directory. | ||||||
127 | # This skips message-nr 13 for testing purposes. | ||||||
128 | # Blanks before "From" are removed. | ||||||
129 | |||||||
130 | sub unpack_mbox2mh($$) | ||||||
131 | 6 | 6 | 0 | 579 | { my ($file, $dir) = @_; | ||
132 | 6 | 29 | clean_dir($dir); | ||||
133 | |||||||
134 | 6 | 578 | mkdir $dir, 0700; | ||||
135 | 6 | 34 | my $count = 1; | ||||
136 | 6 | 18 | my $blank; | ||||
137 | |||||||
138 | 6 | 50 | 278 | open FILE, $file or die; | |||
139 | 6 | 386 | open OUT, '>', File::Spec->devnull; | ||||
140 | |||||||
141 | 6 | 250 | while( |
||||
142 | 20088 | 100 | 33013 | { if( /^From / ) | |||
143 | 270 | 9005 | { close OUT; | ||||
144 | 270 | 894 | undef $blank; | ||||
145 | 270 | 50 | 17533 | open OUT, ">$dir/".$count++ or die; | |||
146 | 270 | 100 | 1210 | $count++ if $count==13; # skip 13 for test | |||
147 | 270 | 1444 | next; # from line not included in file. | ||||
148 | } | ||||||
149 | |||||||
150 | 19818 | 100 | 30090 | print OUT $blank | |||
151 | if defined $blank; | ||||||
152 | |||||||
153 | 19818 | 100 | 34067 | if( m/^\015?\012$/ ) | |||
154 | 2400 | 3489 | { $blank = $_; | ||||
155 | 2400 | 5987 | next; | ||||
156 | } | ||||||
157 | |||||||
158 | 17418 | 19889 | undef $blank; | ||||
159 | 17418 | 34407 | print OUT; | ||||
160 | } | ||||||
161 | |||||||
162 | 6 | 217 | close OUT; | ||||
163 | 6 | 86 | close FILE; | ||||
164 | } | ||||||
165 | |||||||
166 | # UNPACK_MBOX2MAILDIR | ||||||
167 | # Unpack an mbox-file into an Maildir-directory. | ||||||
168 | |||||||
169 | our @maildir_names = | ||||||
170 | ( '8000000.localhost.23:2,' | ||||||
171 | , '90000000.localhost.213:2,' | ||||||
172 | , '110000000.localhost.12:2,' | ||||||
173 | , '110000001.l.42:2,' | ||||||
174 | , '110000002.l.42:2,' | ||||||
175 | , '110000002.l.43:2,' | ||||||
176 | , '110000004.l.43:2,' | ||||||
177 | , '110000005.l.43:2,' | ||||||
178 | , '110000006.l.43:2,' | ||||||
179 | , '110000007.l.43:2,D' | ||||||
180 | , '110000008.l.43:2,DF' | ||||||
181 | , '110000009.l.43:2,DFR' | ||||||
182 | , '110000010.l.43:2,DFRS' | ||||||
183 | , '110000011.l.43:2,DFRST' | ||||||
184 | , '110000012.l.43:2,F' | ||||||
185 | , '110000013.l.43:2,FR' | ||||||
186 | , '110000014.l.43:2,FRS' | ||||||
187 | , '110000015.l.43:2,FRST' | ||||||
188 | , '110000016.l.43:2,DR' | ||||||
189 | , '110000017.l.43:2,DRS' | ||||||
190 | , '110000018.l.43:2,DRST' | ||||||
191 | , '110000019.l.43:2,FS' | ||||||
192 | , '110000020.l.43:2,FST' | ||||||
193 | , '110000021.l.43:2,R' | ||||||
194 | , '110000022.l.43:2,RS' | ||||||
195 | , '110000023.l.43:2,RST' | ||||||
196 | , '110000024.l.43:2,S' | ||||||
197 | , '110000025.l.43:2,ST' | ||||||
198 | , '110000026.l.43:2,T' | ||||||
199 | , '110000027.l.43:2,' | ||||||
200 | , '110000028.l.43:2,' | ||||||
201 | , '110000029.l.43:2,' | ||||||
202 | , '110000030.l.43:2,' | ||||||
203 | , '110000031.l.43:2,' | ||||||
204 | , '110000032.l.43:2,' | ||||||
205 | , '110000033.l.43:2,' | ||||||
206 | , '110000034.l.43:2,' | ||||||
207 | , '110000035.l.43:2,' | ||||||
208 | , '110000036.l.43:2,' | ||||||
209 | , '110000037.l.43:2,' | ||||||
210 | , '110000038.l.43' | ||||||
211 | , '110000039.l.43' | ||||||
212 | , '110000040.l.43' | ||||||
213 | , '110000041.l.43' | ||||||
214 | , '110000042.l.43' | ||||||
215 | ); | ||||||
216 | |||||||
217 | sub unpack_mbox2maildir($$) | ||||||
218 | 4 | 4 | 0 | 505 | { my ($file, $dir) = @_; | ||
219 | 4 | 19 | clean_dir($dir); | ||||
220 | |||||||
221 | 4 | 50 | 47 | die unless @maildir_names==45; | |||
222 | |||||||
223 | 4 | 50 | 630 | mkdir $dir or die; | |||
224 | 4 | 50 | 3730 | mkdir File::Spec->catfile($dir, 'cur') or die; | |||
225 | 4 | 50 | 338 | mkdir File::Spec->catfile($dir, 'new') or die; | |||
226 | 4 | 50 | 292 | mkdir File::Spec->catfile($dir, 'tmp') or die; | |||
227 | 4 | 30 | my $msgnr = 0; | ||||
228 | |||||||
229 | 4 | 50 | 252 | open FILE, $file or die; | |||
230 | 4 | 234 | open OUT, '>', File::Spec->devnull; | ||||
231 | |||||||
232 | 4 | 26 | my $last_empty = 0; | ||||
233 | 4 | 8 | my $blank; | ||||
234 | |||||||
235 | 4 | 154 | while( |
||||
236 | 13392 | 100 | 21951 | { if( m/^From / ) | |||
237 | 180 | 5947 | { close OUT; | ||||
238 | 180 | 619 | undef $blank; | ||||
239 | 180 | 338 | my $now = time; | ||||
240 | 180 | 635 | my $hostname = hostname; | ||||
241 | |||||||
242 | 180 | 100 | 3060 | my $msgfile = File::Spec->catfile($dir | |||
243 | , ($msgnr > 40 ? 'new' : 'cur') | ||||||
244 | , $maildir_names[$msgnr++] | ||||||
245 | ); | ||||||
246 | |||||||
247 | 180 | 50 | 11369 | open OUT, ">", $msgfile or die "Create $msgfile: $!\n"; | |||
248 | 180 | 1517 | next; # from line not included in file. | ||||
249 | } | ||||||
250 | |||||||
251 | 13212 | 100 | 20285 | print OUT $blank | |||
252 | if defined $blank; | ||||||
253 | |||||||
254 | 13212 | 100 | 22892 | if( m/^\015?\012$/ ) | |||
255 | 1600 | 2244 | { $blank = $_; | ||||
256 | 1600 | 3961 | next; | ||||
257 | } | ||||||
258 | |||||||
259 | 11612 | 13616 | undef $blank; | ||||
260 | 11612 | 23489 | print OUT; | ||||
261 | } | ||||||
262 | |||||||
263 | 4 | 140 | close OUT; | ||||
264 | 4 | 69 | close FILE; | ||||
265 | } | ||||||
266 | |||||||
267 | # | ||||||
268 | # Compare two lists. | ||||||
269 | # | ||||||
270 | |||||||
271 | sub compare_lists($$) | ||||||
272 | 16 | 16 | 0 | 840 | { my ($first, $second) = @_; | ||
273 | #warn "[@$first]==[@$second]\n"; | ||||||
274 | 16 | 50 | 53 | return 0 unless @$first == @$second; | |||
275 | 16 | 51 | for(my $i=0; $i<@$first; $i++) | ||||
276 | 193 | 50 | 440 | { return 0 unless $first->[$i] eq $second->[$i]; | |||
277 | } | ||||||
278 | 16 | 110 | 1; | ||||
279 | } | ||||||
280 | |||||||
281 | # | ||||||
282 | # Compare the text of two messages, rather strict. | ||||||
283 | # On CRLF platforms, the Content-Length may be different. | ||||||
284 | # | ||||||
285 | |||||||
286 | sub compare_message_prints($$$) | ||||||
287 | 0 | 0 | 0 | 0 | { my ($first, $second, $label) = @_; | ||
288 | |||||||
289 | 0 | 0 | 0 | if($crlf_platform) | |||
290 | 0 | 0 | { $first =~ s/Content-Length: (\d+)/Content-Length: |
||||
291 | 0 | 0 | $second =~ s/Content-Length: (\d+)/Content-Length: |
||||
292 | } | ||||||
293 | |||||||
294 | 0 | 0 | is($first, $second, $label); | ||||
295 | } | ||||||
296 | |||||||
297 | # | ||||||
298 | # Strip message text down the things which are the same on all | ||||||
299 | # platforms and all situations. | ||||||
300 | # | ||||||
301 | |||||||
302 | sub reproducable_text($) | ||||||
303 | 0 | 0 | 0 | 0 | { my $text = shift; | ||
304 | 0 | 0 | my @lines = split /^/m, $text; | ||||
305 | 0 | 0 | foreach (@lines) | ||||
306 | 0 | 0 | { s/((?:references|message-id|date|content-length)\: ).*/$1 |
||||
307 | 0 | 0 | s/boundary-\d+/boundary- |
||||
308 | } | ||||||
309 | 0 | 0 | join '', @lines; | ||||
310 | } | ||||||
311 | |||||||
312 | # | ||||||
313 | # Compare two outputs of thread details. | ||||||
314 | # On CRLF platforms, the reported sizes are ignored. | ||||||
315 | # | ||||||
316 | |||||||
317 | sub compare_thread_dumps($$$) | ||||||
318 | 6 | 6 | 0 | 24 | { my ($first, $second, $label) = @_; | ||
319 | |||||||
320 | 6 | 50 | 21 | if($crlf_platform) | |||
321 | 0 | 0 | { $first =~ s/^..../ /gm; | ||||
322 | 0 | 0 | $second =~ s/^..../ /gm; | ||||
323 | } | ||||||
324 | |||||||
325 | 6 | 27 | is($first, $second, $label); | ||||
326 | } | ||||||
327 | |||||||
328 | # | ||||||
329 | # List directory | ||||||
330 | # This removes '.' and '..' | ||||||
331 | # | ||||||
332 | |||||||
333 | sub listdir($) | ||||||
334 | 3 | 3 | 0 | 16 | { my $dir = shift; | ||
335 | 3 | 50 | 118 | opendir LISTDIR, $dir or return (); | |||
336 | 3 | 280 | my @entities = grep !/^\.\.?$/, readdir LISTDIR; | ||||
337 | 3 | 76 | closedir LISTDIR; | ||||
338 | 3 | 64 | @entities; | ||||
339 | } | ||||||
340 | |||||||
341 | # | ||||||
342 | # A piece of HTML text which is used in some tests. | ||||||
343 | # | ||||||
344 | |||||||
345 | our $raw_html_data = <<'TEXT'; | ||||||
346 | |||||||
347 | |||||||
348 | |
||||||
349 | |||||||
350 | |||||||
351 | |||||||
352 | Life according to Brian |
||||||
353 | |||||||
354 | This is normal text, but not in a paragraph. New paragraph |
||||||
355 | in a bad way. | ||||||
356 | |||||||
357 | And this is just a continuation. When texts get long, they must be | ||||||
358 | auto-wrapped; and even that is working already. | ||||||
359 | |||||||
360 | Silly subsection at once |
||||||
361 | and another chapter |
||||||
362 | again a section |
||||||
363 | Normal paragraph, which contains an | ||||||
364 | SRC=image.gif>, some | ||||||
365 | italics with linebreak | ||||||
366 | and code | ||||||
367 | |||||||
368 | |
||||||
369 | And now for the preformatted stuff | ||||||
370 | it should stay as it was | ||||||
371 | even with strange blanks | ||||||
372 | and indentations | ||||||
373 | |||||||
374 | |||||||
375 | And back to normal text... | ||||||
376 | |
||||||
377 | |
||||||
378 | |
||||||
379 | |
||||||
380 | |
||||||
381 | |||||||
382 | |
||||||
383 | |||||||
384 | |||||||
385 | |||||||
386 | TEXT | ||||||
387 | |||||||
388 | 1; |