1#!./perl 2 3=head1 NAME 4 5s2p.t - test suite for s2p/psed 6 7=head1 NOTES 8 9The general idea is to 10 11 (a) run psed with a sed script and input data to obtain some output 12 (b) run s2p with a sed script creating a Perl program and then run the 13 Perl program with the input data, again producing output 14 15Both final outputs should be identical to the expected output. 16 17A $testcase{<name>} contains entries (after the comment ### <name> ###): 18 19 - script: the sed script 20 - input: the key of the input data, stored in $input{<input>} 21 - expect: the expected output 22 - datfil: an additional file [ <path>, <data> ] (if required) 23 24Temporary files are created in the working directory (embedding $$ 25in the name), and removed after the test. 26 27Except for bin2dec (which indeed converts binary to decimal) none of the 28sed scripts is doing something useful. 29 30Author: Wolfgang Laun. 31 32=cut 33 34BEGIN { 35 chdir 't' if -d 't'; 36 @INC = ( '../lib' ); 37} 38 39### use Test::More; 40use File::Copy; 41use File::Spec; 42require './test.pl'; 43 44# BRE extensions 45$ENV{PSEDEXTBRE} = '<>wW'; 46 47our %input = ( 48 bins => <<'[TheEnd]', 490 50111 511000 5210001 53[TheEnd] 54 55 text => <<'[TheEnd]', 56line 1 57line 2 58line 3 59line 4 60line 5 61line 6 62line 7 63line 8 64[TheEnd] 65 66 adr1 => <<'[TheEnd]', 67#no autoprint 68# This script should be run on itself 69/^#__DATA__$/,${ 70 /^#A$/p 71 s/^# *[0-9]* *// 72 /^#\*$/p 73 /^#\.$/p 74 /^#\(..\)\(..\)\2\1*$/p 75 /^#[abc]\{1,\}[def]\{1,\}$/p 76} 77#__DATA__ 78#A 79#* 80#. 81#abxyxy 82#abxyxyab 83#abxyxyabab 84#ad 85#abcdef 86[TheEnd] 87); 88 89 90our %testcase = ( 91 92### bin2dec ### 93'bin2dec' => { 94 script => <<'[TheEnd]', 95# binary -> decimal 96s/^[ ]*\([01]\{1,\}\)[ ]*/\1/ 97t go 98i\ 99is not a binary number 100d 101 102# expand binary to Xs 103: go 104s/^0*// 105s/^1/X/ 106: expand 107s/^\(X\{1,\}\)0/\1\1/ 108s/^\(X\{1,\}\)1/\1\1X/ 109t expand 110 111# count Xs in decimal 112: count 113s/^X/1/ 114s/0X/1/ 115s/1X/2/ 116s/2X/3/ 117s/3X/4/ 118s/4X/5/ 119s/5X/6/ 120s/6X/7/ 121s/7X/8/ 122s/8X/9/ 123s/9X/X0/ 124t count 125s/^$/0/ 126[TheEnd] 127 input => 'bins', 128 expect => <<'[TheEnd]', 1290 1307 1318 13217 133[TheEnd] 134}, 135 136 137### = ### 138'=' => { 139 script => <<'[TheEnd]', 1401= 141$= 142[TheEnd] 143 input => 'text', 144 expect => <<'[TheEnd]', 1451 146line 1 147line 2 148line 3 149line 4 150line 5 151line 6 152line 7 1538 154line 8 155[TheEnd] 156}, 157 158### D ### 159'D' => { 160 script => <<'[TheEnd]', 161#no autoprint 162/1/{ 163N 164N 165N 166D 167} 168p 169/2/D 170= 171p 172[TheEnd] 173 input => 'text', 174 expect => <<'[TheEnd]', 175line 2 176line 3 177line 4 178line 3 179line 4 1804 181line 3 182line 4 183line 5 1845 185line 5 186line 6 1876 188line 6 189line 7 1907 191line 7 192line 8 1938 194line 8 195[TheEnd] 196}, 197 198### H ### 199'H' => { 200 script => <<'[TheEnd]', 201#no autoprint 2021,$H 203$g 204$= 205$p 206[TheEnd] 207 input => 'text', 208 expect => <<'[TheEnd]', 2098 210 211line 1 212line 2 213line 3 214line 4 215line 5 216line 6 217line 7 218line 8 219[TheEnd] 220}, 221 222### N ### 223'N' => { 224 script => <<'[TheEnd]', 2253a\ 226added line 2274a\ 228added line 2295a\ 230added line 2313,5N 232= 233d 234[TheEnd] 235 input => 'text', 236 expect => <<'[TheEnd]', 2371 2382 239added line 2404 241added line 2426 2437 2448 245[TheEnd] 246}, 247 248### P ### 249'P' => { 250 script => <<'[TheEnd]', 2511N 2522N 2533N 2544= 2554P 2564,$d 257[TheEnd] 258 input => 'text', 259 expect => <<'[TheEnd]', 2604 261line 1 262[TheEnd] 263}, 264 265### a ### 266'a' => { 267 script => <<'[TheEnd]', 2681a\ 269added line 1.1\ 270added line 1.2 271 2723a\ 273added line 3.1 2743a\ 275added line 3.2 276 277[TheEnd] 278 input => 'text', 279 expect => <<'[TheEnd]', 280line 1 281added line 1.1 282added line 1.2 283line 2 284line 3 285added line 3.1 286added line 3.2 287line 4 288line 5 289line 6 290line 7 291line 8 292[TheEnd] 293}, 294 295### b ### 296'b' => { 297 script => <<'[TheEnd]', 298#no autoprint 2992 b eos 3004 b eos 301p 302: eos 303[TheEnd] 304 input => 'text', 305 expect => <<'[TheEnd]', 306line 1 307line 3 308line 5 309line 6 310line 7 311line 8 312[TheEnd] 313}, 314 315### block ### 316'block' => { 317 script => "#no autoprint\n1,3{\n=\np\n}", 318 input => 'text', 319 expect => <<'[TheEnd]', 3201 321line 1 3222 323line 2 3243 325line 3 326[TheEnd] 327}, 328 329### c ### 330'c' => { 331 script => <<'[TheEnd]', 3322= 333 3342,4c\ 335change 2,4 line 1\ 336change 2,4 line 2 337 3382= 339 3403,5c\ 341change 3,5 line 1\ 342change 3,5 line 2 343 3443= 345 346[TheEnd] 347 input => 'text', 348 expect => <<'[TheEnd]', 349line 1 3502 351change 2,4 line 1 352change 2,4 line 2 353line 5 354line 6 355line 7 356line 8 357[TheEnd] 358}, 359 360### c1 ### 361'c1' => { 362 script => <<'[TheEnd]', 3631c\ 364replaces line 1 365 3662,3c\ 367replaces lines 2-3 368 369/5/,/6/c\ 370replaces lines 3-4 371 3728,10c\ 373replaces lines 6-10 374[TheEnd] 375 input => 'text', 376 expect => <<'[TheEnd]', 377replaces line 1 378replaces lines 2-3 379line 4 380replaces lines 3-4 381line 7 382[TheEnd] 383}, 384 385### c2 ### 386'c2' => { 387 script => <<'[TheEnd]', 3883!c\ 389replace all except line 3 390 391[TheEnd] 392 input => 'text', 393 expect => <<'[TheEnd]', 394replace all except line 3 395replace all except line 3 396line 3 397replace all except line 3 398replace all except line 3 399replace all except line 3 400replace all except line 3 401replace all except line 3 402[TheEnd] 403}, 404 405### c3 ### 406'c3' => { 407 script => <<'[TheEnd]', 4081,4!c\ 409replace all except 1-4 410 411/5/,/8/!c\ 412replace all except 5-8 413[TheEnd] 414 input => 'text', 415 expect => <<'[TheEnd]', 416replace all except 5-8 417replace all except 5-8 418replace all except 5-8 419replace all except 5-8 420replace all except 1-4 421replace all except 1-4 422replace all except 1-4 423replace all except 1-4 424[TheEnd] 425}, 426 427### d ### 428'd' => { 429 script => <<'[TheEnd]', 430# d delete pattern space, start next cycle 4312,4 d 4325 d 433[TheEnd] 434 input => 'text', 435 expect => <<'[TheEnd]', 436line 1 437line 6 438line 7 439line 8 440[TheEnd] 441}, 442 443### gh ### 444'gh' => { 445 script => <<'[TheEnd]', 4461h 4472g 4483h 4494g 4505q 451[TheEnd] 452 input => 'text', 453 expect => <<'[TheEnd]', 454line 1 455line 1 456line 3 457line 3 458line 5 459[TheEnd] 460}, 461 462### i ### 463'i' => { 464 script => <<'[TheEnd]', 4651i\ 466inserted line 1.1\ 467inserted line 1.2 468 4693i\ 470inserted line 3.1 4713i\ 472inserted line 3.2 473[TheEnd] 474 input => 'text', 475 expect => <<'[TheEnd]', 476inserted line 1.1 477inserted line 1.2 478line 1 479line 2 480inserted line 3.1 481inserted line 3.2 482line 3 483line 4 484line 5 485line 6 486line 7 487line 8 488[TheEnd] 489}, 490 491### n ### 492'n' => { 493 script => <<'[TheEnd]', 4943a\ 495added line 4964a\ 497added line 4985a\ 499added line 5003,5n 501= 502d 503[TheEnd] 504 input => 'text', 505 expect => <<'[TheEnd]', 5061 5072 508line 3 509added line 5104 511line 5 512added line 5136 5147 5158 516[TheEnd] 517}, 518 519### o ### 520'o' => { 521 script => <<'[TheEnd]', 522/abc/,/def/ s//XXX/ 523// i\ 524cheers 525[TheEnd] 526 input => 'text', 527 expect => <<'[TheEnd]', 528line 1 529line 2 530line 3 531line 4 532line 5 533line 6 534line 7 535line 8 536[TheEnd] 537}, 538 539### q ### 540'q' => { 541 script => <<'[TheEnd]', 5422a\ 543append to line 2 5443a\ 545append to line 3 - should not appear in output 5463q 547[TheEnd] 548 input => 'text', 549 expect => <<'[TheEnd]', 550line 1 551line 2 552append to line 2 553line 3 554[TheEnd] 555}, 556 557### r ### 558'r' => { 559 datfil => [ 'r.txt', "r.txt line 1\nr.txt line 2\nr.txt line 3\n" ], 560 script => <<'[TheEnd]', 5612r%r.txt% 5624r %r.txt% 563[TheEnd] 564 input => 'text', 565 expect => <<'[TheEnd]', 566line 1 567line 2 568r.txt line 1 569r.txt line 2 570r.txt line 3 571line 3 572line 4 573r.txt line 1 574r.txt line 2 575r.txt line 3 576line 5 577line 6 578line 7 579line 8 580[TheEnd] 581}, 582 583### s ### 584's' => { 585 script => <<'[TheEnd]', 586# enclose any `(a)'.. `(c)' in `-' 587s/([a-z])/-\1-/g 588 589s/\([abc]\)/-\1-/g 590[TheEnd] 591 input => 'text', 592 expect => <<'[TheEnd]', 593line 1 594line 2 595line 3 596line 4 597line 5 598line 6 599line 7 600line 8 601[TheEnd] 602}, 603 604### s1 ### 605's1' => { 606 script => <<'[TheEnd]', 607s/\w/@1/ 608s/\y/@2/ 609 610s/\n/@3/ 611 612# this is literal { } 613s/a{3}/@4/ 614 615# proper repetition 616s/a\{3\}/a rep 3/ 617[TheEnd] 618 input => 'text', 619 expect => <<'[TheEnd]', 620@1ine 1 621@1ine 2 622@1ine 3 623@1ine 4 624@1ine 5 625@1ine 6 626@1ine 7 627@1ine 8 628[TheEnd] 629}, 630 631### t ### 632't' => { 633 script => join( "\n", 634 '#no autoprint', 's/./X/p', 's/foo/bar/p', 't bye', '=', 'p', ':bye' ), 635 input => 'text', 636 expect => <<'[TheEnd]', 637Xine 1 638Xine 2 639Xine 3 640Xine 4 641Xine 5 642Xine 6 643Xine 7 644Xine 8 645[TheEnd] 646}, 647 648### w ### 649'w' => { 650 datfil => [ 'w.txt', '' ], 651 script => <<'[TheEnd]', 652w %w.txt% 653[TheEnd] 654 input => 'text', 655 expect => <<'[TheEnd]', 656line 1 657line 2 658line 3 659line 4 660line 5 661line 6 662line 7 663line 8 664[TheEnd] 665}, 666 667### x ### 668'x' => { 669 script => <<'[TheEnd]', 6701h 6711d 6722x 6732,$G 674[TheEnd] 675 input => 'text', 676 expect => <<'[TheEnd]', 677line 1 678line 2 679line 3 680line 2 681line 4 682line 2 683line 5 684line 2 685line 6 686line 2 687line 7 688line 2 689line 8 690line 2 691[TheEnd] 692}, 693 694### y ### 695'y' => { 696 script => <<'[TheEnd]', 697y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/ 698y/|/\ 699/ 700[TheEnd] 701 input => 'text', 702 expect => <<'[TheEnd]', 703LINE 1 704LINE 2 705LINE 3 706LINE 4 707LINE 5 708LINE 6 709LINE 7 710LINE 8 711[TheEnd] 712}, 713 714### cnt ### 715'cnt' => { 716 script => <<'[TheEnd]', 717#no autoprint 718 719# delete line, append NL to hold space 720s/.*// 721H 722$!b 723 724# last line only: get hold 725g 726s/./X/g 727t count 728: count 729s/^X/1/ 730s/0X/1/ 731s/1X/2/ 732s/2X/3/ 733s/3X/4/ 734s/4X/5/ 735s/5X/6/ 736s/6X/7/ 737s/7X/8/ 738s/8X/9/ 739s/9X/X0/ 740t count 741p 742[TheEnd] 743 input => 'text', 744 expect => <<'[TheEnd]', 7458 746[TheEnd] 747}, 748 749### adr1 ### 750'adr1' => { 751 script => <<'[TheEnd]', 752#no autoprint 753# This script should be run on itself 754/^#__DATA__$/,${ 755 /^#A$/p 756 s/^# *[0-9]* *// 757 /^#\*$/p 758 /^#\.$/p 759 /^#\(..\)\(..\)\2\1*$/p 760 /^#[abc]\{1,\}[def]\{1,\}$/p 761} 762#__DATA__ 763#A 764#* 765#. 766#abxyxy 767#abxyxyab 768#abxyxyabab 769#ad 770#abcdef 771[TheEnd] 772 input => 'adr1', 773 expect => <<'[TheEnd]', 774#A 775[TheEnd] 776}, 777 778); 779 780my @aux = (); 781my $ntc = 2 * keys %testcase; 782plan( $ntc ); 783 784# temporary file names 785my $script = "s2pt$$.sed"; 786my $stdin = "s2pt$$.in"; 787my $plsed = "s2pt$$.pl"; 788 789# various command lines for 790my $s2p = File::Spec->catfile( File::Spec->updir(), 'x2p', 's2p' ); 791my $psed = File::Spec->catfile( File::Spec->curdir(), 'psed' ); 792if ($^O eq 'VMS') { 793 # default in the .com extenson if it's not already there 794 $s2p = VMS::Filespec::rmsexpand($s2p, '.com'); 795 $psed = VMS::Filespec::rmsexpand($psed, '.com'); 796} 797my $sedcmd = [ $psed, '-f', $script, $stdin ]; 798my $s2pcmd = [ $s2p, '-f', $script ]; 799my $plcmd = [ $plsed, $stdin ]; 800 801my $switches = ''; 802$switches = ['-x'] if $^O eq 'MacOS'; 803 804# psed: we create a local copy as linking may not work on some systems. 805copy( $s2p, $psed ); 806push( @aux, $psed ); 807 808# process all testcases 809# 810my $indat = ''; 811for my $tc ( sort keys %testcase ){ 812 my( $psedres, $s2pres ); 813 814 # 1st test: run psed 815 # prepare the script 816 open( SED, ">$script" ) || goto FAIL_BOTH; 817 my $script = $testcase{$tc}{script}; 818 819 # additional files for r, w: patch script, inserting temporary names 820 if( exists( $testcase{$tc}{datfil} ) ){ 821 my( $datnam, $datdat ) = @{$testcase{$tc}{datfil}}; 822 my $datfil = "s2pt$$" . $datnam; 823 push( @aux, $datfil ); 824 open( DAT, ">$datfil" ) || goto FAIL_BOTH; 825 print DAT $datdat; 826 close( DAT ); 827 $script =~ s/\%$datnam\%/$datfil/eg; 828 } 829 print SED $script; 830 close( SED ) || goto FAIL_BOTH; 831 832 # prepare input 833 # 834 if( $indat ne $testcase{$tc}{input} ){ 835 $indat = $testcase{$tc}{input}; 836 open( IN, ">$stdin" ) || goto FAIL_BOTH; 837 print IN $input{$indat}; 838 close( IN ) || goto FAIL_BOTH; 839 } 840 841 # on VMS, runperl eats blank lines to work around 842 # spurious newlines in pipes 843 $testcase{$tc}{expect} =~ s/\n\n/\n/ if $^O eq 'VMS'; 844 845 # run and compare 846 # 847 $psedres = runperl( args => $sedcmd, switches => $switches ); 848 is( $psedres, $testcase{$tc}{expect}, "psed $tc" ); 849 850 # 2nd test: run s2p 851 # translate the sed script to a Perl program 852 853 my $perlprog = runperl( args => $s2pcmd, switches => $switches ); 854 open( PP, ">$plsed" ) || goto FAIL_S2P; 855 print PP $perlprog; 856 close( PP ) || goto FAIL_S2P; 857 858 # execute generated Perl program, compare 859 $s2pres = runperl( args => $plcmd, switches => $switches ); 860 is( $s2pres, $testcase{$tc}{expect}, "s2p $tc" ); 861 next; 862 863FAIL_BOTH: 864 fail( "psed $tc" ); 865FAIL_S2P: 866 fail( "s2p $tc" ); 867} 868 869END { 870 for my $f ( $script, $stdin, $plsed, @aux ){ 871 1 while unlink( $f ); # hats off to VMS... 872 } 873} 874