3 # testsuite for Data::Dumper
7 require Config; import Config;
8 if ($Config{'extensions'} !~ /\bData\/Dumper\b/) {
9 print "1..0 # Skip: Data::Dumper was not built\n";
14 # Since Perl 5.8.1 because otherwise hash ordering is really random.
15 local $Data::Dumper::Sortkeys = 1;
20 $Data::Dumper::Pad = "#";
26 sub convert_to_native($) {
29 # unicode_to_native() not available before this release; hence won't work
30 # on EBCDIC platforms for earlier.
31 return $input if $] lt 5.007_003;
35 # The input should always be one of the following constructs
36 while ($input =~ m/ ( \\ [0-7]+ )
37 | ( \\ x \{ [[:xdigit:]]+ } )
41 #print STDERR __LINE__, ": ", $&, "\n";
44 if (defined $4) { # Literal
48 elsif (defined $3) { # backslash escape
49 $index = ord eval "\"$3\"";
52 elsif (defined $2) { # Hex
53 $index = utf8::unicode_to_native(ord eval "\"$2\"");
55 # But low hex numbers are always in octal. These are all
57 my $format = ($index < ord(" "))
60 $replacement = sprintf($format, $index);
62 elsif (defined $1) { # Octal
63 $index = utf8::unicode_to_native(ord eval "\"$1\"");
64 $replacement = sprintf("\\%o", $index);
67 die "Unexpected match in convert_to_native()";
70 if (defined $output[$index]) {
71 print STDERR "ordinal $index already has '$output[$index]'; skipping '$replacement'\n";
75 $output[$index] = $replacement;
78 return join "", grep { defined } @output;
86 $t =~ s/([A-Z]+)\(0x[0-9a-f]+\)/$1(0xdeadbeef)/g
87 if ($WANT =~ /deadbeef/);
88 $name = $name ? " - $name" : '';
89 print( ($t eq $WANT and not $@) ? "ok $TNUM$name\n"
90 : "not ok $TNUM$name\n--Expected--\n$WANT\n--Got--\n$@$t\n");
94 print $@ ? "not ok $TNUM\n# \$@ says: $@\n" : "ok $TNUM - no eval error\n";
98 $t =~ s/([A-Z]+)\(0x[0-9a-f]+\)/$1(0xdeadbeef)/g
99 if ($WANT =~ /deadbeef/);
100 print( ($t eq $WANT and not $@) ? "ok $TNUM - works a 2nd time after intervening eval\n"
101 : "not ok $TNUM\n--Expected--\n$WANT\n--Got--\n$@$t\n");
106 ++$TNUM; print "ok $TNUM # skip $reason\n";
107 ++$TNUM; print "ok $TNUM # skip $reason\n";
108 ++$TNUM; print "ok $TNUM # skip $reason\n";
113 # Force Data::Dumper::Dump to use perl. We test Dumpxs explicitly by calling
114 # it direct. Out here it lets us knobble the next if to test that the perl
115 # only tests do work (and count correctly)
116 $Data::Dumper::Useperl = 1;
117 if (defined &Data::Dumper::Dumpxs) {
118 print "### XS extension loaded, will run XS tests\n";
122 print "### XS extensions not loaded, will NOT run XS tests\n";
159 TEST (q(Data::Dumper->Dump([$a,$b,$c], [qw(a b), 6])),
160 'basic test with names: Dump()');
161 TEST (q(Data::Dumper->Dumpxs([$a,$b,$c], [qw(a b), 6])),
162 'basic test with names: Dumpxs()')
166 local $Data::Dumper::Sparseseen = 1;
167 TEST (q(Data::Dumper->Dump([$a,$b,$c], [qw(a b), 6])),
168 'Sparseseen with names: Dump()');
169 TEST (q(Data::Dumper->Dumpxs([$a,$b,$c], [qw(a b), 6])),
170 'Sparseseen with names: Dumpxs()')
195 $Data::Dumper::Purity = 1; # fill in the holes for eval
196 TEST (q(Data::Dumper->Dump([$a, $b], [qw(*a b)])),
197 'Purity: basic test with dereferenced array: Dump()'); # print as @a
198 TEST (q(Data::Dumper->Dumpxs([$a, $b], [qw(*a b)])),
199 'Purity: basic test with dereferenced array: Dumpxs()')
203 local $Data::Dumper::Sparseseen = 1;
204 TEST (q(Data::Dumper->Dump([$a, $b], [qw(*a b)])),
205 'Purity: Sparseseen with dereferenced array: Dump()'); # print as @a
206 TEST (q(Data::Dumper->Dumpxs([$a, $b], [qw(*a b)])),
207 'Purity: Sparseseen with dereferenced array: Dumpxs()')
227 #$b{'c'} = $b{'a'}[2];
231 TEST (q(Data::Dumper->Dump([$b, $a], [qw(*b a)])),
232 'basic test with dereferenced hash: Dump()'); # print as %b
233 TEST (q(Data::Dumper->Dumpxs([$b, $a], [qw(*b a)])),
234 'basic test with dereferenced hash: Dumpxs()')
250 #$a->[1]{'b'} = $a->[1];
256 $Data::Dumper::Indent = 1;
258 $d = Data::Dumper->new([$a,$b], [qw(a b)]);
259 $d->Seen({'*c' => $c});
262 'Indent: Seen: Dump()');
265 $d = Data::Dumper->new([$a,$b], [qw(a b)]);
266 $d->Seen({'*c' => $c});
269 'Indent: Seen: Dumpxs()');
295 $d->Purity(0)->Quotekeys(0);
296 TEST (q( $d->Reset; $d->Dump ),
297 'Indent(3): Purity(0)->Quotekeys(0): Dump()');
299 TEST (q( $d->Reset; $d->Dumpxs ),
300 'Indent(3): Purity(0)->Quotekeys(0): Dumpxs()')
317 #$VAR1->[1]{'a'} = $VAR1;
318 #$VAR1->[1]{'b'} = $VAR1->[1];
319 #$VAR1->[2] = $VAR1->[1]{'c'};
322 TEST (q(Dumper($a)), 'Dumper');
323 TEST (q(Data::Dumper::DumperX($a)), 'DumperX') if $XS;
342 local $Data::Dumper::Purity = 0;
343 local $Data::Dumper::Quotekeys = 0;
344 local $Data::Dumper::Terse = 1;
346 'Purity 0: Quotekeys 0: Terse 1: Dumper');
347 TEST (q(Data::Dumper::DumperX($a)),
348 'Purity 0: Quotekeys 0: Terse 1: DumperX')
357 # "abc\0'\efg" => "mno\0",
362 $foo = { "abc\000\'\efg" => "mno\000",
366 local $Data::Dumper::Useqq = 1;
367 TEST (q(Dumper($foo)), 'Useqq: Dumper');
368 TEST (q(Data::Dumper::DumperX($foo)), 'Useqq: DumperX') if $XS;
381 %foo = (a=>1,b=>\$foo,c=>\@foo);
403 #*::foo{ARRAY}->[1] = $foo;
404 #*::foo{ARRAY}->[2]{'b'} = *::foo{SCALAR};
405 #*::foo{ARRAY}->[2]{'c'} = *::foo{ARRAY};
406 #*::foo{ARRAY}->[2]{'d'} = *::foo{ARRAY}->[2];
407 #*::foo = *::foo{ARRAY}->[2];
408 #@bar = @{*::foo{ARRAY}};
409 #%baz = %{*::foo{ARRAY}->[2]};
412 $Data::Dumper::Purity = 1;
413 $Data::Dumper::Indent = 3;
414 TEST (q(Data::Dumper->Dump([\\*foo, \\@foo, \\%foo], ['*foo', '*bar', '*baz'])),
415 'Purity 1: Indent 3: Dump()');
416 TEST (q(Data::Dumper->Dumpxs([\\*foo, \\@foo, \\%foo], ['*foo', '*bar', '*baz'])),
417 'Purity 1: Indent 3: Dumpxs()')
435 #*::foo{ARRAY}->[1] = $foo;
436 #*::foo{ARRAY}->[2]{'b'} = *::foo{SCALAR};
437 #*::foo{ARRAY}->[2]{'c'} = *::foo{ARRAY};
438 #*::foo{ARRAY}->[2]{'d'} = *::foo{ARRAY}->[2];
439 #*::foo = *::foo{ARRAY}->[2];
440 #$bar = *::foo{ARRAY};
441 #$baz = *::foo{ARRAY}->[2];
444 $Data::Dumper::Indent = 1;
445 TEST (q(Data::Dumper->Dump([\\*foo, \\@foo, \\%foo], ['foo', 'bar', 'baz'])),
446 'Purity 1: Indent 1: Dump()');
447 TEST (q(Data::Dumper->Dumpxs([\\*foo, \\@foo, \\%foo], ['foo', 'bar', 'baz'])),
448 'Purity 1: Indent 1: Dumpxs()')
467 #*::foo{HASH}->{'b'} = *::foo{SCALAR};
468 #*::foo{HASH}->{'c'} = \@bar;
469 #*::foo{HASH}->{'d'} = *::foo{HASH};
470 #$bar[2] = *::foo{HASH};
471 #%baz = %{*::foo{HASH}};
475 TEST (q(Data::Dumper->Dump([\\@foo, \\%foo, \\*foo], ['*bar', '*baz', '*foo'])),
476 'array|hash|glob dereferenced: Dump()');
477 TEST (q(Data::Dumper->Dumpxs([\\@foo, \\%foo, \\*foo], ['*bar', '*baz', '*foo'])),
478 'array|hash|glob dereferenced: Dumpxs()')
497 #*::foo{HASH}->{'b'} = *::foo{SCALAR};
498 #*::foo{HASH}->{'c'} = $bar;
499 #*::foo{HASH}->{'d'} = *::foo{HASH};
500 #$bar->[2] = *::foo{HASH};
501 #$baz = *::foo{HASH};
505 TEST (q(Data::Dumper->Dump([\\@foo, \\%foo, \\*foo], ['bar', 'baz', 'foo'])),
506 'array|hash|glob: not dereferenced: Dump()');
507 TEST (q(Data::Dumper->Dumpxs([\\@foo, \\%foo, \\*foo], ['bar', 'baz', 'foo'])),
508 'array|hash|glob: not dereferenced: Dumpxs()')
528 $Data::Dumper::Purity = 0;
529 $Data::Dumper::Quotekeys = 0;
530 TEST (q(Data::Dumper->Dump([\\*foo, \\@foo, \\%foo], ['*foo', '*bar', '*baz'])),
531 'Purity 0: Quotekeys 0: dereferenced: Dump()');
532 TEST (q(Data::Dumper->Dumpxs([\\*foo, \\@foo, \\%foo], ['*foo', '*bar', '*baz'])),
533 'Purity 0: Quotekeys 0: dereferenced: Dumpxs')
553 TEST (q(Data::Dumper->Dump([\\*foo, \\@foo, \\%foo], ['foo', 'bar', 'baz'])),
554 'Purity 0: Quotekeys 0: not dereferenced: Dump()');
555 TEST (q(Data::Dumper->Dumpxs([\\*foo, \\@foo, \\%foo], ['foo', 'bar', 'baz'])),
556 'Purity 0: Quotekeys 0: not dereferenced: Dumpxs()')
565 @dogs = ( 'Fido', 'Wags' );
572 $mutts = $mutts; # avoid warning
582 # ${$kennels{First}},
583 # ${$kennels{Second}},
590 $d = Data::Dumper->new([\\%kennel, \\@dogs, $mutts],
591 [qw(*kennels *dogs *mutts)] );
594 'constructor: hash|array|scalar: Dump()');
597 $d = Data::Dumper->new([\\%kennel, \\@dogs, $mutts],
598 [qw(*kennels *dogs *mutts)] );
601 'constructor: hash|array|scalar: Dumpxs()');
607 #%kennels = %kennels;
612 TEST q($d->Dump), 'object call: Dump';
613 TEST q($d->Dumpxs), 'object call: Dumpxs' if $XS;
623 # ${$kennels{First}},
624 # ${$kennels{Second}},
630 TEST q($d->Reset; $d->Dump), 'Reset and Dump separate calls';
632 TEST (q($d->Reset; $d->Dumpxs), 'Reset and Dumpxs separate calls');
642 # First => \$dogs[0],
643 # Second => \$dogs[1]
646 #%kennels = %{$dogs[2]};
647 #%mutts = %{$dogs[2]};
651 $d = Data::Dumper->new([\\@dogs, \\%kennel, $mutts],
652 [qw(*dogs *kennels *mutts)] );
655 'constructor: array|hash|scalar: Dump()');
658 $d = Data::Dumper->new([\\@dogs, \\%kennel, $mutts],
659 [qw(*dogs *kennels *mutts)] );
662 'constructor: array|hash|scalar: Dumpxs()');
667 TEST q($d->Reset->Dump), 'Reset Dump chained';
669 TEST q($d->Reset->Dumpxs), 'Reset Dumpxs chained';
690 $d = Data::Dumper->new( [\@dogs, \%kennel], [qw(*dogs *kennels)] );
691 $d->Deepcopy(1)->Dump;
693 'Deepcopy(1): Dump');
695 # TEST 'q($d->Reset->Dumpxs);
697 $d = Data::Dumper->new( [\@dogs, \%kennel], [qw(*dogs *kennels)] );
698 $d->Deepcopy(1)->Dumpxs;
700 'Deepcopy(1): Dumpxs');
707 sub z { print "foo\n" }
719 TEST (q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'b' => \&z})->Dump;),
720 'Seen: scalar: Dump');
721 TEST (q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'b' => \&z})->Dumpxs;),
722 'Seen: scalar: Dumpxs')
734 TEST (q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'*b' => \&z})->Dump;),
736 TEST (q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'*b' => \&z})->Dumpxs;),
737 'Seen: glob: Dumpxs')
749 TEST (q(Data::Dumper->new([\&z,$c],['*a','*c'])->Seen({'*b' => \&z})->Dump;),
750 'Seen: glob: dereference: Dump');
751 TEST (q(Data::Dumper->new([\&z,$c],['*a','*c'])->Seen({'*b' =>
753 'Seen: glob: derference: Dumpxs')
772 TEST (q(Data::Dumper->new([$a],['*a'])->Purity(1)->Dump;),
773 'Purity(1): dereference: Dump');
774 TEST (q(Data::Dumper->new([$a],['*a'])->Purity(1)->Dumpxs;),
775 'Purity(1): dereference: Dumpxs')
790 TEST (q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dump;),
791 'Purity(1): not dereferenced: Dump');
792 TEST (q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dumpxs;),
793 'Purity(1): not dereferenced: Dumpxs')
798 $a = [{ a => \$b }, { b => undef }];
799 $b = [{ c => \$b }, { d => \$a }];
819 #${$a->[0]{a}}->[0]->{c} = $a->[0]{a};
820 #${${$a->[0]{a}}->[1]->{d}} = $a;
824 TEST (q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dump;),
825 'Purity(1): Dump again');
826 TEST (q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dumpxs;),
827 'Purity(1); Dumpxs again')
832 $a = [[[[\\\\\'foo']]]];
849 #$c = ${${$a->[0][0][0][0]}};
852 TEST (q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Purity(1)->Dump;),
853 'Purity(1): Dump: 3 elements');
854 TEST (q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Purity(1)->Dumpxs;),
855 'Purity(1): Dumpxs: 3 elements')
874 # e => 'ARRAY(0xdeadbeef)'
883 TEST (q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(4)->Dump;),
884 'Maxdepth(4): Dump()');
885 TEST (q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(4)->Dumpxs;),
886 'Maxdepth(4): Dumpxs()')
893 # b => 'HASH(0xdeadbeef)'
901 TEST (q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(1)->Dump;),
902 'Maxdepth(1): Dump()');
903 TEST (q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(1)->Dumpxs;),
904 'Maxdepth(1): Dumpxs()')
920 TEST (q(Data::Dumper->new([$b],['b'])->Purity(0)->Dump;),
921 'Purity(0): Dump()');
922 TEST (q(Data::Dumper->new([$b],['b'])->Purity(0)->Dumpxs;),
923 'Purity(0): Dumpxs()')
932 #${$b->[0]} = $b->[0];
936 TEST (q(Data::Dumper->new([$b],['b'])->Purity(1)->Dump;),
937 'Purity(1): Dump()');
938 TEST (q(Data::Dumper->new([$b],['b'])->Purity(1)->Dumpxs;),
946 ## XS code was adding an extra \0
952 TEST q(Data::Dumper->Dump([$a], ['a'])), "\\x{9c10}";
954 SKIP_TEST "Incomplete support for UTF-8 in old perls";
956 TEST q(Data::Dumper->Dumpxs([$a], ['a'])), "XS \\x{9c10}"
962 $a = { map { ("$_$_$_", ++$i) } 'I'..'Q' };
980 TEST (q(Data::Dumper->new([$a])->Dump;),
981 'basic test without names: Dump()');
982 TEST (q(Data::Dumper->new([$a])->Dumpxs;),
983 'basic test without names: Dumpxs()')
989 $c = { map { (++$i, "$_$_$_") } 'I'..'Q' };
990 local $Data::Dumper::Sortkeys = \&sort199;
993 return [ sort { $b <=> $a } keys %$hash ];
1012 TEST q(Data::Dumper->new([$c])->Dump;), "sortkeys sub";
1013 TEST q(Data::Dumper->new([$c])->Dumpxs;), "sortkeys sub (XS)"
1019 $c = { map { (++$i, "$_$_$_") } 'I'..'Q' };
1020 $d = { reverse %$c };
1021 local $Data::Dumper::Sortkeys = \&sort205;
1025 $hash eq $c ? (sort { $a <=> $b } keys %$hash)
1026 : (reverse sort keys %$hash)
1059 TEST q(Data::Dumper->new([[$c, $d]])->Dump;), "more sortkeys sub";
1060 # the XS code does number values as strings
1061 $WANT =~ s/ (\d+)(,?)$/ '$1'$2/gm;
1062 TEST q(Data::Dumper->new([[$c, $d]])->Dumpxs;), "more sortkeys sub (XS)"
1067 local $Data::Dumper::Deparse = 1;
1068 local $Data::Dumper::Indent = 2;
1080 if(" $Config{'extensions'} " !~ m[ B ]) {
1081 SKIP_TEST "Perl configured without B module";
1083 TEST (q(Data::Dumper->new([{ foo => sub { print "foo"; } }])->Dump),
1084 'Deparse 1: Indent 2; Dump()');
1092 # The controls (bare numbers) are stored either as integers or floating point.
1093 # [depending on whether the tokeniser sees things like ".".
1094 # The peephole optimiser only runs for constant folding, not single constants,
1095 # so I already have some NVs, some IVs
1096 # The string versions are not. They are all PV
1098 # This is arguably all far too chummy with the implementation, but I really
1099 # want to ensure that we don't go wrong when flags on scalars get as side
1100 # effects of reading them.
1102 # These tests are actually testing the precise output of the current
1103 # implementation, so will most likely fail if the implementation changes,
1104 # even if the new implementation produces different but correct results.
1105 # It would be nice to test for wrong answers, but I can't see how to do that,
1106 # so instead I'm checking for unexpected answers. (ie -2 becoming "-2" is not
1107 # wrong, but I can't see an easy, reliable way to code that knowledge)
1109 # Numbers (seen by the tokeniser as numbers, stored as numbers.
1112 0, +1, -2, 3.0, +4.0, -5.0, 6.5, +7.5, -8.5,
1113 9, +10, -11, 12.0, +13.0, -14.0, 15.5, +16.25, -17.75,
1118 "0", "+1", "-2", "3.0", "+4.0", "-5.0", "6.5", "+7.5", "-8.5", " 9",
1119 " +10", " -11", " 12.0", " +13.0", " -14.0", " 15.5", " +16.25", " -17.75",
1122 # The perl code always does things the same way for numbers.
1123 $WANT_PL_N = <<'EOT';
1143 # The perl code knows that 0 and -2 stringify exactly back to the strings,
1144 # so it dumps them as numbers, not strings.
1145 $WANT_PL_S = <<'EOT';
1162 #$VAR17 = ' +16.25';
1163 #$VAR18 = ' -17.75';
1166 # The XS code differs.
1167 # These are the numbers as seen by the tokeniser. Constants aren't folded
1168 # (which makes IVs where possible) so values the tokeniser thought were
1169 # floating point are stored as NVs. The XS code outputs these as strings,
1170 # but as it has converted them from NVs, leading + signs will not be there.
1171 $WANT_XS_N = <<'EOT';
1192 # These are the strings as seen by the tokeniser. The XS code will output
1193 # these for all cases except where the scalar has been used in integer context
1194 $WANT_XS_S = <<'EOT';
1211 #$VAR17 = ' +16.25';
1212 #$VAR18 = ' -17.75';
1215 # These are the numbers as IV-ized by &
1216 # These will differ from WANT_XS_N because now IV flags will be set on all
1217 # values that were actually integer, and the XS code will then output these
1218 # as numbers not strings.
1219 $WANT_XS_I = <<'EOT';
1240 # Some of these tests will be redundant.
1241 @numbers_s = @numbers_i = @numbers_is = @numbers_n = @numbers_ns = @numbers_ni
1242 = @numbers_nis = @numbers;
1243 @strings_s = @strings_i = @strings_is = @strings_n = @strings_ns = @strings_ni
1244 = @strings_nis = @strings;
1245 # Use them in an integer context
1246 foreach (@numbers_i, @numbers_ni, @numbers_nis, @numbers_is,
1247 @strings_i, @strings_ni, @strings_nis, @strings_is) {
1248 my $b = sprintf "%d", $_;
1250 # Use them in a floating point context
1251 foreach (@numbers_n, @numbers_ni, @numbers_nis, @numbers_ns,
1252 @strings_n, @strings_ni, @strings_nis, @strings_ns) {
1253 my $b = sprintf "%e", $_;
1255 # Use them in a string context
1256 foreach (@numbers_s, @numbers_is, @numbers_nis, @numbers_ns,
1257 @strings_s, @strings_is, @strings_nis, @strings_ns) {
1258 my $b = sprintf "%s", $_;
1261 # use Devel::Peek; Dump ($_) foreach @vanilla_c;
1264 TEST q(Data::Dumper->new(\@numbers)->Dump), 'Numbers';
1265 TEST q(Data::Dumper->new(\@numbers_s)->Dump), 'Numbers PV';
1266 TEST q(Data::Dumper->new(\@numbers_i)->Dump), 'Numbers IV';
1267 TEST q(Data::Dumper->new(\@numbers_is)->Dump), 'Numbers IV,PV';
1268 TEST q(Data::Dumper->new(\@numbers_n)->Dump), 'Numbers NV';
1269 TEST q(Data::Dumper->new(\@numbers_ns)->Dump), 'Numbers NV,PV';
1270 TEST q(Data::Dumper->new(\@numbers_ni)->Dump), 'Numbers NV,IV';
1271 TEST q(Data::Dumper->new(\@numbers_nis)->Dump), 'Numbers NV,IV,PV';
1273 TEST q(Data::Dumper->new(\@strings)->Dump), 'Strings';
1274 TEST q(Data::Dumper->new(\@strings_s)->Dump), 'Strings PV';
1275 TEST q(Data::Dumper->new(\@strings_i)->Dump), 'Strings IV';
1276 TEST q(Data::Dumper->new(\@strings_is)->Dump), 'Strings IV,PV';
1277 TEST q(Data::Dumper->new(\@strings_n)->Dump), 'Strings NV';
1278 TEST q(Data::Dumper->new(\@strings_ns)->Dump), 'Strings NV,PV';
1279 TEST q(Data::Dumper->new(\@strings_ni)->Dump), 'Strings NV,IV';
1280 TEST q(Data::Dumper->new(\@strings_nis)->Dump), 'Strings NV,IV,PV';
1282 my $nv_preserves_uv = defined $Config{d_nv_preserves_uv};
1283 my $nv_preserves_uv_4bits = exists($Config{nv_preserves_uv_bits}) && $Config{nv_preserves_uv_bits} >= 4;
1285 TEST q(Data::Dumper->new(\@numbers)->Dumpxs), 'XS Numbers';
1286 TEST q(Data::Dumper->new(\@numbers_s)->Dumpxs), 'XS Numbers PV';
1287 if ($nv_preserves_uv || $nv_preserves_uv_4bits) {
1289 TEST q(Data::Dumper->new(\@numbers_i)->Dumpxs), 'XS Numbers IV';
1290 TEST q(Data::Dumper->new(\@numbers_is)->Dumpxs), 'XS Numbers IV,PV';
1292 SKIP_TEST "NV does not preserve 4bits";
1293 SKIP_TEST "NV does not preserve 4bits";
1296 TEST q(Data::Dumper->new(\@numbers_n)->Dumpxs), 'XS Numbers NV';
1297 TEST q(Data::Dumper->new(\@numbers_ns)->Dumpxs), 'XS Numbers NV,PV';
1298 if ($nv_preserves_uv || $nv_preserves_uv_4bits) {
1300 TEST q(Data::Dumper->new(\@numbers_ni)->Dumpxs), 'XS Numbers NV,IV';
1301 TEST q(Data::Dumper->new(\@numbers_nis)->Dumpxs), 'XS Numbers NV,IV,PV';
1303 SKIP_TEST "NV does not preserve 4bits";
1304 SKIP_TEST "NV does not preserve 4bits";
1308 TEST q(Data::Dumper->new(\@strings)->Dumpxs), 'XS Strings';
1309 TEST q(Data::Dumper->new(\@strings_s)->Dumpxs), 'XS Strings PV';
1310 # This one used to really mess up. New code actually emulates the .pm code
1312 TEST q(Data::Dumper->new(\@strings_i)->Dumpxs), 'XS Strings IV';
1313 TEST q(Data::Dumper->new(\@strings_is)->Dumpxs), 'XS Strings IV,PV';
1314 if ($nv_preserves_uv || $nv_preserves_uv_4bits) {
1316 TEST q(Data::Dumper->new(\@strings_n)->Dumpxs), 'XS Strings NV';
1317 TEST q(Data::Dumper->new(\@strings_ns)->Dumpxs), 'XS Strings NV,PV';
1319 SKIP_TEST "NV does not preserve 4bits";
1320 SKIP_TEST "NV does not preserve 4bits";
1322 # This one used to really mess up. New code actually emulates the .pm code
1324 TEST q(Data::Dumper->new(\@strings_ni)->Dumpxs), 'XS Strings NV,IV';
1325 TEST q(Data::Dumper->new(\@strings_nis)->Dumpxs), 'XS Strings NV,IV,PV';
1331 ## Perl code was using /...$/ and hence missing the \n.
1337 # Can't pad with # as the output has an embedded newline.
1338 local $Data::Dumper::Pad = "my ";
1339 TEST q(Data::Dumper->Dump(["42\n"])), "number with trailing newline";
1340 TEST q(Data::Dumper->Dumpxs(["42\n"])), "XS number with trailing newline"
1360 ## Perl code flips over at 10 digits.
1363 #$VAR2 = '1000000000';
1364 #$VAR3 = '9999999999';
1365 #$VAR4 = '10000000000';
1366 #$VAR5 = -999999999;
1367 #$VAR6 = '-1000000000';
1368 #$VAR7 = '-9999999999';
1369 #$VAR8 = '-10000000000';
1370 #$VAR9 = '4294967295';
1371 #$VAR10 = '4294967296';
1372 #$VAR11 = '-2147483648';
1373 #$VAR12 = '-2147483649';
1376 TEST q(Data::Dumper->Dump(\@a)), "long integers";
1379 ## XS code flips over at 11 characters ("-" is a char) or larger than int.
1380 if (~0 == 0xFFFFFFFF) {
1384 #$VAR2 = 1000000000;
1385 #$VAR3 = '9999999999';
1386 #$VAR4 = '10000000000';
1387 #$VAR5 = -999999999;
1388 #$VAR6 = '-1000000000';
1389 #$VAR7 = '-9999999999';
1390 #$VAR8 = '-10000000000';
1391 #$VAR9 = 4294967295;
1392 #$VAR10 = '4294967296';
1393 #$VAR11 = '-2147483648';
1394 #$VAR12 = '-2147483649';
1399 #$VAR2 = 1000000000;
1400 #$VAR3 = 9999999999;
1401 #$VAR4 = '10000000000';
1402 #$VAR5 = -999999999;
1403 #$VAR6 = '-1000000000';
1404 #$VAR7 = '-9999999999';
1405 #$VAR8 = '-10000000000';
1406 #$VAR9 = 4294967295;
1407 #$VAR10 = 4294967296;
1408 #$VAR11 = '-2147483648';
1409 #$VAR12 = '-2147483649';
1412 TEST q(Data::Dumper->Dumpxs(\@a)), "XS long integers";
1419 $b = "Bad. XS didn't escape dollar sign";
1421 $WANT = <<"EOT"; # Careful. This is '' string written inside "" here doc
1422 #\$VAR1 = '\$b\"\@\\\\\xB1';
1424 $a = "\$b\"\@\\\xB1\x{100}";
1426 TEST q(Data::Dumper->Dump([$a])), "utf8 flag with \" and \$";
1428 $WANT = <<'EOT'; # While this is "" string written inside "" here doc
1429 #$VAR1 = "\$b\"\@\\\x{b1}";
1431 TEST q(Data::Dumper->Dumpxs([$a])), "XS utf8 flag with \" and \$";
1434 $b = "Bad. XS didn't escape dollar sign";
1436 $WANT = <<"EOT"; # Careful. This is '' string written inside "" here doc
1437 #\$VAR1 = '\$b\"\@\\\\\xA3';
1440 $a = "\$b\"\@\\\xA3\x{100}";
1442 TEST q(Data::Dumper->Dump([$a])), "utf8 flag with \" and \$";
1444 $WANT = <<'EOT'; # While this is "" string written inside "" here doc
1445 #$VAR1 = "\$b\"\@\\\x{a3}";
1447 TEST q(Data::Dumper->Dumpxs([$a])), "XS utf8 flag with \" and \$";
1450 # XS used to produce "$b\"' which is 4 chars, not 3. [ie wrongly qq(\$b\\\")]
1456 $a = "\$b\"\x{100}";
1458 TEST q(Data::Dumper->Dump([$a])), "utf8 flag with \" and \$";
1460 TEST q(Data::Dumper->Dumpxs([$a])), "XS utf8 flag with \" and \$";
1464 # XS used to produce 'D'oh!' which is well, D'oh!
1465 # Andreas found this one, which in turn discovered the previous two.
1471 $a = "D'oh!\x{100}";
1473 TEST q(Data::Dumper->Dump([$a])), "utf8 flag with '";
1475 TEST q(Data::Dumper->Dumpxs([$a])), "XS utf8 flag with '";
1479 # Jarkko found that -Mutf8 caused some tests to fail. Turns out that there
1480 # was an otherwise untested code path in the XS for utf8 hash keys with purity
1488 # "\x{decaf}\x{decaf}\x{decaf}\x{decaf}" => do{my $o}
1490 #*::ping{HASH}->{"\x{decaf}\x{decaf}\x{decaf}\x{decaf}"} = *::ping{SCALAR};
1491 #%pong = %{*::ping{HASH}};
1493 local $Data::Dumper::Purity = 1;
1494 local $Data::Dumper::Sortkeys;
1496 %ping = (chr (0xDECAF) x 4 =>\$ping);
1497 for $Data::Dumper::Sortkeys (0, 1) {
1499 TEST (q(Data::Dumper->Dump([\\*ping, \\%ping], ['*ping', '*pong'])),
1500 "utf8: Purity 1: Sortkeys: Dump()");
1501 TEST (q(Data::Dumper->Dumpxs([\\*ping, \\%ping], ['*ping', '*pong'])),
1502 "utf8: Purity 1: Sortkeys: Dumpxs()")
1505 SKIP_TEST "Incomplete support for UTF-8 in old perls";
1506 SKIP_TEST "Incomplete support for UTF-8 in old perls";
1511 # XS for quotekeys==0 was not being defensive enough against utf8 flagged
1520 local $Data::Dumper::Quotekeys = 0;
1521 my $k = 'perl' . chr 256;
1523 %foo = ($k => 'rocks');
1525 TEST q(Data::Dumper->Dump([\\%foo])), "quotekeys == 0 for utf8 flagged ASCII";
1526 TEST q(Data::Dumper->Dumpxs([\\%foo])),
1527 "XS quotekeys == 0 for utf8 flagged ASCII" if $XS;
1540 TEST q(Data::Dumper->Dump([\@foo])), 'Richard Clamp, Message-Id: <20030104005247.GA27685@mirth.demon.co.uk>: Dump()';
1541 TEST q(Data::Dumper->Dumpxs([\@foo])), 'Richard Clamp, Message-Id: <20030104005247.GA27685@mirth.demon.co.uk>: Dumpxs()'if $XS;
1545 # Make sure $obj->Dumpxs returns the right thing in list context. This was
1546 # broken by the initial attempt to fix [perl #74170].
1550 TEST q(join " ", new Data::Dumper [[]],[] =>->Dumpxs),
1551 '$obj->Dumpxs in list context'
1556 $WANT = '\0\1\2\3\4\5\6\a\b\t\n\13\f\r\16\17\20\21\22\23\24\25\26\27\30\31\32\e\34\35\36\37 !\"#\$%&\'()*+,-./0123456789:;<=>?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377';
1557 $WANT = convert_to_native($WANT);
1564 $foo = [ join "", map chr, 0..255 ];
1565 local $Data::Dumper::Useqq = 1;
1566 TEST (q(Dumper($foo)), 'All latin1 characters: Dumper');
1567 TEST (q(Data::Dumper::DumperX($foo)), 'All latin1 characters: DumperX') if $XS;
1572 $WANT = '\0\1\2\3\4\5\6\a\b\t\n\13\f\r\16\17\20\21\22\23\24\25\26\27\30\31\32\e\34\35\36\37 !\"#\$%&\'()*+,-./0123456789:;<=>?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177\x{80}\x{81}\x{82}\x{83}\x{84}\x{85}\x{86}\x{87}\x{88}\x{89}\x{8a}\x{8b}\x{8c}\x{8d}\x{8e}\x{8f}\x{90}\x{91}\x{92}\x{93}\x{94}\x{95}\x{96}\x{97}\x{98}\x{99}\x{9a}\x{9b}\x{9c}\x{9d}\x{9e}\x{9f}\x{a0}\x{a1}\x{a2}\x{a3}\x{a4}\x{a5}\x{a6}\x{a7}\x{a8}\x{a9}\x{aa}\x{ab}\x{ac}\x{ad}\x{ae}\x{af}\x{b0}\x{b1}\x{b2}\x{b3}\x{b4}\x{b5}\x{b6}\x{b7}\x{b8}\x{b9}\x{ba}\x{bb}\x{bc}\x{bd}\x{be}\x{bf}\x{c0}\x{c1}\x{c2}\x{c3}\x{c4}\x{c5}\x{c6}\x{c7}\x{c8}\x{c9}\x{ca}\x{cb}\x{cc}\x{cd}\x{ce}\x{cf}\x{d0}\x{d1}\x{d2}\x{d3}\x{d4}\x{d5}\x{d6}\x{d7}\x{d8}\x{d9}\x{da}\x{db}\x{dc}\x{dd}\x{de}\x{df}\x{e0}\x{e1}\x{e2}\x{e3}\x{e4}\x{e5}\x{e6}\x{e7}\x{e8}\x{e9}\x{ea}\x{eb}\x{ec}\x{ed}\x{ee}\x{ef}\x{f0}\x{f1}\x{f2}\x{f3}\x{f4}\x{f5}\x{f6}\x{f7}\x{f8}\x{f9}\x{fa}\x{fb}\x{fc}\x{fd}\x{fe}\x{ff}\x{20ac}';
1573 $WANT = convert_to_native($WANT);
1580 $foo = [ join "", map chr, 0..255, 0x20ac ];
1581 local $Data::Dumper::Useqq = 1;
1583 print "not ok " . (++$TNUM) . " # TODO - fails under 5.6\n" for 1..3;
1586 TEST q(Dumper($foo)),
1587 'All latin1 characters with utf8 flag including a wide character: Dumper';
1589 TEST (q(Data::Dumper::DumperX($foo)),
1590 'All latin1 characters with utf8 flag including a wide character: DumperX')
1596 # If XS cannot load, the pure-Perl version cannot deparse vstrings with
1597 # underscores properly. In 5.8.0, vstrings are just strings.
1598 my $no_vstrings = <<'NOVSTRINGS';
1604 my $ABC_native = chr(65) . chr(66) . chr(67);
1605 my $vstrings_corr = <<VSTRINGS_CORRECT;
1607 #\$b = \\v65.66.067;
1608 #\$c = \\v65.66.6_7;
1609 #\$d = \\'$ABC_native';
1611 $WANT = $] <= 5.0080001
1617 \($] < 5.007 ? v65.66.67 : eval 'v65.66.067'),
1622 TEST q(Data::Dumper->Dump(\@::_v, [qw(a b c d)])), 'vstrings';
1623 TEST q(Data::Dumper->Dumpxs(\@::_v, [qw(a b c d)])), 'xs vstrings'
1626 else { # Skip tests before 5.10. vstrings considered funny before
1627 SKIP_TEST "vstrings considered funny before 5.10.0";
1628 SKIP_TEST "vstrings considered funny before 5.10.0 (XS)"
1635 # [perl #107372] blessed overloaded globs
1637 #$VAR1 = bless( \*::finkle, 'overtest' );
1641 use overload fallback=>1, q\""\=>sub{"oaoaa"};
1643 TEST q(Data::Dumper->Dump([bless \*finkle, "overtest"])),
1644 'blessed overloaded globs';
1645 TEST q(Data::Dumper->Dumpxs([\*finkle])), 'blessed overloaded globs (xs)'
1650 # [perl #74798] uncovered behaviour
1654 local $Data::Dumper::Useqq = 1;
1655 TEST q(Data::Dumper->Dump(["\x000"])),
1656 "\\ octal followed by digit";
1657 TEST q(Data::Dumper->Dumpxs(["\x000"])), '\\ octal followed by digit (xs)'
1661 #$VAR1 = "\x{100}\0000";
1663 local $Data::Dumper::Useqq = 1;
1664 TEST q(Data::Dumper->Dump(["\x{100}\x000"])),
1665 "\\ octal followed by digit unicode";
1666 TEST q(Data::Dumper->Dumpxs(["\x{100}\x000"])), '\\ octal followed by digit unicode (xs)'
1671 #$VAR1 = "\0\x{660}";
1673 TEST q(Data::Dumper->Dump(["\\x00\\x{0660}"])),
1674 "\\ octal followed by unicode digit";
1675 TEST q(Data::Dumper->Dumpxs(["\\x00\\x{0660}"])), '\\ octal followed by unicode digit (xs)'
1678 # [perl #118933 - handling of digits
1686 #$VAR7 = "1234567890";
1688 TEST q(Data::Dumper->Dump([0, 1, 90, -10, "010", "112345678", "1234567890" ])),
1689 "numbers and number-like scalars";
1691 TEST q(Data::Dumper->Dumpxs([0, 1, 90, -10, "010", "112345678", "1234567890" ])),
1692 "numbers and number-like scalars"
1698 # re::regexp_pattern was moved to universal.c in v5.10.0-252-g192c1e2
1699 # and apparently backported to maint-5.10
1700 $WANT = $] > 5.010 ? <<'NEW' : <<'OLD';
1704 #$VAR1 = qr/(?-xism:abc)/;
1705 #$VAR2 = qr/(?i-xsm:abc)/;
1707 TEST q(Data::Dumper->Dump([ qr/abc/, qr/abc/i ])), "qr//";
1708 TEST q(Data::Dumper->Dumpxs([ qr/abc/, qr/abc/i ])), "qr// xs"
1716 #*a = sub { "DUMMY" };
1720 TEST q(Data::Dumper->new([ \&foo, \\&foo ], [ "*a", "b" ])->Dump), "name of code in *foo";
1721 TEST q(Data::Dumper->new([ \&foo, \\&foo ], [ "*a", "b" ])->Dumpxs), "name of code in *foo xs"