]> git.vpit.fr Git - perl/modules/autovivification.git/commitdiff
Test keys/values @array
authorVincent Pit <vince@profvince.com>
Sat, 9 Jan 2010 14:56:42 +0000 (15:56 +0100)
committerVincent Pit <vince@profvince.com>
Sat, 9 Jan 2010 14:56:42 +0000 (15:56 +0100)
MANIFEST
lib/autovivification.pm
samples/hash2array.pl
t/22-hash-kv.t
t/32-array-kv.t [new file with mode: 0644]

index bf44d3acca03e683c8c3a227d13a2f678959053d..21c20c290063460d9237b16b6b7066afa54c6242 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -12,6 +12,7 @@ t/20-hash.t
 t/22-hash-kv.t
 t/30-array.t
 t/31-array-fast.t
+t/32-array-kv.t
 t/40-scope.t
 t/41-padsv.t
 t/91-pod.t
index bff3f85855b87d410fec9a338fd07955d6e358b6..1bab02f6466839d44978531853d89c1c348125e6 100644 (file)
@@ -65,6 +65,7 @@ Enables the features given in C<@opts>, which can be :
 C<'fetch'>
 
 Turn off autovivification for rvalue dereferencing expressions, such as C<< $value = $hashref->{key}[$idx]{$field} >>, C<< keys %{$hashref->{key}} >> or C<< values %{$hashref->{key}} >>.
+Starting from perl C<5.11>, it also covers C<leys> and C<values> on array references.
 When the expression would have autovivified, C<undef> is returned for a plain fetch, while C<keys> and C<values> return C<0> in scalar context and the empty list in list context.
 
 =item *
index e70b69be8ea90e83c558a527dcc862c8a0beba67..9fc4a61a773e68d15abae8ad54d3e94b65b0c47e 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Fatal qw/open/;
+use Fatal qw/open close/;
 use Text::Balanced qw/extract_bracketed/;
 
 open my $hash_t,       '<', 't/20-hash.t';
@@ -27,13 +27,48 @@ sub hash2array {
 
 sub dump_array {
  my ($a) = @_;
+
  return 'undef' unless defined $a;
- return $a      unless ref $a;
- die "Invalid argument" unless ref $a eq 'ARRAY';
- return '[ ' . join(', ', map dump_array($_), @$a) . ' ]';
+
+ if (ref $a) {
+  die "Invalid argument" unless ref $a eq 'ARRAY';
+  return '[ ' . join(', ', map dump_array($_), @$a) . ' ]';
+ } else {
+  $a = "'\Q$a\E'" if $a !~ /^\s*\d/;
+  return $a;
+ }
+}
+
+sub extract ($$) {
+ extract_bracketed $_[0], $_[1],  qr/.*?(?<![\\@%])(?:\\\\)*(?=$_[1])/
 }
 
-sub extract ($) { extract_bracketed $_[0], '{',  qr/.*?(?<!\\)(?:\\\\)*(?={)/ }
+sub convert_testcase ($$) {
+ local $_ = $_[0];
+ my $fast = $_[1];
+
+ s!(\ba\b)?(\s*)HASH\b!($1 ? 'an': '') . "$2ARRAY"!eg;
+ s{
+  [\{\[]\s*(['"]?[a-z]['"]?(?:\s*,\s*['"]?[a-z]['"]?)*)\s*[\}\]]
+ }{
+  '[' . join(', ', map { my $n = num($_); $fast ? $n : "\$N[$n]" }
+                    split /\s*,\s*/, $1) . ']'
+ }gex;
+ s!%(\{?)\$!\@$1\$!g;
+
+ my $buf;
+ my $suffix = $_;
+ my ($bracket, $prefix);
+ while (do { ($bracket, $suffix, $prefix) = extract($suffix, '{'); $bracket }) {
+  my $array = dump_array(hash2array(eval $bracket));
+  $buf .= $prefix . $array;
+ }
+ $buf .= $suffix;
+ $buf =~ s/\s+/ /g;
+ $buf =~ s/\s+$//;
+
+ return "$buf\n";
+}
 
 my $in_data;
 while (<$hash_t>) {
@@ -46,26 +81,31 @@ while (<$hash_t>) {
   print $array_t      $_;
   print $array_fast_t $_;
  } else {
-  for my $file ([ 1, $array_t ], [ 0, $array_fast_t ]) {
-   local $_ = $_;
-   s!(\ba\b)?(\s*)HASH\b!($1 ? 'an': '') . "$2ARRAY"!eg;
-   s{
-    {\s*(['"]?[a-z]['"]?(?:\s*,\s*['"]?[a-z]['"]?)*)\s*}
-   }{
-    '[' . join(', ', map { my $n = num($_); $file->[0] ? "\$N[$n]" : $n }
-                      split /\s*,\s*/, $1) . ']'
-   }gex;
-   s!%(\{?)\$!\@$1\$!g;
-   my $buf;
-   my $suffix = $_;
-   my ($bracket, $prefix);
-   while (do { ($bracket, $suffix, $prefix) = extract($suffix); $bracket }) {
-    $buf .= $prefix . dump_array(hash2array(eval $bracket));
-   }
-   $buf .= $suffix;
-   $buf =~ s/\s+/ /g;
-   $buf =~ s/\s+$//;
-   print { $file->[1] } "$buf\n";
+  print $array_t      convert_testcase($_, 0);
+  print $array_fast_t convert_testcase($_, 1);
+ }
+}
+
+close $hash_t;
+close $array_t;
+close $array_fast_t;
+
+open my $hash_specific_t,  '<', 't/22-hash-kv.t';
+open my $array_specific_t, '>', 't/32-array-kv.t';
+
+$in_data = 0;
+while (<$hash_specific_t>) {
+ if (/^__DATA__$/) {
+  $in_data = 1;
+ } elsif (!$in_data) {
+  s{'%'}{'\@'};
+  if (/\bplan\s*[\s\(]\s*tests\b/) {
+   s/\s*;?\s*$//;
+   s/^(\s*)//;
+   $_ = "$1if (\$] >= 5.011) { $_ } else { plan skip_all => 'perl 5.11 required for keys/values \@array' }\n";
   }
+ } else {
+  $_ = convert_testcase($_, 1);
  }
+ print $array_specific_t $_;
 }
index a965ed29c94c4a4fce06bbf939da7448d95524ff..999bfdfe2d5e3bf53e033e24e9ea9132c1afab27 100644 (file)
@@ -3,7 +3,11 @@
 use strict;
 use warnings;
 
-use Test::More tests => 9 * 3 * 64;
+use Test::More;
+
+BEGIN {
+ plan tests => 9 * 3 * 64;
+}
 
 use lib 't/lib';
 use autovivification::TestCases;
@@ -35,10 +39,10 @@ $x # [ keys %$x ] # '', [ ], undef #
 $x # [ keys %$x ] # '', [ ], undef # +fetch
 $x # [ keys %$x ] # '', [ ], { }   # +exists +delete +store
 
-$x->{a} ='b' # [ keys %$x ] # '', [ 'a' ], { a => 'b' }
-$x->{a} ='b' # [ keys %$x ] # '', [ 'a' ], { a => 'b' } #
-$x->{a} ='b' # [ keys %$x ] # '', [ 'a' ], { a => 'b' } # +fetch
-$x->{a} ='b' # [ keys %$x ] # '', [ 'a' ], { a => 'b' } # +exists +delete +store
+$x->{a} = 1 # [ keys %$x ] # '', [ 'a' ], { a => 1 }
+$x->{a} = 1 # [ keys %$x ] # '', [ 'a' ], { a => 1 } #
+$x->{a} = 1 # [ keys %$x ] # '', [ 'a' ], { a => 1 } # +fetch
+$x->{a} = 1 # [ keys %$x ] # '', [ 'a' ], { a => 1 } # +exists +delete +store
 
 $x # keys %{$x->{a}} # '', 0, { a => { } }
 $x # keys %{$x->{a}} # '', 0, undef        #
@@ -76,10 +80,10 @@ $x # [ values %$x ] # '', [ ], undef #
 $x # [ values %$x ] # '', [ ], undef # +fetch
 $x # [ values %$x ] # '', [ ], { }   # +exists +delete +store
 
-$x->{a} ='b' # [ values %$x ] # '', [ 'b' ], { a=>'b' }
-$x->{a} ='b' # [ values %$x ] # '', [ 'b' ], { a=>'b' } #
-$x->{a} ='b' # [ values %$x ] # '', [ 'b' ], { a=>'b' } # +fetch
-$x->{a} ='b' # [ values %$x ] # '', [ 'b' ], { a=>'b' } # +exists +delete +store
+$x->{a} = 1 # [ values %$x ] # '', [ 1 ], { a => 1 }
+$x->{a} = 1 # [ values %$x ] # '', [ 1 ], { a => 1 } #
+$x->{a} = 1 # [ values %$x ] # '', [ 1 ], { a => 1 } # +fetch
+$x->{a} = 1 # [ values %$x ] # '', [ 1 ], { a => 1 } # +exists +delete +store
 
 $x # values %{$x->{a}} # '', 0, { a => { } }
 $x # values %{$x->{a}} # '', 0, undef        #
diff --git a/t/32-array-kv.t b/t/32-array-kv.t
new file mode 100644 (file)
index 0000000..9ca1f05
--- /dev/null
@@ -0,0 +1,103 @@
+#!perl -T
+
+use strict;
+use warnings;
+
+use Test::More;
+
+BEGIN {
+ if ($] >= 5.011) { plan tests => 9 * 3 * 64 } else { plan skip_all => 'perl 5.11 required for keys/values @array' }
+}
+
+use lib 't/lib';
+use autovivification::TestCases;
+
+while (<DATA>) {
+ 1 while chomp;
+ next unless /#/;
+ testcase_ok($_, '@');
+}
+
+__DATA__
+
+--- keys ---
+
+$x # keys @$x # '', 0, [ ]
+$x # keys @$x # '', 0, undef #
+$x # keys @$x # '', 0, undef # +fetch
+$x # keys @$x # '', 0, [ ] # +exists
+$x # keys @$x # '', 0, [ ] # +delete
+$x # keys @$x # '', 0, [ ] # +store
+
+$x # keys @$x # qr/^Reference vivification forbidden/, undef, undef # +strict +fetch
+$x # keys @$x # '', 0, [ ] # +strict +exists
+$x # keys @$x # '', 0, [ ] # +strict +delete
+$x # keys @$x # '', 0, [ ] # +strict +store
+
+$x # [ keys @$x ] # '', [ ], [ ]
+$x # [ keys @$x ] # '', [ ], undef #
+$x # [ keys @$x ] # '', [ ], undef # +fetch
+$x # [ keys @$x ] # '', [ ], [ ] # +exists +delete +store
+
+$x->[0] = 1 # [ keys @$x ] # '', [0], [ 1 ]
+$x->[0] = 1 # [ keys @$x ] # '', [0], [ 1 ] #
+$x->[0] = 1 # [ keys @$x ] # '', [0], [ 1 ] # +fetch
+$x->[0] = 1 # [ keys @$x ] # '', [0], [ 1 ] # +exists +delete +store
+
+$x # keys @{$x->[0]} # '', 0, [ [ ] ]
+$x # keys @{$x->[0]} # '', 0, undef #
+$x # keys @{$x->[0]} # '', 0, undef # +fetch
+$x # keys @{$x->[0]} # '', 0, [ [ ] ] # +exists
+$x # keys @{$x->[0]} # '', 0, [ [ ] ] # +delete
+$x # keys @{$x->[0]} # '', 0, [ [ ] ] # +store
+
+$x # keys @{$x->[0]} # qr/^Reference vivification forbidden/, undef, undef # +strict +fetch
+$x # keys @{$x->[0]} # '', 0, [ [ ] ] # +strict +exists
+$x # keys @{$x->[0]} # '', 0, [ [ ] ] # +strict +delete
+$x # keys @{$x->[0]} # '', 0, [ [ ] ] # +strict +store
+
+$x # [ keys @{$x->[0]} ] # '', [ ], [ [ ] ]
+$x # [ keys @{$x->[0]} ] # '', [ ], undef #
+$x # [ keys @{$x->[0]} ] # '', [ ], undef # +fetch
+$x # [ keys @{$x->[0]} ] # '', [ ], [ [ ] ] # +exists +delete +store
+
+--- values ---
+
+$x # values @$x # '', 0, [ ]
+$x # values @$x # '', 0, undef #
+$x # values @$x # '', 0, undef # +fetch
+$x # values @$x # '', 0, [ ] # +exists
+$x # values @$x # '', 0, [ ] # +delete
+$x # values @$x # '', 0, [ ] # +store
+
+$x # values @$x # qr/^Reference vivification forbidden/, undef, undef # +strict +fetch
+$x # values @$x # '', 0, [ ] # +strict +exists
+$x # values @$x # '', 0, [ ] # +strict +delete
+$x # values @$x # '', 0, [ ] # +strict +store
+
+$x # [ values @$x ] # '', [ ], [ ]
+$x # [ values @$x ] # '', [ ], undef #
+$x # [ values @$x ] # '', [ ], undef # +fetch
+$x # [ values @$x ] # '', [ ], [ ] # +exists +delete +store
+
+$x->[0] = 1 # [ values @$x ] # '', [ 1 ], [ 1 ]
+$x->[0] = 1 # [ values @$x ] # '', [ 1 ], [ 1 ] #
+$x->[0] = 1 # [ values @$x ] # '', [ 1 ], [ 1 ] # +fetch
+$x->[0] = 1 # [ values @$x ] # '', [ 1 ], [ 1 ] # +exists +delete +store
+
+$x # values @{$x->[0]} # '', 0, [ [ ] ]
+$x # values @{$x->[0]} # '', 0, undef #
+$x # values @{$x->[0]} # '', 0, undef # +fetch
+$x # values @{$x->[0]} # '', 0, [ [ ] ] # +exists
+$x # values @{$x->[0]} # '', 0, [ [ ] ] # +delete
+$x # values @{$x->[0]} # '', 0, [ [ ] ] # +store
+
+$x # values @{$x->[0]} # qr/^Reference vivification forbidden/, undef, undef # +strict +fetch
+$x # values @{$x->[0]} # '', 0, [ [ ] ] # +strict +exists
+$x # values @{$x->[0]} # '', 0, [ [ ] ] # +strict +delete
+$x # values @{$x->[0]} # '', 0, [ [ ] ] # +strict +store
+
+$x # [ values @{$x->[0]} ] # '', [ ], [ [ ] ]
+$x # [ values @{$x->[0]} ] # '', [ ], undef #
+$x # [ values @{$x->[0]} ] # '', [ ], undef # +fetch
+$x # [ values @{$x->[0]} ] # '', [ ], [ [ ] ] # +exists +delete +store