@@ -4,78 +4,181 @@ use Test2::V0;
44# load the script
55do (' ./Porting/merge-deltas.pl' ) or die $@ || $! ;
66
7- # helper function
8- sub head2_slice ( $tree , $title ) {
9- my $begin = next_header_pos( $tree , 2, header_pos( $tree , 1, $title ) );
10- my $end = next_header_pos( $tree , 1, $begin ) - 1;
11- return [ $tree -> @[ $begin .. $end ] ];
12- }
13-
14- # test data
7+ # test snippets
158my %pod = do {
169 local $/ ;
1710 my ( undef , @kv ) = split /^# (.*)\n/m, <DATA>;
1811 @kv ;
1912};
20- $pod {master } = slurp(' Porting/perldelta_template.pod' );
13+
14+ # grab text snippets from the template
15+ # and double-check they're not empty
16+ {
17+ my $template = slurp(' Porting/perldelta_template.pod' );
18+ @pod {qw( preamble postamble ) } =
19+ $template =~ / \A (.*?)^=head1 Notice.*(^=head1 Acknowledgements.*)\Z /gsm ;
20+ is( $pod {$_ }, L(), " $_ is not empty" ) for qw( preamble postamble ) ;
21+ for (qw( Notice Security Documentation Diagnostics Testing ) ) {
22+ ( $pod {" xxx_\L $_ " } ) = $template =~ / ^=head1 $_ \n\n (.*?)^=/gsm ;
23+ is( $pod {" xxx_\L $_ " }, L(), " xxx_\L $_ \E is not empty" );
24+ }
25+ for ( ' New Documentation' , ' Changes to Existing Documentation' ) {
26+ my $key = lc join ' _' , xxx => tr / / _/ r;
27+ ( $pod {$key } ) = $template =~ / ^=head2 $_ \n\n (.*)^=/gsm ;
28+ is( $pod {$key }, L(), " $key is not empty" );
29+ }
30+ }
31+
32+ $pod {" item_bullet_xxx" } = " =item *\n\n XXX\n\n " ;
33+ $pod {" item_bullet$_ " } = " =item *\n\n Item number $_ \n\n " for 1 .. 5;
34+ $pod {" item_text_xxx" } = " =item XXX-item\n\n XXX\n\n " ;
35+ $pod {" item_text$_ " } = " =item Number $_ \n\n Text number $_ \n\n " for 1 .. 5;
36+
37+ # helper function to build pod from a short description
38+ sub assemble_pod {
39+ state $format = {
40+ head1 => " =head1 %s \n\n " ,
41+ head2 => " =head2 %s \n\n " ,
42+ over => " =over 4\n\n %s =back\n\n " ,
43+ };
44+ return join ' ' , map exists $pod {$_ }
45+ ? $pod {$_ }
46+ : /:/ ? do {
47+ my ( $fmt , @items ) = split /:/;
48+ sprintf $format -> {$fmt }, join ' ' , map $pod {$_ } // $_ , @items ;
49+ }
50+ : $_ ,
51+ ' preamble' , shift -> @*, ' postamble' ;
52+ }
53+
54+ # test data
55+ my @tests = ( # name, expected, master, deltas...
56+ [ ' skip (empty)' , [' ' ], [' ' ], [' ' ] ],
57+ [
58+ ' skip' ,
59+ [' ' ],
60+ [' ' ],
61+ [
62+ ' head1:Modules and Pragmata' , # this one is skipped
63+ ' xxx_notice' , ' xxx_security' # random content
64+ ]
65+ ],
66+ [
67+ ' copy' ,
68+ [qw( head1:Notice notice xxx_notice ) ],
69+ [qw( head1:Notice xxx_notice ) ],
70+ [qw( head1:Notice notice ) ],
71+ ],
72+ [
73+ ' head2 (single)' ,
74+ [qw( head1:Security xxx_security security1 ) ],
75+ [qw( head1:Security xxx_security ) ],
76+ [qw( head1:Security xxx_security security1 ) ],
77+ ],
78+ [
79+ ' head2 (2-in-1)' ,
80+ [qw( head1:Security xxx_security security1 security2 ) ],
81+ [qw( head1:Security xxx_security ) ],
82+ [qw( head1:Security xxx_security security1 security2 ) ],
83+ ],
84+ [
85+ ' head2 (multiple)' ,
86+ [qw( head1:Security xxx_security security1 security2 ) ],
87+ [qw( head1:Security xxx_security ) ],
88+ [qw( head1:Security xxx_security security1 ) ],
89+ [qw( head1:Security xxx_security security2 ) ],
90+ ],
91+ [
92+ ' head2 (multiple reverse)' ,
93+ [qw( head1:Security xxx_security security2 security1 ) ],
94+ [qw( head1:Security xxx_security ) ],
95+ [qw( head1:Security xxx_security security2 ) ],
96+ [qw( head1:Security xxx_security security1 ) ],
97+ ],
98+ [
99+ ' copy + head2' ,
100+ [
101+ qw( head1:Notice notice xxx_notice head1:Security xxx_security security1 )
102+ ],
103+ [qw( head1:Notice xxx_notice head1:Security xxx_security ) ],
104+ [qw( head1:Notice notice ) ],
105+ [qw( head1:Security xxx_security security1 ) ],
106+ ],
107+ [
108+ ' item (single)' ,
109+ [qw( head1:Testing xxx_testing over:item_bullet1:item_bullet_xxx ) ],
110+ [qw( head1:Testing xxx_testing over:item_bullet_xxx ) ],
111+ [qw( head1:Testing xxx_testing over:item_bullet1 ) ],
112+ ],
113+ [
114+ ' item (2-in-1)' ,
115+ [
116+ qw( head1:Testing xxx_testing over:item_bullet1:item_bullet2:item_bullet_xxx )
117+ ],
118+ [qw( head1:Testing xxx_testing over:item_bullet_xxx ) ],
119+ [qw( head1:Testing xxx_testing over:item_bullet1:item_bullet2 ) ],
120+ ],
121+ [
122+ ' item (multiple)' ,
123+ [
124+ qw( head1:Testing xxx_testing ) ,
125+ ' over:item_bullet1:item_bullet2:item_bullet3:item_bullet4:item_bullet_xxx'
126+ ],
127+ [qw( head1:Testing xxx_testing over:item_bullet_xxx ) ],
128+ [qw( head1:Testing xxx_testing over:item_bullet1:item_bullet2 ) ],
129+ [qw( head1:Testing xxx_testing over:item_bullet3:item_bullet4 ) ],
130+ ],
131+ [
132+ ' item (multiple reverse)' ,
133+ [
134+ qw( head1:Testing xxx_testing ) ,
135+ ' over:item_bullet3:item_bullet4:item_bullet1:item_bullet2:item_bullet_xxx'
136+ ],
137+ [qw( head1:Testing xxx_testing over:item_bullet_xxx ) ],
138+ [qw( head1:Testing xxx_testing over:item_bullet3:item_bullet4 ) ],
139+ [qw( head1:Testing xxx_testing over:item_bullet1:item_bullet2 ) ],
140+ ],
141+ );
21142
22143# tree_for:
23144# just a single test: we're not testing Pod::Simple::SimpleTree
24145is(
25- tree_for( $pod {' NAME section ' } ),
146+ tree_for( $pod {security1 } ),
26147 [
27148 Document => { start_line => 1 },
28- [ head1 => { start_line => 1 }, ' NAME' ],
29- [ Para => { start_line => 3 }, ' some text' ]
149+ [ head2 => { start_line => 1 }, ' CVE-2025-12345' ],
150+ [ Para => { start_line => 3 }, ' Some CVE was fixed.' ],
151+ [ Para => { start_line => 5 }, ' Found by some person.' ],
30152 ],
31- ' tree_for on NAME section '
153+ ' tree_for (basic POD) '
32154);
33155
34- # as_pod: round trips
35- is( as_pod( tree_for( $pod {$_ } ) ), $pod {$_ }, " $_ POD round trips" )
36- for sort keys %pod ;
37-
38- # merge_info
39- my ( $master , $delta , $title );
40-
41- # merge_into: skips (e.g. NAME)
42- $title = ' NAME' ;
43- $master = tree_for( $pod {master } );
44- my $master_pod = as_pod( $pod {master } ); # compute it before munging $master
45- merge_into( $master , tree_for( $pod {$title } ), $title );
46- is( as_pod($master ), $master_pod , ' merge_into( skip )' );
47-
48- # merge_into: head2 section (e.g. Security)
49- $title = ' Security' ;
50- $master = tree_for( $pod {master } );
51- $delta = tree_for( $pod {$title } );
52- merge_into( $master , $delta , $title );
53- is(
54- head2_slice( $master , $title ),
55- head2_slice( $delta , $title ),
56- ' merge_into( head2 )'
57- );
156+ # merge_into:
157+ # this is the meat of our tests
158+ for my $t (@tests ) {
159+ my ( $mesg , $expected_spec , $master_spec , @delta_specs ) = @$t ;
160+ my $master = tree_for( assemble_pod($master_spec ) );
161+ merge_into( $master , $_ , $mesg )
162+ for map tree_for( assemble_pod($_ ) ), reverse @delta_specs ;
163+ is( as_pod($master ), assemble_pod($expected_spec ), $mesg );
164+ }
58165
59166done_testing;
60167
61168__DATA__
62- # NAME section
63- =head1 NAME
64-
65- some text
66-
67- =cut
68- # Security
69- =head1 Security
169+ # notice
170+ My important notice.
70171
71- Some security blurb.
172+ # security1
173+ =head2 CVE-2025-12345
72174
73- =head2 [ CVE-1999-12345] Heap buffer overflow vulnerability
175+ Some CVE was fixed.
74176
75- A heap buffer overflow vulnerability was discovered in Perl .
177+ Found by some person .
76178
77- =head1 Acknowledgements
179+ # security2
180+ =head2 Some other security fix
78181
79- ACK
182+ Was Perl pwnd again? Looks like.
80183
81- =cut
184+ # empty
0 commit comments