1#!./perl 2# 3# Contributed by Graham Barr <Graham.Barr@tiuk.ti.com> 4# 5# So far there are tests for the following prototypes. 6# none, () ($) ($@) ($%) ($;$) (&) (&\@) (&@) (%) (\%) (\@) 7# 8# It is impossible to test every prototype that can be specified, but 9# we should test as many as we can. 10# 11 12BEGIN { 13 chdir 't' if -d 't'; 14 @INC = '../lib'; 15} 16 17use strict; 18 19print "1..141\n"; 20 21my $i = 1; 22 23sub testing (&$) { 24 my $p = prototype(shift); 25 my $c = shift; 26 my $what = defined $c ? '(' . $p . ')' : 'no prototype'; 27 print '#' x 25,"\n"; 28 print '# Testing ',$what,"\n"; 29 print '#' x 25,"\n"; 30 print "not " 31 if((defined($p) && defined($c) && $p ne $c) 32 || (defined($p) != defined($c))); 33 printf "ok %d\n",$i++; 34} 35 36@_ = qw(a b c d); 37my @array; 38my %hash; 39 40## 41## 42## 43 44testing \&no_proto, undef; 45 46sub no_proto { 47 print "# \@_ = (",join(",",@_),")\n"; 48 scalar(@_) 49} 50 51print "not " unless 0 == no_proto(); 52printf "ok %d\n",$i++; 53 54print "not " unless 1 == no_proto(5); 55printf "ok %d\n",$i++; 56 57print "not " unless 4 == &no_proto; 58printf "ok %d\n",$i++; 59 60print "not " unless 1 == no_proto +6; 61printf "ok %d\n",$i++; 62 63print "not " unless 4 == no_proto(@_); 64printf "ok %d\n",$i++; 65 66## 67## 68## 69 70 71testing \&no_args, ''; 72 73sub no_args () { 74 print "# \@_ = (",join(",",@_),")\n"; 75 scalar(@_) 76} 77 78print "not " unless 0 == no_args(); 79printf "ok %d\n",$i++; 80 81print "not " unless 0 == no_args; 82printf "ok %d\n",$i++; 83 84print "not " unless 5 == no_args +5; 85printf "ok %d\n",$i++; 86 87print "not " unless 4 == &no_args; 88printf "ok %d\n",$i++; 89 90print "not " unless 2 == &no_args(1,2); 91printf "ok %d\n",$i++; 92 93eval "no_args(1)"; 94print "not " unless $@; 95printf "ok %d\n",$i++; 96 97## 98## 99## 100 101testing \&one_args, '$'; 102 103sub one_args ($) { 104 print "# \@_ = (",join(",",@_),")\n"; 105 scalar(@_) 106} 107 108print "not " unless 1 == one_args(1); 109printf "ok %d\n",$i++; 110 111print "not " unless 1 == one_args +5; 112printf "ok %d\n",$i++; 113 114print "not " unless 4 == &one_args; 115printf "ok %d\n",$i++; 116 117print "not " unless 2 == &one_args(1,2); 118printf "ok %d\n",$i++; 119 120eval "one_args(1,2)"; 121print "not " unless $@; 122printf "ok %d\n",$i++; 123 124eval "one_args()"; 125print "not " unless $@; 126printf "ok %d\n",$i++; 127 128sub one_a_args ($) { 129 print "# \@_ = (",join(",",@_),")\n"; 130 print "not " unless @_ == 1 && $_[0] == 4; 131 printf "ok %d\n",$i++; 132} 133 134one_a_args(@_); 135 136## 137## 138## 139 140testing \&over_one_args, '$@'; 141 142sub over_one_args ($@) { 143 print "# \@_ = (",join(",",@_),")\n"; 144 scalar(@_) 145} 146 147print "not " unless 1 == over_one_args(1); 148printf "ok %d\n",$i++; 149 150print "not " unless 2 == over_one_args(1,2); 151printf "ok %d\n",$i++; 152 153print "not " unless 1 == over_one_args +5; 154printf "ok %d\n",$i++; 155 156print "not " unless 4 == &over_one_args; 157printf "ok %d\n",$i++; 158 159print "not " unless 2 == &over_one_args(1,2); 160printf "ok %d\n",$i++; 161 162print "not " unless 5 == &over_one_args(1,@_); 163printf "ok %d\n",$i++; 164 165eval "over_one_args()"; 166print "not " unless $@; 167printf "ok %d\n",$i++; 168 169sub over_one_a_args ($@) { 170 print "# \@_ = (",join(",",@_),")\n"; 171 print "not " unless @_ >= 1 && $_[0] == 4; 172 printf "ok %d\n",$i++; 173} 174 175over_one_a_args(@_); 176over_one_a_args(@_,1); 177over_one_a_args(@_,1,2); 178over_one_a_args(@_,@_); 179 180## 181## 182## 183 184testing \&scalar_and_hash, '$%'; 185 186sub scalar_and_hash ($%) { 187 print "# \@_ = (",join(",",@_),")\n"; 188 scalar(@_) 189} 190 191print "not " unless 1 == scalar_and_hash(1); 192printf "ok %d\n",$i++; 193 194print "not " unless 3 == scalar_and_hash(1,2,3); 195printf "ok %d\n",$i++; 196 197print "not " unless 1 == scalar_and_hash +5; 198printf "ok %d\n",$i++; 199 200print "not " unless 4 == &scalar_and_hash; 201printf "ok %d\n",$i++; 202 203print "not " unless 2 == &scalar_and_hash(1,2); 204printf "ok %d\n",$i++; 205 206print "not " unless 5 == &scalar_and_hash(1,@_); 207printf "ok %d\n",$i++; 208 209eval "scalar_and_hash()"; 210print "not " unless $@; 211printf "ok %d\n",$i++; 212 213sub scalar_and_hash_a ($@) { 214 print "# \@_ = (",join(",",@_),")\n"; 215 print "not " unless @_ >= 1 && $_[0] == 4; 216 printf "ok %d\n",$i++; 217} 218 219scalar_and_hash_a(@_); 220scalar_and_hash_a(@_,1); 221scalar_and_hash_a(@_,1,2); 222scalar_and_hash_a(@_,@_); 223 224## 225## 226## 227 228testing \&one_or_two, '$;$'; 229 230sub one_or_two ($;$) { 231 print "# \@_ = (",join(",",@_),")\n"; 232 scalar(@_) 233} 234 235print "not " unless 1 == one_or_two(1); 236printf "ok %d\n",$i++; 237 238print "not " unless 2 == one_or_two(1,3); 239printf "ok %d\n",$i++; 240 241print "not " unless 1 == one_or_two +5; 242printf "ok %d\n",$i++; 243 244print "not " unless 4 == &one_or_two; 245printf "ok %d\n",$i++; 246 247print "not " unless 3 == &one_or_two(1,2,3); 248printf "ok %d\n",$i++; 249 250print "not " unless 5 == &one_or_two(1,@_); 251printf "ok %d\n",$i++; 252 253eval "one_or_two()"; 254print "not " unless $@; 255printf "ok %d\n",$i++; 256 257eval "one_or_two(1,2,3)"; 258print "not " unless $@; 259printf "ok %d\n",$i++; 260 261sub one_or_two_a ($;$) { 262 print "# \@_ = (",join(",",@_),")\n"; 263 print "not " unless @_ >= 1 && $_[0] == 4; 264 printf "ok %d\n",$i++; 265} 266 267one_or_two_a(@_); 268one_or_two_a(@_,1); 269one_or_two_a(@_,@_); 270 271## 272## 273## 274 275testing \&a_sub, '&'; 276 277sub a_sub (&) { 278 print "# \@_ = (",join(",",@_),")\n"; 279 &{$_[0]}; 280} 281 282sub tmp_sub_1 { printf "ok %d\n",$i++ } 283 284a_sub { printf "ok %d\n",$i++ }; 285a_sub \&tmp_sub_1; 286 287@array = ( \&tmp_sub_1 ); 288eval 'a_sub @array'; 289print "not " unless $@; 290printf "ok %d\n",$i++; 291 292## 293## 294## 295 296testing \&a_subx, '\&'; 297 298sub a_subx (\&) { 299 print "# \@_ = (",join(",",@_),")\n"; 300 &{$_[0]}; 301} 302 303sub tmp_sub_2 { printf "ok %d\n",$i++ } 304a_subx &tmp_sub_2; 305 306@array = ( \&tmp_sub_2 ); 307eval 'a_subx @array'; 308print "not " unless $@; 309printf "ok %d\n",$i++; 310 311## 312## 313## 314 315testing \&sub_aref, '&\@'; 316 317sub sub_aref (&\@) { 318 print "# \@_ = (",join(",",@_),")\n"; 319 my($sub,$array) = @_; 320 print "not " unless @_ == 2 && @{$array} == 4; 321 print map { &{$sub}($_) } @{$array} 322} 323 324@array = (qw(O K)," ", $i++); 325sub_aref { lc shift } @array; 326print "\n"; 327 328## 329## 330## 331 332testing \&sub_array, '&@'; 333 334sub sub_array (&@) { 335 print "# \@_ = (",join(",",@_),")\n"; 336 print "not " unless @_ == 5; 337 my $sub = shift; 338 print map { &{$sub}($_) } @_ 339} 340 341@array = (qw(O K)," ", $i++); 342sub_array { lc shift } @array; 343sub_array { lc shift } ('O', 'K', ' ', $i++); 344print "\n"; 345 346## 347## 348## 349 350testing \&a_hash, '%'; 351 352sub a_hash (%) { 353 print "# \@_ = (",join(",",@_),")\n"; 354 scalar(@_); 355} 356 357print "not " unless 1 == a_hash 'a'; 358printf "ok %d\n",$i++; 359 360print "not " unless 2 == a_hash 'a','b'; 361printf "ok %d\n",$i++; 362 363## 364## 365## 366 367testing \&a_hash_ref, '\%'; 368 369sub a_hash_ref (\%) { 370 print "# \@_ = (",join(",",@_),")\n"; 371 print "not " unless ref($_[0]) && $_[0]->{'a'}; 372 printf "ok %d\n",$i++; 373 $_[0]->{'b'} = 2; 374} 375 376%hash = ( a => 1); 377a_hash_ref %hash; 378print "not " unless $hash{'b'} == 2; 379printf "ok %d\n",$i++; 380 381## 382## 383## 384 385testing \&array_ref_plus, '\@@'; 386 387sub array_ref_plus (\@@) { 388 print "# \@_ = (",join(",",@_),")\n"; 389 print "not " unless @_ == 2 && ref($_[0]) && 1 == @{$_[0]} && $_[1] eq 'x'; 390 printf "ok %d\n",$i++; 391 @{$_[0]} = (qw(ok)," ",$i++,"\n"); 392} 393 394@array = ('a'); 395{ my @more = ('x'); 396 array_ref_plus @array, @more; } 397print "not " unless @array == 4; 398print @array; 399 400my $p; 401print "not " if defined prototype('CORE::print'); 402print "ok ", $i++, "\n"; 403 404print "not " if defined prototype('CORE::system'); 405print "ok ", $i++, "\n"; 406 407print "# CORE::open => ($p)\nnot " if ($p = prototype('CORE::open')) ne '*;$@'; 408print "ok ", $i++, "\n"; 409 410print "# CORE:Foo => ($p), \$@ => `$@'\nnot " 411 if defined ($p = eval { prototype('CORE::Foo') or 1 }) or $@ !~ /^Can't find an opnumber/; 412print "ok ", $i++, "\n"; 413 414# correctly note too-short parameter lists that don't end with '$', 415# a possible regression. 416 417sub foo1 ($\@); 418eval q{ foo1 "s" }; 419print "not " unless $@ =~ /^Not enough/; 420print "ok ", $i++, "\n"; 421 422sub foo2 ($\%); 423eval q{ foo2 "s" }; 424print "not " unless $@ =~ /^Not enough/; 425print "ok ", $i++, "\n"; 426 427sub X::foo3; 428*X::foo3 = sub {'ok'}; 429print "# $@not " unless eval {X->foo3} eq 'ok'; 430print "ok ", $i++, "\n"; 431 432sub X::foo4 ($); 433*X::foo4 = sub ($) {'ok'}; 434print "not " unless X->foo4 eq 'ok'; 435print "ok ", $i++, "\n"; 436 437# test if the (*) prototype allows barewords, constants, scalar expressions, 438# globs and globrefs (just as CORE::open() does), all under stricture 439sub star (*&) { &{$_[1]} } 440sub star2 (**&) { &{$_[2]} } 441sub BAR { "quux" } 442sub Bar::BAZ { "quuz" } 443my $star = 'FOO'; 444star FOO, sub { 445 print "not " unless $_[0] eq 'FOO'; 446 print "ok $i - star FOO\n"; 447}; $i++; 448star(FOO, sub { 449 print "not " unless $_[0] eq 'FOO'; 450 print "ok $i - star(FOO)\n"; 451 }); $i++; 452star "FOO", sub { 453 print "not " unless $_[0] eq 'FOO'; 454 print qq/ok $i - star "FOO"\n/; 455}; $i++; 456star("FOO", sub { 457 print "not " unless $_[0] eq 'FOO'; 458 print qq/ok $i - star("FOO")\n/; 459 }); $i++; 460star $star, sub { 461 print "not " unless $_[0] eq 'FOO'; 462 print "ok $i - star \$star\n"; 463}; $i++; 464star($star, sub { 465 print "not " unless $_[0] eq 'FOO'; 466 print "ok $i - star(\$star)\n"; 467 }); $i++; 468star *FOO, sub { 469 print "not " unless $_[0] eq \*FOO; 470 print "ok $i - star *FOO\n"; 471}; $i++; 472star(*FOO, sub { 473 print "not " unless $_[0] eq \*FOO; 474 print "ok $i - star(*FOO)\n"; 475 }); $i++; 476star \*FOO, sub { 477 print "not " unless $_[0] eq \*FOO; 478 print "ok $i - star \\*FOO\n"; 479}; $i++; 480star(\*FOO, sub { 481 print "not " unless $_[0] eq \*FOO; 482 print "ok $i - star(\\*FOO)\n"; 483 }); $i++; 484star2 FOO, BAR, sub { 485 print "not " unless $_[0] eq 'FOO' and $_[1] eq 'BAR'; 486 print "ok $i - star2 FOO, BAR\n"; 487}; $i++; 488star2(Bar::BAZ, FOO, sub { 489 print "not " unless $_[0] eq 'Bar::BAZ' and $_[1] eq 'FOO'; 490 print "ok $i - star2(Bar::BAZ, FOO)\n" 491 }); $i++; 492star2 BAR(), FOO, sub { 493 print "not " unless $_[0] eq 'quux' and $_[1] eq 'FOO'; 494 print "ok $i - star2 BAR(), FOO\n" 495}; $i++; 496star2(FOO, BAR(), sub { 497 print "not " unless $_[0] eq 'FOO' and $_[1] eq 'quux'; 498 print "ok $i - star2(FOO, BAR())\n"; 499 }); $i++; 500star2 "FOO", "BAR", sub { 501 print "not " unless $_[0] eq 'FOO' and $_[1] eq 'BAR'; 502 print qq/ok $i - star2 "FOO", "BAR"\n/; 503}; $i++; 504star2("FOO", "BAR", sub { 505 print "not " unless $_[0] eq 'FOO' and $_[1] eq 'BAR'; 506 print qq/ok $i - star2("FOO", "BAR")\n/; 507 }); $i++; 508star2 $star, $star, sub { 509 print "not " unless $_[0] eq 'FOO' and $_[1] eq 'FOO'; 510 print "ok $i - star2 \$star, \$star\n"; 511}; $i++; 512star2($star, $star, sub { 513 print "not " unless $_[0] eq 'FOO' and $_[1] eq 'FOO'; 514 print "ok $i - star2(\$star, \$star)\n"; 515 }); $i++; 516star2 *FOO, *BAR, sub { 517 print "not " unless $_[0] eq \*FOO and $_[1] eq \*BAR; 518 print "ok $i - star2 *FOO, *BAR\n"; 519}; $i++; 520star2(*FOO, *BAR, sub { 521 print "not " unless $_[0] eq \*FOO and $_[1] eq \*BAR; 522 print "ok $i - star2(*FOO, *BAR)\n"; 523 }); $i++; 524star2 \*FOO, \*BAR, sub { 525 no strict 'refs'; 526 print "not " unless $_[0] eq \*{'FOO'} and $_[1] eq \*{'BAR'}; 527 print "ok $i - star2 \*FOO, \*BAR\n"; 528}; $i++; 529star2(\*FOO, \*BAR, sub { 530 no strict 'refs'; 531 print "not " unless $_[0] eq \*{'FOO'} and $_[1] eq \*{'BAR'}; 532 print "ok $i - star2(\*FOO, \*BAR)\n"; 533 }); $i++; 534 535# test scalarref prototype 536sub sreftest (\$$) { 537 print "not " unless ref $_[0]; 538 print "ok $_[1] - sreftest\n"; 539} 540{ 541 no strict 'vars'; 542 sreftest my $sref, $i++; 543 sreftest($helem{$i}, $i++); 544 sreftest $aelem[0], $i++; 545} 546 547# test prototypes when they are evaled and there is a syntax error 548# Byacc generates the string "syntax error". Bison gives the 549# string "parse error". 550# 551for my $p ( "", qw{ () ($) ($@) ($%) ($;$) (&) (&\@) (&@) (%) (\%) (\@) } ) { 552 no warnings 'prototype'; 553 my $eval = "sub evaled_subroutine $p { &void *; }"; 554 eval $eval; 555 print "# eval[$eval]\nnot " unless $@ && $@ =~ /(parse|syntax) error/i; 556 print "ok ", $i++, "\n"; 557} 558 559# Not $$;$;$ 560print "not " unless prototype "CORE::substr" eq '$$;$$'; 561print "ok ", $i++, "\n"; 562 563# recv takes a scalar reference for its second argument 564print "not " unless prototype "CORE::recv" eq '*\\$$$'; 565print "ok ", $i++, "\n"; 566 567{ 568 my $myvar; 569 my @myarray; 570 my %myhash; 571 sub mysub { print "not calling mysub I hope\n" } 572 local *myglob; 573 574 sub myref (\[$@%&*]) { print "# $_[0]\n"; return "$_[0]" } 575 576 print "not " unless myref($myvar) =~ /^SCALAR\(/; 577 print "ok ", $i++, "\n"; 578 print "not " unless myref(@myarray) =~ /^ARRAY\(/; 579 print "ok ", $i++, "\n"; 580 print "not " unless myref(%myhash) =~ /^HASH\(/; 581 print "ok ", $i++, "\n"; 582 print "not " unless myref(&mysub) =~ /^CODE\(/; 583 print "ok ", $i++, "\n"; 584 print "not " unless myref(*myglob) =~ /^GLOB\(/; 585 print "ok ", $i++, "\n"; 586 587 eval q/sub multi1 (\[%@]) { 1 } multi1 $myvar;/; 588 print "not " 589 unless $@ =~ /Type of arg 1 to main::multi1 must be one of \[%\@\] /; 590 print "ok ", $i++, "\n"; 591 eval q/sub multi2 (\[$*&]) { 1 } multi2 @myarray;/; 592 print "not " 593 unless $@ =~ /Type of arg 1 to main::multi2 must be one of \[\$\*&\] /; 594 print "ok ", $i++, "\n"; 595 eval q/sub multi3 (\[$@]) { 1 } multi3 %myhash;/; 596 print "not " 597 unless $@ =~ /Type of arg 1 to main::multi3 must be one of \[\$\@\] /; 598 print "ok ", $i++, "\n"; 599 eval q/sub multi4 ($\[%]) { 1 } multi4 1, &mysub;/; 600 print "not " 601 unless $@ =~ /Type of arg 2 to main::multi4 must be one of \[%\] /; 602 print "ok ", $i++, "\n"; 603 eval q/sub multi5 (\[$@]$) { 1 } multi5 *myglob;/; 604 print "not " 605 unless $@ =~ /Type of arg 1 to main::multi5 must be one of \[\$\@\] / 606 && $@ =~ /Not enough arguments/; 607 print "ok ", $i++, "\n"; 608} 609 610# check that obviously bad prototypes are getting warnings 611{ 612 use warnings 'syntax'; 613 my $warn = ""; 614 local $SIG{__WARN__} = sub { $warn .= join("",@_) }; 615 616 eval 'sub badproto (@bar) { 1; }'; 617 print "not " unless $warn =~ /Illegal character in prototype for main::badproto : \@bar/; 618 print "ok ", $i++, "\n"; 619 620 eval 'sub badproto2 (bar) { 1; }'; 621 print "not " unless $warn =~ /Illegal character in prototype for main::badproto2 : bar/; 622 print "ok ", $i++, "\n"; 623 624 eval 'sub badproto3 (&$bar$@) { 1; }'; 625 print "not " unless $warn =~ /Illegal character in prototype for main::badproto3 : &\$bar\$\@/; 626 print "ok ", $i++, "\n"; 627 628 eval 'sub badproto4 (@ $b ar) { 1; }'; 629 print "not " unless $warn =~ /Illegal character in prototype for main::badproto4 : \@\$bar/; 630 print "ok ", $i++, "\n"; 631} 632 633# make sure whitespace in prototypes works 634eval "sub good (\$\t\$\n\$) { 1; }"; 635print "not " if $@; 636print "ok ", $i++, "\n"; 637 638# Ought to fail, doesn't in 5.8.1. 639eval 'sub bug (\[%@]) { } my $array = [0 .. 1]; bug %$array;'; 640print "not " unless $@ =~ /Not a HASH reference/; 641print "ok ", $i++, "\n"; 642