summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--regen/warnings.pl226
-rw-r--r--t/porting/deprecation.t145
3 files changed, 260 insertions, 112 deletions
diff --git a/MANIFEST b/MANIFEST
index d19cbf0da6..f390bd9319 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -6220,6 +6220,7 @@ t/porting/copyright.t Check that copyright years match
t/porting/corelist.t Check that Module-CoreList has perl versions for the current perl
t/porting/customized.dat Data file for porting/customized.t
t/porting/customized.t Check all CUSTOMIZED files are as they should be
+t/porting/deprecation.t Test that deprecation warnings are handled right
t/porting/diag.t Test completeness of perldiag.pod
t/porting/dual-life.t Check that dual-life bins are in utils/
t/porting/exec-bit.t Check that exec-bit bins are identified
diff --git a/regen/warnings.pl b/regen/warnings.pl
index 1d1aa1de66..4b598bbc31 100644
--- a/regen/warnings.pl
+++ b/regen/warnings.pl
@@ -5,13 +5,13 @@
# lib/warnings.pm
# warnings.h
#
-# from information hardcoded into this script (the $TREE hash), plus the
+# from information hardcoded into this script (the $WARNING_TREE hash), plus the
# template for warnings.pm in the DATA section.
#
# When changing the number of warnings, t/op/caller.t should change to
# correspond with the value of $BYTES in lib/warnings.pm
#
-# With an argument of 'tree', just dump the contents of $TREE and exits.
+# With an argument of 'tree', just dump the contents of $WARNING_TREE and exits.
# Also accepts the standard regen_lib -q and -v args.
#
# This script is normally invoked from regen.pl.
@@ -44,7 +44,7 @@ sub DEFAULT_OFF () { 2 }
# created. But the warnings category 'io' WILL include all the mask bits
# necessary to turn on 'pipe', 'unopened' etc.
-my $TREE = {
+our $WARNING_TREE = {
'all' => [ 5.008, {
'io' => [ 5.008, {
'pipe' => [ 5.008, DEFAULT_OFF],
@@ -334,7 +334,7 @@ sub warningsTree
if !ref $v || ref $v ne 'ARRAY' ;
my $offset ;
- if ($tree ne $TREE) {
+ if ($tree ne $WARNING_TREE) {
$rv .= $prefix . "|\n" ;
$rv .= $prefix . "+- $k" ;
$offset = ' ' x ($max + 4) ;
@@ -404,149 +404,151 @@ sub mkOct
###########################################################################
+sub main {
-if (@ARGV && $ARGV[0] eq "tree")
-{
- print warningsTree($TREE, " ") ;
- exit ;
-}
-
-my ($warn_h, $warn_pm) = map {
- open_new($_, '>', { by => 'regen/warnings.pl' });
-} 'warnings.h', 'lib/warnings.pm';
+ if (@ARGV && $ARGV[0] eq "tree")
+ {
+ print warningsTree($WARNING_TREE, " ") ;
+ exit ;
+ }
-my ($index, $warn_size);
+ my ($warn_h, $warn_pm) = map {
+ open_new($_, '>', { by => 'regen/warnings.pl' });
+ } 'warnings.h', 'lib/warnings.pm';
-# generate warnings.h
+ my ($index, $warn_size);
-print $warn_h warnings_h_boilerplate_1();
+ # generate warnings.h
-$index = orderValues($TREE);
+ print $warn_h warnings_h_boilerplate_1();
-die <<EOM if $index > 255 ;
-Too many warnings categories -- max is 255
-rewrite packWARN* & unpackWARN* macros
-EOM
+ $index = orderValues($WARNING_TREE);
-walk ($TREE) ;
-for (my $i = $index; $i & 3; $i++) {
- push @{$CATEGORIES{all}}, $i;
-}
+ die <<~EOM if $index > 255 ;
+ Too many warnings categories -- max is 255
+ rewrite packWARN* & unpackWARN* macros
+ EOM
-$index *= 2 ;
-$warn_size = int($index / 8) + ($index % 8 != 0) ;
-
-my $k ;
-my $last_ver = 0;
-my @names;
-foreach $k (sort { $a <=> $b } keys %VALUE_TO_NAME) {
- my ($name, $version) = @{ $VALUE_TO_NAME{$k} };
- print $warn_h "\n/* Warnings Categories added in Perl $version */\n\n"
- if $last_ver != $version ;
- $name =~ y/:/_/;
- $name = "WARN_$name";
- print $warn_h tab(6, "#define $name"), " $k\n" ;
- push @names, $name;
- $last_ver = $version ;
-}
+ walk ($WARNING_TREE) ;
+ for (my $i = $index; $i & 3; $i++) {
+ push @{$CATEGORIES{all}}, $i;
+ }
-print $warn_h tab(6, '#define WARNsize'), " $warn_size\n" ;
-print $warn_h tab(6, '#define WARN_ALLstring'), ' "', ('\125' x $warn_size) , "\"\n" ;
-print $warn_h tab(6, '#define WARN_NONEstring'), ' "', ('\0' x $warn_size) , "\"\n" ;
+ $index *= 2 ;
+ $warn_size = int($index / 8) + ($index % 8 != 0) ;
+
+ my $k ;
+ my $last_ver = 0;
+ my @names;
+ foreach $k (sort { $a <=> $b } keys %VALUE_TO_NAME) {
+ my ($name, $version) = @{ $VALUE_TO_NAME{$k} };
+ print $warn_h "\n/* Warnings Categories added in Perl $version */\n\n"
+ if $last_ver != $version ;
+ $name =~ y/:/_/;
+ $name = "WARN_$name";
+ print $warn_h tab(6, "#define $name"), " $k\n" ;
+ push @names, $name;
+ $last_ver = $version ;
+ }
-print $warn_h warnings_h_boilerplate_2();
+ print $warn_h tab(6, '#define WARNsize'), " $warn_size\n" ;
+ print $warn_h tab(6, '#define WARN_ALLstring'), ' "', ('\125' x $warn_size) , "\"\n" ;
+ print $warn_h tab(6, '#define WARN_NONEstring'), ' "', ('\0' x $warn_size) , "\"\n" ;
-print $warn_h "\n\n/*\n" ;
-print $warn_h map { "=for apidoc Amnh||$_\n" } @names;
-print $warn_h "\n=cut\n*/\n\n" ;
-print $warn_h "/* end of file warnings.h */\n";
+ print $warn_h warnings_h_boilerplate_2();
-read_only_bottom_close_and_rename($warn_h);
+ print $warn_h "\n\n/*\n" ;
+ print $warn_h map { "=for apidoc Amnh||$_\n" } @names;
+ print $warn_h "\n=cut\n*/\n\n" ;
+ print $warn_h "/* end of file warnings.h */\n";
+ read_only_bottom_close_and_rename($warn_h);
-# generate warnings.pm
-while (<DATA>) {
- last if /^VERSION$/ ;
- print $warn_pm $_ ;
-}
+ # generate warnings.pm
-print $warn_pm qq(our \$VERSION = "$::VERSION";\n);
+ while (<DATA>) {
+ last if /^VERSION$/ ;
+ print $warn_pm $_ ;
+ }
-while (<DATA>) {
- last if /^KEYWORDS$/ ;
- print $warn_pm $_ ;
-}
+ print $warn_pm qq(our \$VERSION = "$::VERSION";\n);
-$last_ver = 0;
-print $warn_pm "our %Offsets = (" ;
-foreach my $k (sort { $a <=> $b } keys %VALUE_TO_NAME) {
- my ($name, $version) = @{ $VALUE_TO_NAME{$k} };
- $name = lc $name;
- $k *= 2 ;
- if ( $last_ver != $version ) {
- print $warn_pm "\n";
- print $warn_pm tab(6, " # Warnings Categories added in Perl $version");
- print $warn_pm "\n";
+ while (<DATA>) {
+ last if /^KEYWORDS$/ ;
+ print $warn_pm $_ ;
}
- print $warn_pm tab(6, " '$name'"), "=> $k,\n" ;
- $last_ver = $version;
-}
-print $warn_pm ");\n\n" ;
+ $last_ver = 0;
+ print $warn_pm "our %Offsets = (" ;
+ foreach my $k (sort { $a <=> $b } keys %VALUE_TO_NAME) {
+ my ($name, $version) = @{ $VALUE_TO_NAME{$k} };
+ $name = lc $name;
+ $k *= 2 ;
+ if ( $last_ver != $version ) {
+ print $warn_pm "\n";
+ print $warn_pm tab(6, " # Warnings Categories added in Perl $version");
+ print $warn_pm "\n";
+ }
+ print $warn_pm tab(6, " '$name'"), "=> $k,\n" ;
+ $last_ver = $version;
+ }
-print $warn_pm "our %Bits = (\n" ;
-foreach my $k (sort keys %CATEGORIES) {
+ print $warn_pm ");\n\n" ;
- my $v = $CATEGORIES{$k} ;
- my @list = sort { $a <=> $b } @$v ;
+ print $warn_pm "our %Bits = (\n" ;
+ foreach my $k (sort keys %CATEGORIES) {
- print $warn_pm tab(6, " '$k'"), '=> "',
- mkHex($warn_size, map $_ * 2 , @list),
- '", # [', mkRange(@list), "]\n" ;
-}
+ my $v = $CATEGORIES{$k} ;
+ my @list = sort { $a <=> $b } @$v ;
-print $warn_pm ");\n\n" ;
+ print $warn_pm tab(6, " '$k'"), '=> "',
+ mkHex($warn_size, map $_ * 2 , @list),
+ '", # [', mkRange(@list), "]\n" ;
+ }
-print $warn_pm "our %DeadBits = (\n" ;
-foreach my $k (sort keys %CATEGORIES) {
+ print $warn_pm ");\n\n" ;
- my $v = $CATEGORIES{$k} ;
- my @list = sort { $a <=> $b } @$v ;
+ print $warn_pm "our %DeadBits = (\n" ;
+ foreach my $k (sort keys %CATEGORIES) {
- print $warn_pm tab(6, " '$k'"), '=> "',
- mkHex($warn_size, map $_ * 2 + 1 , @list),
- '", # [', mkRange(@list), "]\n" ;
-}
+ my $v = $CATEGORIES{$k} ;
+ my @list = sort { $a <=> $b } @$v ;
-print $warn_pm ");\n\n" ;
+ print $warn_pm tab(6, " '$k'"), '=> "',
+ mkHex($warn_size, map $_ * 2 + 1 , @list),
+ '", # [', mkRange(@list), "]\n" ;
+ }
-print $warn_pm "our %NoOp = (\n" ;
-foreach my $k ( grep /\A[a-z:_]+\z/, sort keys %NO_BIT_FOR ) {
- print $warn_pm tab(6, " '$k'"), "=> 1,\n";
-}
+ print $warn_pm ");\n\n" ;
-print $warn_pm ");\n\n" ;
-print $warn_pm "# These are used by various things, including our own tests\n";
-print $warn_pm tab(6, 'our $NONE'), '= "', ('\0' x $warn_size) , "\";\n" ;
-print $warn_pm tab(6, 'our $DEFAULT'), '= "',
- mkHex($warn_size, map $_ * 2, @DEFAULTS),
- '"; # [', mkRange(sort { $a <=> $b } @DEFAULTS), "]\n" ;
-print $warn_pm tab(6, 'our $LAST_BIT'), '= ' . "$index ;\n" ;
-print $warn_pm tab(6, 'our $BYTES'), '= ' . "$warn_size ;\n" ;
-while (<DATA>) {
- if ($_ eq "=for warnings.pl tree-goes-here\n") {
- print $warn_pm warningsTree($TREE, " ");
- next;
+ print $warn_pm "our %NoOp = (\n" ;
+ foreach my $k ( grep /\A[a-z:_]+\z/, sort keys %NO_BIT_FOR ) {
+ print $warn_pm tab(6, " '$k'"), "=> 1,\n";
}
- print $warn_pm $_ ;
-}
-read_only_bottom_close_and_rename($warn_pm);
+ print $warn_pm ");\n\n" ;
+ print $warn_pm "# These are used by various things, including our own tests\n";
+ print $warn_pm tab(6, 'our $NONE'), '= "', ('\0' x $warn_size) , "\";\n" ;
+ print $warn_pm tab(6, 'our $DEFAULT'), '= "',
+ mkHex($warn_size, map $_ * 2, @DEFAULTS),
+ '"; # [', mkRange(sort { $a <=> $b } @DEFAULTS), "]\n" ;
+ print $warn_pm tab(6, 'our $LAST_BIT'), '= ' . "$index ;\n" ;
+ print $warn_pm tab(6, 'our $BYTES'), '= ' . "$warn_size ;\n" ;
+ while (<DATA>) {
+ if ($_ eq "=for warnings.pl tree-goes-here\n") {
+ print $warn_pm warningsTree($WARNING_TREE, " ");
+ next;
+ }
+ print $warn_pm $_ ;
+ }
-exit(0);
+ read_only_bottom_close_and_rename($warn_pm);
+ exit(0);
+}
+main() unless caller();
# -----------------------------------------------------------------
sub warnings_h_boilerplate_1 { return <<'EOM'; }
diff --git a/t/porting/deprecation.t b/t/porting/deprecation.t
new file mode 100644
index 0000000000..109818fe6f
--- /dev/null
+++ b/t/porting/deprecation.t
@@ -0,0 +1,145 @@
+#!/usr/bin/perl
+
+BEGIN {
+ if (-f './TestInit.pm') {
+ @INC = '.';
+ } elsif (-f '../TestInit.pm') {
+ @INC = '..';
+ }
+}
+use TestInit qw(T); # T is chdir to the top level
+
+use warnings;
+use strict;
+use Config;
+use Data::Dumper;
+require './t/test.pl';
+
+plan("no_plan");
+
+# Test that all deprecations in regen/warnings.pl are mentioned in
+# pod/perldeprecation.pod and that there is sufficient time between them.
+
+my $pod_file = "./pod/perldeprecation.pod";
+my $warnings_file = "./regen/warnings.pl";
+
+do $warnings_file;
+our $WARNING_TREE;
+
+my $deprecated = $WARNING_TREE->{all}[1]{deprecated}[2];
+
+open my $fh, "<", $pod_file
+ or die "failed to open '$pod_file': $!";
+my $removed_in_version;
+my $subject;
+my %category_seen;
+my %subject_has_category;
+my $in_legacy;
+
+while (<$fh>) {
+ if (/^=head2 (?|Perl (5\.\d+)(?:\.\d+)?|(Unscheduled))/) { # ignore minor version
+ $removed_in_version = lc $1;
+ if ($removed_in_version eq "5.38") {
+ $in_legacy = 1;
+ }
+ }
+ elsif (/^=head3 (.*)/) {
+ my $new_subject = $1;
+ if (!$in_legacy and $subject) {
+ ok($subject_has_category{$subject},
+ "Subject '$subject' has a category specified");
+ }
+ $subject = $new_subject;
+ }
+ elsif (/^Category: "([::\w]+)"/) {
+ my $category = $1;
+ $category_seen{$category} = $removed_in_version;
+ $subject_has_category{$subject} = $category;
+ next if $removed_in_version eq "unscheduled";
+ my $tuple = $deprecated->{$category};
+ ok( $tuple, "Deprecated category '$category' ($subject) exists in $warnings_file")
+ or next;
+ my $added_in_version = $tuple->[0];
+ $added_in_version =~ s/(5\.\d{3})\d+/$1/;
+
+ my $diff = $removed_in_version - $added_in_version;
+ cmp_ok($diff, ">=", 0.004, # two production cycles
+ "Version change for '$category' ($subject) is sufficiently after deprecation date")
+ }
+}
+# make sure that all the deprecated categories have an entry of some sort
+foreach my $category (sort keys %$deprecated) {
+ ok($category_seen{$category},"Deprecated category '$category' is documented in $pod_file");
+}
+# make sure that there arent any new uses of WARN_DEPRECATED,
+# note that \< and \> are ERE expressions roughly equivalent to perl regex \b
+if (-e ".git") {
+ chomp(my @warn_deprecated = `git grep "\<WARN_DEPRECATED\>"`);
+ my %files;
+ foreach my $line (@warn_deprecated) {
+ my ($file, $text) = split /:/, $line, 2;
+ if ($file =~ m!^dist/Devel-PPPort! ||
+ $file eq "t/porting/diag.t" ||
+ ($file eq "warnings.h" && $text=~/^[=#]/)
+ ) {
+ next;
+ }
+ $files{$file}++;
+ }
+ is(0+keys %files, 0,
+ "There should not be any new files which mention WARN_DEPRECATED");
+}
+
+# Test that deprecation warnings are produced under "use warnings"
+# (set above)
+{
+ my $warning = "nada";
+ local $SIG{__WARN__} = sub { $warning = $_[0] };
+ my $count = 0;
+ while ($count<1) {
+ LABEL: $count++;
+ goto DONE if $count>1;
+ }
+ goto LABEL;
+ DONE:
+ like($warning,
+ qr/Use of "goto" to jump into a construct is deprecated/,
+ "Got expected deprecation warning");
+}
+# Test that we can silence deprecation warnings with "no warnings 'deprecated'"
+# as we used to.
+{
+ no warnings 'deprecated';
+ my $warning = "nada";
+ local $SIG{__WARN__} = sub { $warning = $_[0] };
+ my $count = 0;
+ while ($count<1) {
+ LABEL: $count++;
+ goto DONE if $count>1;
+ }
+ goto LABEL;
+ DONE:
+ like($warning, qr/nada/,
+ "no warnings 'deprecated'; silenced deprecation warning as expected");
+}
+
+# Test that we can silence a specific deprecation warnings with "no warnings 'deprecated::$subcategory'"
+# and that by doing so we don't silence any other deprecation warnings.
+{
+ no warnings 'deprecated::goto_construct';
+ my $warning = "nada";
+ local $SIG{__WARN__} = sub { $warning = $_[0] };
+ my $count = 0;
+ while ($count<1) {
+ LABEL: $count++;
+ goto DONE if $count>1;
+ }
+ goto LABEL;
+ DONE:
+ like($warning, qr/nada/,
+ "no warnings 'deprecated::goto_construct'; silenced deprecation warning as expected");
+ @INC = ();
+ do "regen.pl"; # this should produce a deprecation warning
+ like($warning, qr/is no longer in \@INC/,
+ "no warnings 'deprecated::goto_construct'; did not silence deprecated::dot_in_inc warnings");
+}