1b39c5158Smillert#!./perl -w
2b39c5158Smillert#
3b39c5158Smillert# testsuite for Data::Dumper
4b39c5158Smillert#
5b39c5158Smillert
6eac174f2Safresh1use strict;
7eac174f2Safresh1use warnings;
8b39c5158Smillert
9b39c5158Smillertuse Data::Dumper;
10b39c5158Smillertuse Config;
11eac174f2Safresh1use Test::More;
12b39c5158Smillert
13eac174f2Safresh1# Since Perl 5.8.1 because otherwise hash ordering is really random.
14eac174f2Safresh1$Data::Dumper::Sortkeys = 1;
15b39c5158Smillert$Data::Dumper::Pad = "#";
16eac174f2Safresh1
17b39c5158Smillertmy $XS;
18eac174f2Safresh1
19eac174f2Safresh1# Force Data::Dumper::Dump to use perl. We test Dumpxs explicitly by calling
20eac174f2Safresh1# it direct. Out here it lets us knobble the next if to test that the perl
21eac174f2Safresh1# only tests do work (and count correctly)
22eac174f2Safresh1$Data::Dumper::Useperl = 1;
23eac174f2Safresh1if (defined &Data::Dumper::Dumpxs) {
24eac174f2Safresh1    print "### XS extension loaded, will run XS tests\n";
25eac174f2Safresh1    $XS = 1;
26eac174f2Safresh1}
27eac174f2Safresh1else {
28eac174f2Safresh1    print "### XS extensions not loaded, will NOT run XS tests\n";
29eac174f2Safresh1    $XS = 0;
30eac174f2Safresh1}
31eac174f2Safresh1
32eac174f2Safresh1our ( @a, $c, $d, $foo, @foo, %foo, @globs, $v, $ping, %ping );
33eac174f2Safresh1our ( @dogs, %kennel, $mutts );
34eac174f2Safresh1
35eac174f2Safresh1our ( @numbers, @strings );
36eac174f2Safresh1our ( @numbers_s, @numbers_i, @numbers_is, @numbers_n, @numbers_ns, @numbers_ni, @numbers_nis );
37eac174f2Safresh1our ( @strings_s, @strings_i, @strings_is, @strings_n, @strings_ns, @strings_ni, @strings_nis );
38b39c5158Smillert
39b46d8ef2Safresh1# Perl 5.16 was the first version that correctly handled Unicode in typeglob
40b46d8ef2Safresh1# names. Tests for how globs are dumped must revise their expectations
41b46d8ef2Safresh1# downwards when run on earlier Perls.
42b46d8ef2Safresh1sub change_glob_expectation {
43b46d8ef2Safresh1    my ($input) = @_;
44b46d8ef2Safresh1    if ($] < 5.016) {
45b46d8ef2Safresh1        $input =~ s<\\x\{([0-9a-f]+)\}>{
46b46d8ef2Safresh1            my $s = chr hex $1;
47b46d8ef2Safresh1            utf8::encode($s);
48b46d8ef2Safresh1            join '', map sprintf('\\%o', ord), split //, $s;
49b46d8ef2Safresh1        }ge;
50b46d8ef2Safresh1    }
51b46d8ef2Safresh1    return $input;
52b46d8ef2Safresh1}
53b46d8ef2Safresh1
54eac174f2Safresh1sub convert_to_native {
55b8851fccSafresh1    my $input = shift;
56b8851fccSafresh1
57b8851fccSafresh1    my @output;
58b8851fccSafresh1
59b8851fccSafresh1    # The input should always be one of the following constructs
60b8851fccSafresh1    while ($input =~ m/ ( \\ [0-7]+ )
61b8851fccSafresh1                      | ( \\ x \{ [[:xdigit:]]+ } )
62b8851fccSafresh1                      | ( \\ . )
63b8851fccSafresh1                      | ( . ) /gx)
64b8851fccSafresh1    {
65b8851fccSafresh1        #print STDERR __LINE__, ": ", $&, "\n";
66b8851fccSafresh1        my $index;
67b8851fccSafresh1        my $replacement;
68b8851fccSafresh1        if (defined $4) {       # Literal
69b8851fccSafresh1            $index = ord $4;
70b8851fccSafresh1            $replacement = $4;
71b8851fccSafresh1        }
72b8851fccSafresh1        elsif (defined $3) {    # backslash escape
73b8851fccSafresh1            $index = ord eval "\"$3\"";
74b8851fccSafresh1            $replacement = $3;
75b8851fccSafresh1        }
76b8851fccSafresh1        elsif (defined $2) {    # Hex
77b8851fccSafresh1            $index = utf8::unicode_to_native(ord eval "\"$2\"");
78b8851fccSafresh1
79b8851fccSafresh1            # But low hex numbers are always in octal.  These are all
80eac174f2Safresh1            # controls.  The outlier \c? control is also in octal.
81eac174f2Safresh1            my $format = ($index < ord(" ") || $index == ord("\c?"))
82b8851fccSafresh1                         ? "\\%o"
83b8851fccSafresh1                         : "\\x{%x}";
84b8851fccSafresh1            $replacement = sprintf($format, $index);
85b8851fccSafresh1        }
86b8851fccSafresh1        elsif (defined $1) {    # Octal
87b8851fccSafresh1            $index = utf8::unicode_to_native(ord eval "\"$1\"");
88b8851fccSafresh1            $replacement = sprintf("\\%o", $index);
89b8851fccSafresh1        }
90b8851fccSafresh1        else {
91b8851fccSafresh1            die "Unexpected match in convert_to_native()";
92b8851fccSafresh1        }
93b8851fccSafresh1
94b8851fccSafresh1        if (defined $output[$index]) {
95b8851fccSafresh1            print STDERR "ordinal $index already has '$output[$index]'; skipping '$replacement'\n";
96b8851fccSafresh1            next;
97b8851fccSafresh1        }
98b8851fccSafresh1
99b8851fccSafresh1        $output[$index] = $replacement;
100b8851fccSafresh1    }
101b8851fccSafresh1
102b8851fccSafresh1    return join "", grep { defined } @output;
103b8851fccSafresh1}
104b8851fccSafresh1
105b39c5158Smillertsub TEST {
106eac174f2Safresh1    my ($string, $desc, $want) = @_;
107eac174f2Safresh1    Carp::confess("Tests must have a description")
108eac174f2Safresh1            unless $desc;
109b39c5158Smillert
110eac174f2Safresh1    local $Test::Builder::Level = $Test::Builder::Level + 1;
111eac174f2Safresh1 SKIP: {
112eac174f2Safresh1        my $have = do {
113eac174f2Safresh1            no strict;
114eac174f2Safresh1            eval $string;
115eac174f2Safresh1        };
116eac174f2Safresh1        my $error = $@;
117b39c5158Smillert
118eac174f2Safresh1        if (defined $error && length $error) {
119eac174f2Safresh1            is($error, "", "$desc set \$@");
120eac174f2Safresh1            skip('No point in running eval after an error', 2);
121b39c5158Smillert        }
122b39c5158Smillert
123eac174f2Safresh1        $have =~ s/([A-Z]+)\(0x[0-9a-f]+\)/$1(0xdeadbeef)/g
124eac174f2Safresh1            if $want =~ /deadbeef/;
125eac174f2Safresh1        is($have, $want, $desc);
126eac174f2Safresh1
127eac174f2Safresh1        {
128eac174f2Safresh1            no strict;
129eac174f2Safresh1            eval "$have";
130b39c5158Smillert        }
131b39c5158Smillert
132eac174f2Safresh1        is($@, "", "$desc - output did not eval")
133eac174f2Safresh1            or skip('No point in restesting if output failed eval');
134b8851fccSafresh1
135eac174f2Safresh1        $have = do {
136eac174f2Safresh1            no strict;
137eac174f2Safresh1            eval $string;
138eac174f2Safresh1        };
139eac174f2Safresh1        $error = $@;
140eac174f2Safresh1
141eac174f2Safresh1        if (defined $error && length $error) {
142eac174f2Safresh1            is($error, "", "$desc after eval set \$@");
143b39c5158Smillert        }
144b39c5158Smillert        else {
145eac174f2Safresh1            $have =~ s/([A-Z]+)\(0x[0-9a-f]+\)/$1(0xdeadbeef)/g
146eac174f2Safresh1                if $want =~ /deadbeef/;
147eac174f2Safresh1            is($have, $want, "$desc after eval");
148eac174f2Safresh1        }
149eac174f2Safresh1    }
150b39c5158Smillert}
151b39c5158Smillert
152eac174f2Safresh1sub SKIP_BOTH {
153eac174f2Safresh1    my $reason = shift;
154eac174f2Safresh1 SKIP: {
155eac174f2Safresh1        skip($reason, $XS ? 6 : 3);
156eac174f2Safresh1    }
157eac174f2Safresh1}
158b39c5158Smillert
159eac174f2Safresh1# It's more reliable to match (and substitute) on 'Dumpxs' than 'Dump'
160eac174f2Safresh1# (the latter is a substring of many things), but as historically we've tested
161eac174f2Safresh1# "pure perl" then "XS" it seems better to have $want_xs as an optional
162eac174f2Safresh1# parameter.
163eac174f2Safresh1sub TEST_BOTH {
164eac174f2Safresh1    my ($testcase, $desc, $want, $want_xs, $skip_xs) = @_;
165eac174f2Safresh1    $want_xs = $want
166eac174f2Safresh1        unless defined $want_xs;
167eac174f2Safresh1    my $desc_pp = $desc;
168eac174f2Safresh1    my $testcase_pp = $testcase;
169eac174f2Safresh1    Carp::confess("Testcase must contain ->Dumpxs or DumperX")
170eac174f2Safresh1            unless $testcase_pp =~ s/->Dumpxs\b/->Dump/g
171eac174f2Safresh1            || $testcase_pp =~ s/\bDumperX\b/Dumper/g;
172eac174f2Safresh1    unless ($desc_pp =~ s/Dumpxs/Dump/ || $desc_pp =~ s/\bDumperX\b/Dumper/) {
173eac174f2Safresh1        $desc .= ', XS';
174eac174f2Safresh1    }
175eac174f2Safresh1
176eac174f2Safresh1    local $Test::Builder::Level = $Test::Builder::Level + 1;
177eac174f2Safresh1    TEST($testcase_pp, $desc_pp, $want);
178eac174f2Safresh1    return
179eac174f2Safresh1        unless $XS;
180eac174f2Safresh1    if ($skip_xs) {
181eac174f2Safresh1    SKIP: {
182eac174f2Safresh1            skip($skip_xs, 3);
183eac174f2Safresh1        }
184eac174f2Safresh1    }
185eac174f2Safresh1    else {
186eac174f2Safresh1        TEST($testcase, $desc, $want_xs);
187eac174f2Safresh1    }
188eac174f2Safresh1}
189eac174f2Safresh1
190eac174f2Safresh1
191b39c5158Smillert#############
192b39c5158Smillert
193eac174f2Safresh1my @c = ('c');
194b39c5158Smillert$c = \@c;
195eac174f2Safresh1$b = {};          # FIXME - use another variable name
196eac174f2Safresh1$a = [1, $b, $c]; # FIXME - use another variable name
197b39c5158Smillert$b->{a} = $a;
198b39c5158Smillert$b->{b} = $a->[1];
199b39c5158Smillert$b->{c} = $a->[2];
200b39c5158Smillert
201b8851fccSafresh1#############
202b39c5158Smillert##
203eac174f2Safresh1my $want = <<'EOT';
204b39c5158Smillert#$a = [
205b39c5158Smillert#       1,
206b39c5158Smillert#       {
207b39c5158Smillert#         'a' => $a,
208b39c5158Smillert#         'b' => $a->[1],
209b39c5158Smillert#         'c' => [
210b39c5158Smillert#                  'c'
211b39c5158Smillert#                ]
212b39c5158Smillert#       },
213b39c5158Smillert#       $a->[1]{'c'}
214b39c5158Smillert#     ];
215b39c5158Smillert#$b = $a->[1];
216b39c5158Smillert#$6 = $a->[1]{'c'};
217b39c5158SmillertEOT
218b39c5158Smillert
219eac174f2Safresh1TEST_BOTH(q(Data::Dumper->Dumpxs([$a,$b,$c], [qw(a b), 6])),
220eac174f2Safresh1          'basic test with names: Dumpxs()',
221eac174f2Safresh1          $want);
222b39c5158Smillert
22391f110e0Safresh1SCOPE: {
22491f110e0Safresh1    local $Data::Dumper::Sparseseen = 1;
225eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->Dumpxs([$a,$b,$c], [qw(a b), 6])),
226eac174f2Safresh1              'Sparseseen with names: Dumpxs()',
227eac174f2Safresh1              $want);
22891f110e0Safresh1}
229b39c5158Smillert
230b8851fccSafresh1#############
231b39c5158Smillert##
232eac174f2Safresh1$want = <<'EOT';
233b39c5158Smillert#@a = (
234b39c5158Smillert#       1,
235b39c5158Smillert#       {
236b39c5158Smillert#         'a' => [],
237b39c5158Smillert#         'b' => {},
238b39c5158Smillert#         'c' => [
239b39c5158Smillert#                  'c'
240b39c5158Smillert#                ]
241b39c5158Smillert#       },
242b39c5158Smillert#       []
243b39c5158Smillert#     );
244b39c5158Smillert#$a[1]{'a'} = \@a;
245b39c5158Smillert#$a[1]{'b'} = $a[1];
246b39c5158Smillert#$a[2] = $a[1]{'c'};
247b39c5158Smillert#$b = $a[1];
248b39c5158SmillertEOT
249b39c5158Smillert
250b39c5158Smillert$Data::Dumper::Purity = 1;         # fill in the holes for eval
251eac174f2Safresh1TEST_BOTH(q(Data::Dumper->Dumpxs([$a, $b], [qw(*a b)])),
252eac174f2Safresh1          'Purity: basic test with dereferenced array: Dumpxs()',
253eac174f2Safresh1          $want);
254b39c5158Smillert
25591f110e0Safresh1SCOPE: {
25691f110e0Safresh1  local $Data::Dumper::Sparseseen = 1;
257eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([$a, $b], [qw(*a b)])),
258eac174f2Safresh1            'Purity: Sparseseen with dereferenced array: Dumpxs()',
259eac174f2Safresh1            $want);
26091f110e0Safresh1}
26191f110e0Safresh1
262b8851fccSafresh1#############
263b39c5158Smillert##
264eac174f2Safresh1$want = <<'EOT';
265b39c5158Smillert#%b = (
266b39c5158Smillert#       'a' => [
267b39c5158Smillert#                1,
268b39c5158Smillert#                {},
269b39c5158Smillert#                [
270b39c5158Smillert#                  'c'
271b39c5158Smillert#                ]
272b39c5158Smillert#              ],
273b39c5158Smillert#       'b' => {},
274b39c5158Smillert#       'c' => []
275b39c5158Smillert#     );
276b39c5158Smillert#$b{'a'}[1] = \%b;
277b39c5158Smillert#$b{'b'} = \%b;
278b39c5158Smillert#$b{'c'} = $b{'a'}[2];
279b39c5158Smillert#$a = $b{'a'};
280b39c5158SmillertEOT
281b39c5158Smillert
282eac174f2Safresh1TEST_BOTH(q(Data::Dumper->Dumpxs([$b, $a], [qw(*b a)])),
283eac174f2Safresh1          'basic test with dereferenced hash: Dumpxs()',
284eac174f2Safresh1          $want);
285b39c5158Smillert
286b8851fccSafresh1#############
287b39c5158Smillert##
288eac174f2Safresh1$want = <<'EOT';
289b39c5158Smillert#$a = [
290b39c5158Smillert#  1,
291b39c5158Smillert#  {
292b39c5158Smillert#    'a' => [],
293b39c5158Smillert#    'b' => {},
294b39c5158Smillert#    'c' => []
295b39c5158Smillert#  },
296b39c5158Smillert#  []
297b39c5158Smillert#];
298b39c5158Smillert#$a->[1]{'a'} = $a;
299b39c5158Smillert#$a->[1]{'b'} = $a->[1];
300b39c5158Smillert#$a->[1]{'c'} = \@c;
301b39c5158Smillert#$a->[2] = \@c;
302b39c5158Smillert#$b = $a->[1];
303b39c5158SmillertEOT
304b39c5158Smillert
305b39c5158Smillert$Data::Dumper::Indent = 1;
306eac174f2Safresh1TEST_BOTH(q{
307b39c5158Smillert            $d = Data::Dumper->new([$a,$b], [qw(a b)]);
308b39c5158Smillert            $d->Seen({'*c' => $c});
309b39c5158Smillert            $d->Dumpxs;
310eac174f2Safresh1           }, 'Indent: Seen: Dumpxs()',
311eac174f2Safresh1          $want);
312b39c5158Smillert
313b8851fccSafresh1#############
314b39c5158Smillert##
315eac174f2Safresh1$want = <<'EOT';
316b39c5158Smillert#$a = [
317b39c5158Smillert#       #0
318b39c5158Smillert#       1,
319b39c5158Smillert#       #1
320b39c5158Smillert#       {
321b39c5158Smillert#         a => $a,
322b39c5158Smillert#         b => $a->[1],
323b39c5158Smillert#         c => [
324b39c5158Smillert#                #0
325b39c5158Smillert#                'c'
326b39c5158Smillert#              ]
327b39c5158Smillert#       },
328b39c5158Smillert#       #2
329b39c5158Smillert#       $a->[1]{c}
330b39c5158Smillert#     ];
331b39c5158Smillert#$b = $a->[1];
332b39c5158SmillertEOT
333b39c5158Smillert
334b39c5158Smillert$d->Indent(3);
335b39c5158Smillert$d->Purity(0)->Quotekeys(0);
336eac174f2Safresh1TEST_BOTH(q( $d->Reset; $d->Dumpxs ),
337eac174f2Safresh1          'Indent(3): Purity(0)->Quotekeys(0): Dumpxs()',
338eac174f2Safresh1          $want);
339b39c5158Smillert
340b8851fccSafresh1#############
341b39c5158Smillert##
342eac174f2Safresh1$want = <<'EOT';
343b39c5158Smillert#$VAR1 = [
344b39c5158Smillert#  1,
345b39c5158Smillert#  {
346b39c5158Smillert#    'a' => [],
347b39c5158Smillert#    'b' => {},
348b39c5158Smillert#    'c' => [
349b39c5158Smillert#      'c'
350b39c5158Smillert#    ]
351b39c5158Smillert#  },
352b39c5158Smillert#  []
353b39c5158Smillert#];
354b39c5158Smillert#$VAR1->[1]{'a'} = $VAR1;
355b39c5158Smillert#$VAR1->[1]{'b'} = $VAR1->[1];
356b39c5158Smillert#$VAR1->[2] = $VAR1->[1]{'c'};
357b39c5158SmillertEOT
358b39c5158Smillert
359eac174f2Safresh1TEST_BOTH(q(Data::Dumper::DumperX($a)),
360eac174f2Safresh1          'DumperX',
361eac174f2Safresh1          $want);
362b39c5158Smillert
363b8851fccSafresh1#############
364b39c5158Smillert##
365eac174f2Safresh1$want = <<'EOT';
366b39c5158Smillert#[
367b39c5158Smillert#  1,
368b39c5158Smillert#  {
369b39c5158Smillert#    a => $VAR1,
370b39c5158Smillert#    b => $VAR1->[1],
371b39c5158Smillert#    c => [
372b39c5158Smillert#      'c'
373b39c5158Smillert#    ]
374b39c5158Smillert#  },
375b39c5158Smillert#  $VAR1->[1]{c}
376b39c5158Smillert#]
377b39c5158SmillertEOT
378b39c5158Smillert
379b39c5158Smillert{
380b39c5158Smillert  local $Data::Dumper::Purity = 0;
381b39c5158Smillert  local $Data::Dumper::Quotekeys = 0;
382b39c5158Smillert  local $Data::Dumper::Terse = 1;
383eac174f2Safresh1  TEST_BOTH(q(Data::Dumper::DumperX($a)),
384eac174f2Safresh1            'Purity 0: Quotekeys 0: Terse 1: DumperX',
385eac174f2Safresh1            $want);
386b39c5158Smillert}
387b39c5158Smillert
388b8851fccSafresh1#############
389b39c5158Smillert##
390eac174f2Safresh1$want = <<'EOT';
391b39c5158Smillert#$VAR1 = {
392b39c5158Smillert#  "abc\0'\efg" => "mno\0",
393b39c5158Smillert#  "reftest" => \\1
394b39c5158Smillert#};
395b39c5158SmillertEOT
396b39c5158Smillert
397b39c5158Smillert$foo = { "abc\000\'\efg" => "mno\000",
398b39c5158Smillert         "reftest" => \\1,
399b39c5158Smillert       };
400b39c5158Smillert{
401b39c5158Smillert  local $Data::Dumper::Useqq = 1;
402eac174f2Safresh1  TEST_BOTH(q(Data::Dumper::DumperX($foo)),
403eac174f2Safresh1            'Useqq: DumperX',
404eac174f2Safresh1            $want);
405b39c5158Smillert}
406b39c5158Smillert
407b39c5158Smillert#############
408b39c5158Smillert#############
409b39c5158Smillert
410b39c5158Smillert{
411b39c5158Smillert  package main;
412b39c5158Smillert  use Data::Dumper;
413b39c5158Smillert  $foo = 5;
414b39c5158Smillert  @foo = (-10,\*foo);
415b39c5158Smillert  %foo = (a=>1,b=>\$foo,c=>\@foo);
416b39c5158Smillert  $foo{d} = \%foo;
417b39c5158Smillert  $foo[2] = \%foo;
418b39c5158Smillert
419b8851fccSafresh1#############
420b39c5158Smillert##
421eac174f2Safresh1  my $want = <<'EOT';
422b39c5158Smillert#$foo = \*::foo;
423b39c5158Smillert#*::foo = \5;
424b39c5158Smillert#*::foo = [
425b39c5158Smillert#           #0
426b39c5158Smillert#           -10,
427b39c5158Smillert#           #1
428b39c5158Smillert#           do{my $o},
429b39c5158Smillert#           #2
430b39c5158Smillert#           {
431b39c5158Smillert#             'a' => 1,
432b39c5158Smillert#             'b' => do{my $o},
433b39c5158Smillert#             'c' => [],
434b39c5158Smillert#             'd' => {}
435b39c5158Smillert#           }
436b39c5158Smillert#         ];
437b39c5158Smillert#*::foo{ARRAY}->[1] = $foo;
438b39c5158Smillert#*::foo{ARRAY}->[2]{'b'} = *::foo{SCALAR};
439b39c5158Smillert#*::foo{ARRAY}->[2]{'c'} = *::foo{ARRAY};
440b39c5158Smillert#*::foo{ARRAY}->[2]{'d'} = *::foo{ARRAY}->[2];
441b39c5158Smillert#*::foo = *::foo{ARRAY}->[2];
442b39c5158Smillert#@bar = @{*::foo{ARRAY}};
443b39c5158Smillert#%baz = %{*::foo{ARRAY}->[2]};
444b39c5158SmillertEOT
445b39c5158Smillert
446b39c5158Smillert  $Data::Dumper::Purity = 1;
447b39c5158Smillert  $Data::Dumper::Indent = 3;
448eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([\\*foo, \\@foo, \\%foo], ['*foo', '*bar', '*baz'])),
449eac174f2Safresh1            'Purity 1: Indent 3: Dumpxs()',
450eac174f2Safresh1            $want);
451b39c5158Smillert
452b8851fccSafresh1#############
453b39c5158Smillert##
454eac174f2Safresh1  $want = <<'EOT';
455b39c5158Smillert#$foo = \*::foo;
456b39c5158Smillert#*::foo = \5;
457b39c5158Smillert#*::foo = [
458b39c5158Smillert#  -10,
459b39c5158Smillert#  do{my $o},
460b39c5158Smillert#  {
461b39c5158Smillert#    'a' => 1,
462b39c5158Smillert#    'b' => do{my $o},
463b39c5158Smillert#    'c' => [],
464b39c5158Smillert#    'd' => {}
465b39c5158Smillert#  }
466b39c5158Smillert#];
467b39c5158Smillert#*::foo{ARRAY}->[1] = $foo;
468b39c5158Smillert#*::foo{ARRAY}->[2]{'b'} = *::foo{SCALAR};
469b39c5158Smillert#*::foo{ARRAY}->[2]{'c'} = *::foo{ARRAY};
470b39c5158Smillert#*::foo{ARRAY}->[2]{'d'} = *::foo{ARRAY}->[2];
471b39c5158Smillert#*::foo = *::foo{ARRAY}->[2];
472b39c5158Smillert#$bar = *::foo{ARRAY};
473b39c5158Smillert#$baz = *::foo{ARRAY}->[2];
474b39c5158SmillertEOT
475b39c5158Smillert
476b39c5158Smillert  $Data::Dumper::Indent = 1;
477eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([\\*foo, \\@foo, \\%foo], ['foo', 'bar', 'baz'])),
478eac174f2Safresh1            'Purity 1: Indent 1: Dumpxs()',
479eac174f2Safresh1            $want);
480b39c5158Smillert
481b8851fccSafresh1#############
482b39c5158Smillert##
483eac174f2Safresh1  $want = <<'EOT';
484b39c5158Smillert#@bar = (
485b39c5158Smillert#  -10,
486b39c5158Smillert#  \*::foo,
487b39c5158Smillert#  {}
488b39c5158Smillert#);
489b39c5158Smillert#*::foo = \5;
490b39c5158Smillert#*::foo = \@bar;
491b39c5158Smillert#*::foo = {
492b39c5158Smillert#  'a' => 1,
493b39c5158Smillert#  'b' => do{my $o},
494b39c5158Smillert#  'c' => [],
495b39c5158Smillert#  'd' => {}
496b39c5158Smillert#};
497b39c5158Smillert#*::foo{HASH}->{'b'} = *::foo{SCALAR};
498b39c5158Smillert#*::foo{HASH}->{'c'} = \@bar;
499b39c5158Smillert#*::foo{HASH}->{'d'} = *::foo{HASH};
500b39c5158Smillert#$bar[2] = *::foo{HASH};
501b39c5158Smillert#%baz = %{*::foo{HASH}};
502b39c5158Smillert#$foo = $bar[1];
503b39c5158SmillertEOT
504b39c5158Smillert
505eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([\\@foo, \\%foo, \\*foo], ['*bar', '*baz', '*foo'])),
506eac174f2Safresh1            'array|hash|glob dereferenced: Dumpxs()',
507eac174f2Safresh1            $want);
508b39c5158Smillert
509b8851fccSafresh1#############
510b39c5158Smillert##
511eac174f2Safresh1  $want = <<'EOT';
512b39c5158Smillert#$bar = [
513b39c5158Smillert#  -10,
514b39c5158Smillert#  \*::foo,
515b39c5158Smillert#  {}
516b39c5158Smillert#];
517b39c5158Smillert#*::foo = \5;
518b39c5158Smillert#*::foo = $bar;
519b39c5158Smillert#*::foo = {
520b39c5158Smillert#  'a' => 1,
521b39c5158Smillert#  'b' => do{my $o},
522b39c5158Smillert#  'c' => [],
523b39c5158Smillert#  'd' => {}
524b39c5158Smillert#};
525b39c5158Smillert#*::foo{HASH}->{'b'} = *::foo{SCALAR};
526b39c5158Smillert#*::foo{HASH}->{'c'} = $bar;
527b39c5158Smillert#*::foo{HASH}->{'d'} = *::foo{HASH};
528b39c5158Smillert#$bar->[2] = *::foo{HASH};
529b39c5158Smillert#$baz = *::foo{HASH};
530b39c5158Smillert#$foo = $bar->[1];
531b39c5158SmillertEOT
532b39c5158Smillert
533eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([\\@foo, \\%foo, \\*foo], ['bar', 'baz', 'foo'])),
534eac174f2Safresh1            'array|hash|glob: not dereferenced: Dumpxs()',
535eac174f2Safresh1            $want);
536b39c5158Smillert
537b8851fccSafresh1#############
538b39c5158Smillert##
539eac174f2Safresh1  $want = <<'EOT';
540b39c5158Smillert#$foo = \*::foo;
541b39c5158Smillert#@bar = (
542b39c5158Smillert#  -10,
543b39c5158Smillert#  $foo,
544b39c5158Smillert#  {
545b39c5158Smillert#    a => 1,
546b39c5158Smillert#    b => \5,
547b39c5158Smillert#    c => \@bar,
548b39c5158Smillert#    d => $bar[2]
549b39c5158Smillert#  }
550b39c5158Smillert#);
551b39c5158Smillert#%baz = %{$bar[2]};
552b39c5158SmillertEOT
553b39c5158Smillert
554b39c5158Smillert  $Data::Dumper::Purity = 0;
555b39c5158Smillert  $Data::Dumper::Quotekeys = 0;
556eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([\\*foo, \\@foo, \\%foo], ['*foo', '*bar', '*baz'])),
557eac174f2Safresh1            'Purity 0: Quotekeys 0: dereferenced: Dumpxs',
558eac174f2Safresh1            $want);
559b39c5158Smillert
560b8851fccSafresh1#############
561b39c5158Smillert##
562eac174f2Safresh1  $want = <<'EOT';
563b39c5158Smillert#$foo = \*::foo;
564b39c5158Smillert#$bar = [
565b39c5158Smillert#  -10,
566b39c5158Smillert#  $foo,
567b39c5158Smillert#  {
568b39c5158Smillert#    a => 1,
569b39c5158Smillert#    b => \5,
570b39c5158Smillert#    c => $bar,
571b39c5158Smillert#    d => $bar->[2]
572b39c5158Smillert#  }
573b39c5158Smillert#];
574b39c5158Smillert#$baz = $bar->[2];
575b39c5158SmillertEOT
576b39c5158Smillert
577eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([\\*foo, \\@foo, \\%foo], ['foo', 'bar', 'baz'])),
578eac174f2Safresh1            'Purity 0: Quotekeys 0: not dereferenced: Dumpxs()',
579eac174f2Safresh1            $want);
580b39c5158Smillert}
581b39c5158Smillert
582b39c5158Smillert#############
583b39c5158Smillert#############
584eac174f2Safresh1
585b39c5158Smillert{
586b39c5158Smillert  package main;
587b39c5158Smillert  @dogs = ( 'Fido', 'Wags' );
588b39c5158Smillert  %kennel = (
589b39c5158Smillert            First => \$dogs[0],
590b39c5158Smillert            Second =>  \$dogs[1],
591b39c5158Smillert           );
592b39c5158Smillert  $dogs[2] = \%kennel;
593b39c5158Smillert  $mutts = \%kennel;
594b39c5158Smillert  $mutts = $mutts;         # avoid warning
595b39c5158Smillert
596b8851fccSafresh1#############
597b39c5158Smillert##
598eac174f2Safresh1  my $want = <<'EOT';
599b39c5158Smillert#%kennels = (
600b39c5158Smillert#  First => \'Fido',
601b39c5158Smillert#  Second => \'Wags'
602b39c5158Smillert#);
603b39c5158Smillert#@dogs = (
604b39c5158Smillert#  ${$kennels{First}},
605b39c5158Smillert#  ${$kennels{Second}},
606b39c5158Smillert#  \%kennels
607b39c5158Smillert#);
608b39c5158Smillert#%mutts = %kennels;
609b39c5158SmillertEOT
610b39c5158Smillert
611eac174f2Safresh1  TEST_BOTH(q{
612b39c5158Smillert              $d = Data::Dumper->new([\\%kennel, \\@dogs, $mutts],
613b39c5158Smillert                                     [qw(*kennels *dogs *mutts)] );
614b39c5158Smillert              $d->Dumpxs;
615eac174f2Safresh1	    }, 'constructor: hash|array|scalar: Dumpxs()',
616eac174f2Safresh1            $want);
617b39c5158Smillert
618b8851fccSafresh1#############
619b39c5158Smillert##
620eac174f2Safresh1  $want = <<'EOT';
621b39c5158Smillert#%kennels = %kennels;
622b39c5158Smillert#@dogs = @dogs;
623b39c5158Smillert#%mutts = %kennels;
624b39c5158SmillertEOT
625b39c5158Smillert
626eac174f2Safresh1  TEST_BOTH(q($d->Dumpxs),
627eac174f2Safresh1            'object call: Dumpxs',
628eac174f2Safresh1            $want);
629b39c5158Smillert
630b8851fccSafresh1#############
631b39c5158Smillert##
632eac174f2Safresh1  $want = <<'EOT';
633b39c5158Smillert#%kennels = (
634b39c5158Smillert#  First => \'Fido',
635b39c5158Smillert#  Second => \'Wags'
636b39c5158Smillert#);
637b39c5158Smillert#@dogs = (
638b39c5158Smillert#  ${$kennels{First}},
639b39c5158Smillert#  ${$kennels{Second}},
640b39c5158Smillert#  \%kennels
641b39c5158Smillert#);
642b39c5158Smillert#%mutts = %kennels;
643b39c5158SmillertEOT
644b39c5158Smillert
645eac174f2Safresh1  TEST_BOTH(q($d->Reset; $d->Dumpxs),
646eac174f2Safresh1            'Reset and Dumpxs separate calls',
647eac174f2Safresh1            $want);
648b39c5158Smillert
649b8851fccSafresh1#############
650b39c5158Smillert##
651eac174f2Safresh1  $want = <<'EOT';
652b39c5158Smillert#@dogs = (
653b39c5158Smillert#  'Fido',
654b39c5158Smillert#  'Wags',
655b39c5158Smillert#  {
656b39c5158Smillert#    First => \$dogs[0],
657b39c5158Smillert#    Second => \$dogs[1]
658b39c5158Smillert#  }
659b39c5158Smillert#);
660b39c5158Smillert#%kennels = %{$dogs[2]};
661b39c5158Smillert#%mutts = %{$dogs[2]};
662b39c5158SmillertEOT
663b39c5158Smillert
664eac174f2Safresh1  TEST_BOTH(q{
665b39c5158Smillert              $d = Data::Dumper->new([\\@dogs, \\%kennel, $mutts],
666b39c5158Smillert                                     [qw(*dogs *kennels *mutts)] );
667b39c5158Smillert              $d->Dumpxs;
668eac174f2Safresh1	    }, 'constructor: array|hash|scalar: Dumpxs()',
669eac174f2Safresh1            $want);
670b39c5158Smillert
671b8851fccSafresh1#############
672b39c5158Smillert##
673eac174f2Safresh1  TEST_BOTH(q($d->Reset->Dumpxs),
674eac174f2Safresh1            'Reset Dumpxs chained',
675eac174f2Safresh1            $want);
676b39c5158Smillert
677b8851fccSafresh1#############
678b39c5158Smillert##
679eac174f2Safresh1  $want = <<'EOT';
680b39c5158Smillert#@dogs = (
681b39c5158Smillert#  'Fido',
682b39c5158Smillert#  'Wags',
683b39c5158Smillert#  {
684b39c5158Smillert#    First => \'Fido',
685b39c5158Smillert#    Second => \'Wags'
686b39c5158Smillert#  }
687b39c5158Smillert#);
688b39c5158Smillert#%kennels = (
689b39c5158Smillert#  First => \'Fido',
690b39c5158Smillert#  Second => \'Wags'
691b39c5158Smillert#);
692b39c5158SmillertEOT
693b39c5158Smillert
694eac174f2Safresh1  TEST_BOTH(q{
6956fb12b70Safresh1              $d = Data::Dumper->new( [\@dogs, \%kennel], [qw(*dogs *kennels)] );
6966fb12b70Safresh1              $d->Deepcopy(1)->Dumpxs;
697eac174f2Safresh1             }, 'Deepcopy(1): Dumpxs',
698eac174f2Safresh1            $want);
699b39c5158Smillert}
700b39c5158Smillert
701b39c5158Smillert{
702b39c5158Smillert
703b39c5158Smillertsub z { print "foo\n" }
704b39c5158Smillert$c = [ \&z ];
705b39c5158Smillert
706b8851fccSafresh1#############
707b39c5158Smillert##
708eac174f2Safresh1  my $want = <<'EOT';
709b39c5158Smillert#$a = $b;
710b39c5158Smillert#$c = [
711b39c5158Smillert#  $b
712b39c5158Smillert#];
713b39c5158SmillertEOT
714b39c5158Smillert
715eac174f2Safresh1   TEST_BOTH(q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'b' => \&z})->Dumpxs;),
716eac174f2Safresh1             'Seen: scalar: Dumpxs',
717eac174f2Safresh1             $want);
718b39c5158Smillert
719b8851fccSafresh1#############
720b39c5158Smillert##
721eac174f2Safresh1  $want = <<'EOT';
722b39c5158Smillert#$a = \&b;
723b39c5158Smillert#$c = [
724b39c5158Smillert#  \&b
725b39c5158Smillert#];
726b39c5158SmillertEOT
727b39c5158Smillert
728eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([\&z,$c],['a','c'])->Seen({'*b' => \&z})->Dumpxs;),
729eac174f2Safresh1            'Seen: glob: Dumpxs',
730eac174f2Safresh1            $want);
731b39c5158Smillert
732b8851fccSafresh1#############
733b39c5158Smillert##
734eac174f2Safresh1  $want = <<'EOT';
735b39c5158Smillert#*a = \&b;
736b39c5158Smillert#@c = (
737b39c5158Smillert#  \&b
738b39c5158Smillert#);
739b39c5158SmillertEOT
740b39c5158Smillert
741eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([\&z,$c],['*a','*c'])->Seen({'*b' => \&z})->Dumpxs;),
742eac174f2Safresh1            'Seen: glob: derference: Dumpxs',
743eac174f2Safresh1            $want);
744b39c5158Smillert}
745b39c5158Smillert
746b39c5158Smillert{
747b39c5158Smillert  $a = [];
748b39c5158Smillert  $a->[1] = \$a->[0];
749b39c5158Smillert
750b8851fccSafresh1#############
751b39c5158Smillert##
752eac174f2Safresh1  my $want = <<'EOT';
753b39c5158Smillert#@a = (
754b39c5158Smillert#  undef,
755b39c5158Smillert#  do{my $o}
756b39c5158Smillert#);
757b39c5158Smillert#$a[1] = \$a[0];
758b39c5158SmillertEOT
759b39c5158Smillert
760eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([$a],['*a'])->Purity(1)->Dumpxs;),
761eac174f2Safresh1            'Purity(1): dereference: Dumpxs',
762eac174f2Safresh1            $want);
763b39c5158Smillert}
764b39c5158Smillert
765b39c5158Smillert{
766b39c5158Smillert  $a = \\\\\'foo';
767b39c5158Smillert  $b = $$$a;
768b39c5158Smillert
769b8851fccSafresh1#############
770b39c5158Smillert##
771eac174f2Safresh1  my $want = <<'EOT';
772b39c5158Smillert#$a = \\\\\'foo';
773b39c5158Smillert#$b = ${${$a}};
774b39c5158SmillertEOT
775b39c5158Smillert
776eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dumpxs;),
777eac174f2Safresh1            'Purity(1): not dereferenced: Dumpxs',
778eac174f2Safresh1            $want);
779b39c5158Smillert}
780b39c5158Smillert
781b39c5158Smillert{
782b39c5158Smillert  $a = [{ a => \$b }, { b => undef }];
783b39c5158Smillert  $b = [{ c => \$b }, { d => \$a }];
784b39c5158Smillert
785b8851fccSafresh1#############
786b39c5158Smillert##
787eac174f2Safresh1  my $want = <<'EOT';
788b39c5158Smillert#$a = [
789b39c5158Smillert#  {
790b39c5158Smillert#    a => \[
791b39c5158Smillert#        {
792b39c5158Smillert#          c => do{my $o}
793b39c5158Smillert#        },
794b39c5158Smillert#        {
795b39c5158Smillert#          d => \[]
796b39c5158Smillert#        }
797b39c5158Smillert#      ]
798b39c5158Smillert#  },
799b39c5158Smillert#  {
800b39c5158Smillert#    b => undef
801b39c5158Smillert#  }
802b39c5158Smillert#];
803b39c5158Smillert#${$a->[0]{a}}->[0]->{c} = $a->[0]{a};
804b39c5158Smillert#${${$a->[0]{a}}->[1]->{d}} = $a;
805b39c5158Smillert#$b = ${$a->[0]{a}};
806b39c5158SmillertEOT
807b39c5158Smillert
808eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([$a,$b],['a','b'])->Purity(1)->Dumpxs;),
809eac174f2Safresh1            'Purity(1); Dumpxs again',
810eac174f2Safresh1            $want);
811b39c5158Smillert}
812b39c5158Smillert
813b39c5158Smillert{
814b39c5158Smillert  $a = [[[[\\\\\'foo']]]];
815b39c5158Smillert  $b = $a->[0][0];
816b39c5158Smillert  $c = $${$b->[0][0]};
817b39c5158Smillert
818b8851fccSafresh1#############
819b39c5158Smillert##
820eac174f2Safresh1  my $want = <<'EOT';
821b39c5158Smillert#$a = [
822b39c5158Smillert#  [
823b39c5158Smillert#    [
824b39c5158Smillert#      [
825b39c5158Smillert#        \\\\\'foo'
826b39c5158Smillert#      ]
827b39c5158Smillert#    ]
828b39c5158Smillert#  ]
829b39c5158Smillert#];
830b39c5158Smillert#$b = $a->[0][0];
831b39c5158Smillert#$c = ${${$a->[0][0][0][0]}};
832b39c5158SmillertEOT
833b39c5158Smillert
834eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Purity(1)->Dumpxs;),
835eac174f2Safresh1            'Purity(1): Dumpxs: 3 elements',
836eac174f2Safresh1            $want);
837b39c5158Smillert}
838b39c5158Smillert
839b39c5158Smillert{
840eac174f2Safresh1    my $f = "pearl";
841eac174f2Safresh1    my $e = [        $f ];
842b39c5158Smillert    $d = { 'e' => $e };
843b39c5158Smillert    $c = [        $d ];
844eac174f2Safresh1    $b = { 'c' => $c }; # FIXME use different variable name
845eac174f2Safresh1    $a = { 'b' => $b }; # FIXME use different variable name
846b39c5158Smillert
847b8851fccSafresh1#############
848b39c5158Smillert##
849eac174f2Safresh1    my $want = <<'EOT';
850b39c5158Smillert#$a = {
851b39c5158Smillert#  b => {
852b39c5158Smillert#    c => [
853b39c5158Smillert#      {
854b39c5158Smillert#        e => 'ARRAY(0xdeadbeef)'
855b39c5158Smillert#      }
856b39c5158Smillert#    ]
857b39c5158Smillert#  }
858b39c5158Smillert#};
859b39c5158Smillert#$b = $a->{b};
860b39c5158Smillert#$c = $a->{b}{c};
861b39c5158SmillertEOT
862b39c5158Smillert
863eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(4)->Dumpxs;),
864eac174f2Safresh1              'Maxdepth(4): Dumpxs()',
865eac174f2Safresh1              $want);
866b39c5158Smillert
867b8851fccSafresh1#############
868b39c5158Smillert##
869eac174f2Safresh1    $want = <<'EOT';
870b39c5158Smillert#$a = {
871b39c5158Smillert#  b => 'HASH(0xdeadbeef)'
872b39c5158Smillert#};
873b39c5158Smillert#$b = $a->{b};
874b39c5158Smillert#$c = [
875b39c5158Smillert#  'HASH(0xdeadbeef)'
876b39c5158Smillert#];
877b39c5158SmillertEOT
878b39c5158Smillert
879eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new([$a,$b,$c],['a','b','c'])->Maxdepth(1)->Dumpxs;),
880eac174f2Safresh1              'Maxdepth(1): Dumpxs()',
881eac174f2Safresh1              $want);
882b39c5158Smillert}
883b39c5158Smillert
884b39c5158Smillert{
885b39c5158Smillert    $a = \$a;
886b39c5158Smillert    $b = [$a];
887b39c5158Smillert
888b8851fccSafresh1#############
889b39c5158Smillert##
890eac174f2Safresh1    my $want = <<'EOT';
891b39c5158Smillert#$b = [
892b39c5158Smillert#  \$b->[0]
893b39c5158Smillert#];
894b39c5158SmillertEOT
895b39c5158Smillert
896eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new([$b],['b'])->Purity(0)->Dumpxs;),
897eac174f2Safresh1               'Purity(0): Dumpxs()',
898eac174f2Safresh1               $want);
899b39c5158Smillert
900b8851fccSafresh1#############
901b39c5158Smillert##
902eac174f2Safresh1    $want = <<'EOT';
903b39c5158Smillert#$b = [
904b39c5158Smillert#  \do{my $o}
905b39c5158Smillert#];
906b39c5158Smillert#${$b->[0]} = $b->[0];
907b39c5158SmillertEOT
908b39c5158Smillert
909eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new([$b],['b'])->Purity(1)->Dumpxs;),
910eac174f2Safresh1              'Purity(1): Dumpxs',
911eac174f2Safresh1              $want);
912b39c5158Smillert}
913b39c5158Smillert
914b39c5158Smillert{
915b39c5158Smillert  $a = "\x{09c10}";
916b8851fccSafresh1#############
917b39c5158Smillert## XS code was adding an extra \0
918eac174f2Safresh1  my $want = <<'EOT';
919b39c5158Smillert#$a = "\x{9c10}";
920b39c5158SmillertEOT
921b39c5158Smillert
922eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([$a], ['a'])),
923eac174f2Safresh1            "\\x{9c10}",
924eac174f2Safresh1            $want);
925b39c5158Smillert}
926b39c5158Smillert
927b39c5158Smillert{
928eac174f2Safresh1  my $i = 0;
929eac174f2Safresh1  $a = { map { ("$_$_$_", ++$i) } 'I'..'Q' }; # FIXME use different variable name
930b39c5158Smillert
931b8851fccSafresh1#############
932b39c5158Smillert##
933eac174f2Safresh1  my $want = <<'EOT';
934b39c5158Smillert#$VAR1 = {
935b39c5158Smillert#  III => 1,
936b39c5158Smillert#  JJJ => 2,
937b39c5158Smillert#  KKK => 3,
938b39c5158Smillert#  LLL => 4,
939b39c5158Smillert#  MMM => 5,
940b39c5158Smillert#  NNN => 6,
941b39c5158Smillert#  OOO => 7,
942b39c5158Smillert#  PPP => 8,
943b39c5158Smillert#  QQQ => 9
944b39c5158Smillert#};
945b39c5158SmillertEOT
946b39c5158Smillert
947eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([$a])->Dumpxs;),
948eac174f2Safresh1            'basic test without names: Dumpxs()',
949eac174f2Safresh1            $want);
950b39c5158Smillert}
951b39c5158Smillert
952b39c5158Smillert{
953eac174f2Safresh1  my $i = 5;
954b39c5158Smillert  $c = { map { (++$i, "$_$_$_") } 'I'..'Q' };
955b39c5158Smillert  local $Data::Dumper::Sortkeys = \&sort199;
956b39c5158Smillert  sub sort199 {
957b39c5158Smillert    my $hash = shift;
958b39c5158Smillert    return [ sort { $b <=> $a } keys %$hash ];
959b39c5158Smillert  }
960b39c5158Smillert
961b8851fccSafresh1#############
962b39c5158Smillert##
963eac174f2Safresh1  my $want = <<'EOT';
964b39c5158Smillert#$VAR1 = {
965b39c5158Smillert#  14 => 'QQQ',
966b39c5158Smillert#  13 => 'PPP',
967b39c5158Smillert#  12 => 'OOO',
968b39c5158Smillert#  11 => 'NNN',
969b39c5158Smillert#  10 => 'MMM',
970b39c5158Smillert#  9 => 'LLL',
971b39c5158Smillert#  8 => 'KKK',
972b39c5158Smillert#  7 => 'JJJ',
973b39c5158Smillert#  6 => 'III'
974b39c5158Smillert#};
975b39c5158SmillertEOT
976b39c5158Smillert
977eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([$c])->Dumpxs;),
978eac174f2Safresh1            "sortkeys sub",
979eac174f2Safresh1            $want);
980b39c5158Smillert}
981b39c5158Smillert
982b39c5158Smillert{
983eac174f2Safresh1  my $i = 5;
984b39c5158Smillert  $c = { map { (++$i, "$_$_$_") } 'I'..'Q' };
985b39c5158Smillert  $d = { reverse %$c };
986b39c5158Smillert  local $Data::Dumper::Sortkeys = \&sort205;
987b39c5158Smillert  sub sort205 {
988b39c5158Smillert    my $hash = shift;
989b39c5158Smillert    return [
990b39c5158Smillert      $hash eq $c ? (sort { $a <=> $b } keys %$hash)
991b39c5158Smillert		  : (reverse sort keys %$hash)
992b39c5158Smillert    ];
993b39c5158Smillert  }
994b39c5158Smillert
995b8851fccSafresh1#############
996b39c5158Smillert##
997eac174f2Safresh1  my $want = <<'EOT';
998b39c5158Smillert#$VAR1 = [
999b39c5158Smillert#  {
1000b39c5158Smillert#    6 => 'III',
1001b39c5158Smillert#    7 => 'JJJ',
1002b39c5158Smillert#    8 => 'KKK',
1003b39c5158Smillert#    9 => 'LLL',
1004b39c5158Smillert#    10 => 'MMM',
1005b39c5158Smillert#    11 => 'NNN',
1006b39c5158Smillert#    12 => 'OOO',
1007b39c5158Smillert#    13 => 'PPP',
1008b39c5158Smillert#    14 => 'QQQ'
1009b39c5158Smillert#  },
1010b39c5158Smillert#  {
1011b39c5158Smillert#    QQQ => 14,
1012b39c5158Smillert#    PPP => 13,
1013b39c5158Smillert#    OOO => 12,
1014b39c5158Smillert#    NNN => 11,
1015b39c5158Smillert#    MMM => 10,
1016b39c5158Smillert#    LLL => 9,
1017b39c5158Smillert#    KKK => 8,
1018b39c5158Smillert#    JJJ => 7,
1019b39c5158Smillert#    III => 6
1020b39c5158Smillert#  }
1021b39c5158Smillert#];
1022b39c5158SmillertEOT
1023b39c5158Smillert
10246fb12b70Safresh1  # the XS code does number values as strings
1025eac174f2Safresh1  my $want_xs = $want;
1026eac174f2Safresh1  $want_xs =~ s/ (\d+)(,?)$/ '$1'$2/gm;
1027eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([[$c, $d]])->Dumpxs;),
1028eac174f2Safresh1            "more sortkeys sub",
1029eac174f2Safresh1            $want, $want_xs);
1030b39c5158Smillert}
1031b39c5158Smillert
1032b39c5158Smillert{
1033b39c5158Smillert  local $Data::Dumper::Deparse = 1;
1034b39c5158Smillert  local $Data::Dumper::Indent = 2;
1035b39c5158Smillert
1036b8851fccSafresh1#############
1037b39c5158Smillert##
1038eac174f2Safresh1  my $want = <<'EOT';
1039b39c5158Smillert#$VAR1 = {
1040b39c5158Smillert#          foo => sub {
1041eac174f2Safresh1#                     use warnings;
1042b39c5158Smillert#                     print 'foo';
1043b39c5158Smillert#                 }
1044b39c5158Smillert#        };
1045b39c5158SmillertEOT
1046b39c5158Smillert
1047b39c5158Smillert  if(" $Config{'extensions'} " !~ m[ B ]) {
1048eac174f2Safresh1    SKIP_BOTH("Perl configured without B module");
1049b39c5158Smillert  } else {
1050eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new([{ foo => sub { print "foo"; } }])->Dumpxs),
1051eac174f2Safresh1              'Deparse 1: Indent 2; Dumpxs()',
1052eac174f2Safresh1              $want);
1053b39c5158Smillert  }
1054b39c5158Smillert}
1055b39c5158Smillert
1056b8851fccSafresh1#############
1057b39c5158Smillert##
1058b39c5158Smillert
1059b39c5158Smillert# This is messy.
1060b39c5158Smillert# The controls (bare numbers) are stored either as integers or floating point.
1061eac174f2Safresh1# [depending on whether the tokeniser sees things like ".".]
1062b39c5158Smillert# The peephole optimiser only runs for constant folding, not single constants,
1063b39c5158Smillert# so I already have some NVs, some IVs
1064b39c5158Smillert# The string versions are not. They are all PV
1065b39c5158Smillert
1066b39c5158Smillert# This is arguably all far too chummy with the implementation, but I really
1067b39c5158Smillert# want to ensure that we don't go wrong when flags on scalars get as side
1068b39c5158Smillert# effects of reading them.
1069b39c5158Smillert
1070b39c5158Smillert# These tests are actually testing the precise output of the current
1071b39c5158Smillert# implementation, so will most likely fail if the implementation changes,
1072b39c5158Smillert# even if the new implementation produces different but correct results.
1073b39c5158Smillert# It would be nice to test for wrong answers, but I can't see how to do that,
1074b39c5158Smillert# so instead I'm checking for unexpected answers. (ie -2 becoming "-2" is not
1075b39c5158Smillert# wrong, but I can't see an easy, reliable way to code that knowledge)
1076b39c5158Smillert
1077eac174f2Safresh1{
1078b39c5158Smillert    # Numbers (seen by the tokeniser as numbers, stored as numbers.
1079eac174f2Safresh1    @numbers = (
1080b39c5158Smillert        0, +1, -2, 3.0, +4.0, -5.0, 6.5, +7.5, -8.5,
1081b39c5158Smillert        9,  +10,  -11,  12.0,  +13.0,  -14.0,  15.5,  +16.25,  -17.75,
1082b39c5158Smillert    );
1083b39c5158Smillert    # Strings
1084eac174f2Safresh1  @strings = (
1085b39c5158Smillert      "0", "+1", "-2", "3.0", "+4.0", "-5.0", "6.5", "+7.5", "-8.5", " 9",
1086b39c5158Smillert      " +10", " -11", " 12.0", " +13.0", " -14.0", " 15.5", " +16.25", " -17.75",
1087b39c5158Smillert  );
1088b39c5158Smillert
1089b39c5158Smillert    # The perl code always does things the same way for numbers.
1090eac174f2Safresh1    my $WANT_PL_N = <<'EOT';
1091b39c5158Smillert#$VAR1 = 0;
1092b39c5158Smillert#$VAR2 = 1;
1093b39c5158Smillert#$VAR3 = -2;
1094b39c5158Smillert#$VAR4 = 3;
1095b39c5158Smillert#$VAR5 = 4;
1096b39c5158Smillert#$VAR6 = -5;
1097b39c5158Smillert#$VAR7 = '6.5';
1098b39c5158Smillert#$VAR8 = '7.5';
1099b39c5158Smillert#$VAR9 = '-8.5';
1100b39c5158Smillert#$VAR10 = 9;
1101b39c5158Smillert#$VAR11 = 10;
1102b39c5158Smillert#$VAR12 = -11;
1103b39c5158Smillert#$VAR13 = 12;
1104b39c5158Smillert#$VAR14 = 13;
1105b39c5158Smillert#$VAR15 = -14;
1106b39c5158Smillert#$VAR16 = '15.5';
1107b39c5158Smillert#$VAR17 = '16.25';
1108b39c5158Smillert#$VAR18 = '-17.75';
1109b39c5158SmillertEOT
1110b39c5158Smillert    # The perl code knows that 0 and -2 stringify exactly back to the strings,
1111b39c5158Smillert    # so it dumps them as numbers, not strings.
1112eac174f2Safresh1    my $WANT_PL_S = <<'EOT';
1113b39c5158Smillert#$VAR1 = 0;
1114b39c5158Smillert#$VAR2 = '+1';
1115b39c5158Smillert#$VAR3 = -2;
1116b39c5158Smillert#$VAR4 = '3.0';
1117b39c5158Smillert#$VAR5 = '+4.0';
1118b39c5158Smillert#$VAR6 = '-5.0';
1119b39c5158Smillert#$VAR7 = '6.5';
1120b39c5158Smillert#$VAR8 = '+7.5';
1121b39c5158Smillert#$VAR9 = '-8.5';
1122b39c5158Smillert#$VAR10 = ' 9';
1123b39c5158Smillert#$VAR11 = ' +10';
1124b39c5158Smillert#$VAR12 = ' -11';
1125b39c5158Smillert#$VAR13 = ' 12.0';
1126b39c5158Smillert#$VAR14 = ' +13.0';
1127b39c5158Smillert#$VAR15 = ' -14.0';
1128b39c5158Smillert#$VAR16 = ' 15.5';
1129b39c5158Smillert#$VAR17 = ' +16.25';
1130b39c5158Smillert#$VAR18 = ' -17.75';
1131b39c5158SmillertEOT
1132b39c5158Smillert
1133b39c5158Smillert    # The XS code differs.
1134b39c5158Smillert    # These are the numbers as seen by the tokeniser. Constants aren't folded
1135b39c5158Smillert    # (which makes IVs where possible) so values the tokeniser thought were
1136b39c5158Smillert    # floating point are stored as NVs. The XS code outputs these as strings,
1137b39c5158Smillert    # but as it has converted them from NVs, leading + signs will not be there.
1138eac174f2Safresh1    my $WANT_XS_N = <<'EOT';
1139b39c5158Smillert#$VAR1 = 0;
1140b39c5158Smillert#$VAR2 = 1;
1141b39c5158Smillert#$VAR3 = -2;
1142b39c5158Smillert#$VAR4 = '3';
1143b39c5158Smillert#$VAR5 = '4';
1144b39c5158Smillert#$VAR6 = '-5';
1145b39c5158Smillert#$VAR7 = '6.5';
1146b39c5158Smillert#$VAR8 = '7.5';
1147b39c5158Smillert#$VAR9 = '-8.5';
1148b39c5158Smillert#$VAR10 = 9;
1149b39c5158Smillert#$VAR11 = 10;
1150b39c5158Smillert#$VAR12 = -11;
1151b39c5158Smillert#$VAR13 = '12';
1152b39c5158Smillert#$VAR14 = '13';
1153b39c5158Smillert#$VAR15 = '-14';
1154b39c5158Smillert#$VAR16 = '15.5';
1155b39c5158Smillert#$VAR17 = '16.25';
1156b39c5158Smillert#$VAR18 = '-17.75';
1157b39c5158SmillertEOT
1158b39c5158Smillert
1159b39c5158Smillert    # These are the strings as seen by the tokeniser. The XS code will output
1160b39c5158Smillert    # these for all cases except where the scalar has been used in integer context
1161eac174f2Safresh1    my $WANT_XS_S = <<'EOT';
1162b39c5158Smillert#$VAR1 = '0';
1163b39c5158Smillert#$VAR2 = '+1';
1164b39c5158Smillert#$VAR3 = '-2';
1165b39c5158Smillert#$VAR4 = '3.0';
1166b39c5158Smillert#$VAR5 = '+4.0';
1167b39c5158Smillert#$VAR6 = '-5.0';
1168b39c5158Smillert#$VAR7 = '6.5';
1169b39c5158Smillert#$VAR8 = '+7.5';
1170b39c5158Smillert#$VAR9 = '-8.5';
1171b39c5158Smillert#$VAR10 = ' 9';
1172b39c5158Smillert#$VAR11 = ' +10';
1173b39c5158Smillert#$VAR12 = ' -11';
1174b39c5158Smillert#$VAR13 = ' 12.0';
1175b39c5158Smillert#$VAR14 = ' +13.0';
1176b39c5158Smillert#$VAR15 = ' -14.0';
1177b39c5158Smillert#$VAR16 = ' 15.5';
1178b39c5158Smillert#$VAR17 = ' +16.25';
1179b39c5158Smillert#$VAR18 = ' -17.75';
1180b39c5158SmillertEOT
1181b39c5158Smillert
1182b39c5158Smillert    # These are the numbers as IV-ized by &
1183b39c5158Smillert    # These will differ from WANT_XS_N because now IV flags will be set on all
1184b39c5158Smillert    # values that were actually integer, and the XS code will then output these
1185b39c5158Smillert    # as numbers not strings.
1186eac174f2Safresh1    my $WANT_XS_I = <<'EOT';
1187b39c5158Smillert#$VAR1 = 0;
1188b39c5158Smillert#$VAR2 = 1;
1189b39c5158Smillert#$VAR3 = -2;
1190b39c5158Smillert#$VAR4 = 3;
1191b39c5158Smillert#$VAR5 = 4;
1192b39c5158Smillert#$VAR6 = -5;
1193b39c5158Smillert#$VAR7 = '6.5';
1194b39c5158Smillert#$VAR8 = '7.5';
1195b39c5158Smillert#$VAR9 = '-8.5';
1196b39c5158Smillert#$VAR10 = 9;
1197b39c5158Smillert#$VAR11 = 10;
1198b39c5158Smillert#$VAR12 = -11;
1199b39c5158Smillert#$VAR13 = 12;
1200b39c5158Smillert#$VAR14 = 13;
1201b39c5158Smillert#$VAR15 = -14;
1202b39c5158Smillert#$VAR16 = '15.5';
1203b39c5158Smillert#$VAR17 = '16.25';
1204b39c5158Smillert#$VAR18 = '-17.75';
1205b39c5158SmillertEOT
1206b39c5158Smillert
1207b39c5158Smillert    # Some of these tests will be redundant.
1208eac174f2Safresh1    @numbers_s = @numbers_i = @numbers_is = @numbers_n = @numbers_ns
1209eac174f2Safresh1        = @numbers_ni = @numbers_nis = @numbers;
1210eac174f2Safresh1    @strings_s = @strings_i = @strings_is = @strings_n = @strings_ns
1211eac174f2Safresh1        = @strings_ni = @strings_nis = @strings;
1212b39c5158Smillert    # Use them in an integer context
1213b39c5158Smillert    foreach (@numbers_i, @numbers_ni, @numbers_nis, @numbers_is,
1214b39c5158Smillert             @strings_i, @strings_ni, @strings_nis, @strings_is) {
1215b39c5158Smillert        my $b = sprintf "%d", $_;
1216b39c5158Smillert    }
1217b39c5158Smillert    # Use them in a floating point context
1218b39c5158Smillert    foreach (@numbers_n, @numbers_ni, @numbers_nis, @numbers_ns,
1219b39c5158Smillert             @strings_n, @strings_ni, @strings_nis, @strings_ns) {
1220b39c5158Smillert        my $b = sprintf "%e", $_;
1221b39c5158Smillert    }
1222b39c5158Smillert    # Use them in a string context
1223b39c5158Smillert    foreach (@numbers_s, @numbers_is, @numbers_nis, @numbers_ns,
1224b39c5158Smillert             @strings_s, @strings_is, @strings_nis, @strings_ns) {
1225b39c5158Smillert        my $b = sprintf "%s", $_;
1226b39c5158Smillert    }
1227b39c5158Smillert
1228b39c5158Smillert    # use Devel::Peek; Dump ($_) foreach @vanilla_c;
1229b39c5158Smillert
1230eac174f2Safresh1    my $nv_preserves_uv_4bits = defined $Config{d_nv_preserves_uv}
1231eac174f2Safresh1        || (exists($Config{nv_preserves_uv_bits}) && $Config{nv_preserves_uv_bits} >= 4);
1232b39c5158Smillert
1233eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@numbers)->Dumpxs),
1234eac174f2Safresh1              'Numbers',
1235eac174f2Safresh1              $WANT_PL_N, $WANT_XS_N);
1236eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@numbers_s)->Dumpxs),
1237eac174f2Safresh1              'Numbers PV',
1238eac174f2Safresh1              $WANT_PL_N, $WANT_XS_N);
1239eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@numbers_i)->Dumpxs),
1240eac174f2Safresh1              'Numbers IV',
1241eac174f2Safresh1              $WANT_PL_N, $WANT_XS_I,
1242eac174f2Safresh1              $nv_preserves_uv_4bits ? "" : "NV does not preserve 4bits");
1243eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@numbers_is)->Dumpxs),
1244eac174f2Safresh1              'Numbers IV,PV',
1245eac174f2Safresh1              $WANT_PL_N, $WANT_XS_I,
1246eac174f2Safresh1              $nv_preserves_uv_4bits ? "" : "NV does not preserve 4bits");
1247eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@numbers_n)->Dumpxs),
1248eac174f2Safresh1              'XS Numbers NV',
1249eac174f2Safresh1              $WANT_PL_N, $WANT_XS_N);
1250eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@numbers_ns)->Dumpxs),
1251eac174f2Safresh1              'XS Numbers NV,PV',
1252eac174f2Safresh1              $WANT_PL_N, $WANT_XS_N);
1253eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@numbers_ni)->Dumpxs),
1254eac174f2Safresh1              'Numbers NV,IV',
1255eac174f2Safresh1              $WANT_PL_N, $WANT_XS_I,
1256eac174f2Safresh1              $nv_preserves_uv_4bits ? "" : "NV does not preserve 4bits");
1257eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@numbers_nis)->Dumpxs),
1258eac174f2Safresh1              'Numbers NV,IV,PV',
1259eac174f2Safresh1              $WANT_PL_N, $WANT_XS_I,
1260eac174f2Safresh1              $nv_preserves_uv_4bits ? "" : "NV does not preserve 4bits");
1261eac174f2Safresh1
1262eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@strings)->Dumpxs),
1263eac174f2Safresh1              'Strings',
1264eac174f2Safresh1              $WANT_PL_S, $WANT_XS_S);
1265eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@strings_s)->Dumpxs),
1266eac174f2Safresh1              'Strings PV',
1267eac174f2Safresh1              $WANT_PL_S, $WANT_XS_S);
1268b39c5158Smillert    # This one used to really mess up. New code actually emulates the .pm code
1269eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@strings_i)->Dumpxs),
1270eac174f2Safresh1              'Strings IV',
1271eac174f2Safresh1              $WANT_PL_S);
1272eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@strings_is)->Dumpxs),
1273eac174f2Safresh1              'Strings IV,PV',
1274eac174f2Safresh1              $WANT_PL_S);
1275eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@strings_n)->Dumpxs),
1276eac174f2Safresh1              'Strings NV',
1277eac174f2Safresh1              $WANT_PL_S, $WANT_XS_S,
1278eac174f2Safresh1              $nv_preserves_uv_4bits ? "" : "NV does not preserve 4bits");
1279eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@strings_ns)->Dumpxs),
1280eac174f2Safresh1              'Strings NV,PV',
1281eac174f2Safresh1              $WANT_PL_S, $WANT_XS_S,
1282eac174f2Safresh1              $nv_preserves_uv_4bits ? "" : "NV does not preserve 4bits");
1283b39c5158Smillert    # This one used to really mess up. New code actually emulates the .pm code
1284eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@strings_ni)->Dumpxs),
1285eac174f2Safresh1              'Strings NV,IV',
1286eac174f2Safresh1              $WANT_PL_S);
1287eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->new(\@strings_nis)->Dumpxs),
1288eac174f2Safresh1              'Strings NV,IV,PV',
1289eac174f2Safresh1              $WANT_PL_S);
1290b39c5158Smillert}
1291b39c5158Smillert
1292b39c5158Smillert{
1293b39c5158Smillert  $a = "1\n";
1294b8851fccSafresh1#############
1295b39c5158Smillert## Perl code was using /...$/ and hence missing the \n.
1296eac174f2Safresh1  my $want = <<'EOT';
1297b39c5158Smillertmy $VAR1 = '42
1298b39c5158Smillert';
1299b39c5158SmillertEOT
1300b39c5158Smillert
1301b39c5158Smillert  # Can't pad with # as the output has an embedded newline.
1302b39c5158Smillert  local $Data::Dumper::Pad = "my ";
1303eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs(["42\n"])),
1304eac174f2Safresh1            "number with trailing newline",
1305eac174f2Safresh1            $want);
1306b39c5158Smillert}
1307b39c5158Smillert
1308b39c5158Smillert{
1309b39c5158Smillert  @a = (
1310b39c5158Smillert        999999999,
1311b39c5158Smillert        1000000000,
1312b39c5158Smillert        9999999999,
1313b39c5158Smillert        10000000000,
1314b39c5158Smillert        -999999999,
1315b39c5158Smillert        -1000000000,
1316b39c5158Smillert        -9999999999,
1317b39c5158Smillert        -10000000000,
1318b39c5158Smillert        4294967295,
1319b39c5158Smillert        4294967296,
1320b39c5158Smillert        -2147483648,
1321b39c5158Smillert        -2147483649,
1322b39c5158Smillert        );
1323b8851fccSafresh1#############
1324b39c5158Smillert## Perl code flips over at 10 digits.
1325eac174f2Safresh1  my $want = <<'EOT';
1326b39c5158Smillert#$VAR1 = 999999999;
1327b39c5158Smillert#$VAR2 = '1000000000';
1328b39c5158Smillert#$VAR3 = '9999999999';
1329b39c5158Smillert#$VAR4 = '10000000000';
1330b39c5158Smillert#$VAR5 = -999999999;
1331b39c5158Smillert#$VAR6 = '-1000000000';
1332b39c5158Smillert#$VAR7 = '-9999999999';
1333b39c5158Smillert#$VAR8 = '-10000000000';
1334b39c5158Smillert#$VAR9 = '4294967295';
1335b39c5158Smillert#$VAR10 = '4294967296';
1336b39c5158Smillert#$VAR11 = '-2147483648';
1337b39c5158Smillert#$VAR12 = '-2147483649';
1338b39c5158SmillertEOT
1339b39c5158Smillert
1340b39c5158Smillert## XS code flips over at 11 characters ("-" is a char) or larger than int.
1341eac174f2Safresh1  my $want_xs = ~0 == 0xFFFFFFFF ? << 'EOT32' : << 'EOT64';
1342b39c5158Smillert#$VAR1 = 999999999;
1343b39c5158Smillert#$VAR2 = 1000000000;
1344b39c5158Smillert#$VAR3 = '9999999999';
1345b39c5158Smillert#$VAR4 = '10000000000';
1346b39c5158Smillert#$VAR5 = -999999999;
1347b39c5158Smillert#$VAR6 = '-1000000000';
1348b39c5158Smillert#$VAR7 = '-9999999999';
1349b39c5158Smillert#$VAR8 = '-10000000000';
1350b39c5158Smillert#$VAR9 = 4294967295;
1351b39c5158Smillert#$VAR10 = '4294967296';
1352b39c5158Smillert#$VAR11 = '-2147483648';
1353b39c5158Smillert#$VAR12 = '-2147483649';
1354eac174f2Safresh1EOT32
1355b39c5158Smillert#$VAR1 = 999999999;
1356b39c5158Smillert#$VAR2 = 1000000000;
1357b39c5158Smillert#$VAR3 = 9999999999;
1358b39c5158Smillert#$VAR4 = '10000000000';
1359b39c5158Smillert#$VAR5 = -999999999;
1360b39c5158Smillert#$VAR6 = '-1000000000';
1361b39c5158Smillert#$VAR7 = '-9999999999';
1362b39c5158Smillert#$VAR8 = '-10000000000';
1363b39c5158Smillert#$VAR9 = 4294967295;
1364b39c5158Smillert#$VAR10 = 4294967296;
1365b39c5158Smillert#$VAR11 = '-2147483648';
1366b39c5158Smillert#$VAR12 = '-2147483649';
1367eac174f2Safresh1EOT64
1368eac174f2Safresh1
1369eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs(\@a)),
1370eac174f2Safresh1            "long integers",
1371eac174f2Safresh1            $want, $want_xs);
1372b39c5158Smillert}
1373b39c5158Smillert
1374b39c5158Smillert{
1375b39c5158Smillert    $b = "Bad. XS didn't escape dollar sign";
1376b8851fccSafresh1#############
1377b8851fccSafresh1    # B6 is chosen because it is UTF-8 variant on ASCII and all 3 EBCDIC
1378b8851fccSafresh1    # platforms that Perl currently purports to work on.  It also is the only
1379b8851fccSafresh1    # such code point that has the same meaning on all 4, the paragraph sign.
1380eac174f2Safresh1    my $want = <<"EOT"; # Careful. This is '' string written inside "" here doc
1381b8851fccSafresh1#\$VAR1 = '\$b\"\@\\\\\xB6';
1382b39c5158SmillertEOT
1383b39c5158Smillert
1384b8851fccSafresh1    $a = "\$b\"\@\\\xB6\x{100}";
1385b39c5158Smillert    chop $a;
1386eac174f2Safresh1    my $want_xs = <<'EOT'; # While this is "" string written inside "" here doc
1387b8851fccSafresh1#$VAR1 = "\$b\"\@\\\x{b6}";
1388b39c5158SmillertEOT
1389eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->Dumpxs([$a])),
1390eac174f2Safresh1              "XS utf8 flag with \" and \$",
1391eac174f2Safresh1              $want, $want_xs);
1392eac174f2Safresh1
1393b39c5158Smillert  # XS used to produce "$b\"' which is 4 chars, not 3. [ie wrongly qq(\$b\\\")]
1394b8851fccSafresh1#############
1395eac174f2Safresh1  $want = <<'EOT';
1396b39c5158Smillert#$VAR1 = '$b"';
1397b39c5158SmillertEOT
1398b39c5158Smillert
1399b39c5158Smillert  $a = "\$b\"\x{100}";
1400b39c5158Smillert  chop $a;
1401eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([$a])),
1402eac174f2Safresh1            "XS utf8 flag with \" and \$",
1403eac174f2Safresh1            $want);
1404b39c5158Smillert
1405b39c5158Smillert
1406b39c5158Smillert  # XS used to produce 'D'oh!' which is well, D'oh!
1407b39c5158Smillert  # Andreas found this one, which in turn discovered the previous two.
1408b8851fccSafresh1#############
1409eac174f2Safresh1  $want = <<'EOT';
1410b39c5158Smillert#$VAR1 = 'D\'oh!';
1411b39c5158SmillertEOT
1412b39c5158Smillert
1413b39c5158Smillert  $a = "D'oh!\x{100}";
1414b39c5158Smillert  chop $a;
1415eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([$a])),
1416eac174f2Safresh1            "XS utf8 flag with '",
1417eac174f2Safresh1            $want);
1418b39c5158Smillert}
1419b39c5158Smillert
1420b39c5158Smillert# Jarkko found that -Mutf8 caused some tests to fail.  Turns out that there
1421b39c5158Smillert# was an otherwise untested code path in the XS for utf8 hash keys with purity
1422b39c5158Smillert# 1
1423b39c5158Smillert
1424b39c5158Smillert{
1425eac174f2Safresh1  my $want = <<'EOT';
1426b39c5158Smillert#$ping = \*::ping;
1427b39c5158Smillert#*::ping = \5;
1428b39c5158Smillert#*::ping = {
1429b39c5158Smillert#  "\x{decaf}\x{decaf}\x{decaf}\x{decaf}" => do{my $o}
1430b39c5158Smillert#};
1431b39c5158Smillert#*::ping{HASH}->{"\x{decaf}\x{decaf}\x{decaf}\x{decaf}"} = *::ping{SCALAR};
1432b39c5158Smillert#%pong = %{*::ping{HASH}};
1433b39c5158SmillertEOT
1434b39c5158Smillert  local $Data::Dumper::Purity = 1;
1435b39c5158Smillert  local $Data::Dumper::Sortkeys;
1436b39c5158Smillert  $ping = 5;
1437b39c5158Smillert  %ping = (chr (0xDECAF) x 4  =>\$ping);
1438b39c5158Smillert  for $Data::Dumper::Sortkeys (0, 1) {
1439eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->Dumpxs([\\*ping, \\%ping], ['*ping', '*pong'])),
1440eac174f2Safresh1              "utf8: Purity 1: Sortkeys: Dumpxs()",
1441eac174f2Safresh1              $want);
1442b39c5158Smillert  }
1443b39c5158Smillert}
1444b39c5158Smillert
1445b39c5158Smillert# XS for quotekeys==0 was not being defensive enough against utf8 flagged
1446b39c5158Smillert# scalars
1447b39c5158Smillert
1448b39c5158Smillert{
1449eac174f2Safresh1  my $want = <<'EOT';
1450b39c5158Smillert#$VAR1 = {
1451b39c5158Smillert#  perl => 'rocks'
1452b39c5158Smillert#};
1453b39c5158SmillertEOT
1454b39c5158Smillert  local $Data::Dumper::Quotekeys = 0;
1455b39c5158Smillert  my $k = 'perl' . chr 256;
1456b39c5158Smillert  chop $k;
1457b39c5158Smillert  %foo = ($k => 'rocks');
1458b39c5158Smillert
1459eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([\\%foo])),
1460eac174f2Safresh1            "quotekeys == 0 for utf8 flagged ASCII",
1461eac174f2Safresh1            $want);
1462b39c5158Smillert}
1463b8851fccSafresh1#############
1464b39c5158Smillert{
1465eac174f2Safresh1  my $want = <<'EOT';
1466b39c5158Smillert#$VAR1 = [
1467b39c5158Smillert#  undef,
1468b39c5158Smillert#  undef,
1469b39c5158Smillert#  1
1470b39c5158Smillert#];
1471b39c5158SmillertEOT
1472b39c5158Smillert    @foo = ();
1473b39c5158Smillert    $foo[2] = 1;
1474eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->Dumpxs([\@foo])),
1475eac174f2Safresh1              'Richard Clamp, Message-Id: <20030104005247.GA27685@mirth.demon.co.uk>: Dumpxs()',
1476eac174f2Safresh1              $want);
1477b39c5158Smillert}
1478b39c5158Smillert
1479b8851fccSafresh1#############
1480898184e3Ssthen# Make sure $obj->Dumpxs returns the right thing in list context. This was
1481898184e3Ssthen# broken by the initial attempt to fix [perl #74170].
1482eac174f2Safresh1{
1483eac174f2Safresh1    my $want = <<'EOT';
1484898184e3Ssthen#$VAR1 = [];
1485898184e3SsthenEOT
1486eac174f2Safresh1    TEST_BOTH(q(join " ", new Data::Dumper [[]],[] =>->Dumpxs),
1487eac174f2Safresh1              '$obj->Dumpxs in list context',
1488eac174f2Safresh1              $want);
1489eac174f2Safresh1}
1490b39c5158Smillert
1491b8851fccSafresh1#############
1492898184e3Ssthen{
1493eac174f2Safresh1  my $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';
1494eac174f2Safresh1  $want = convert_to_native($want);
1495eac174f2Safresh1  $want = <<"EOT";
1496b8851fccSafresh1#\$VAR1 = [
1497eac174f2Safresh1#  "$want"
1498898184e3Ssthen#];
1499898184e3SsthenEOT
1500898184e3Ssthen
1501898184e3Ssthen  $foo = [ join "", map chr, 0..255 ];
1502898184e3Ssthen  local $Data::Dumper::Useqq = 1;
1503eac174f2Safresh1  TEST_BOTH(q(Data::Dumper::DumperX($foo)),
1504eac174f2Safresh1            'All latin1 characters: DumperX',
1505eac174f2Safresh1            $want);
1506898184e3Ssthen}
1507898184e3Ssthen
1508b8851fccSafresh1#############
1509898184e3Ssthen{
1510eac174f2Safresh1  my $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}';
1511eac174f2Safresh1  $want = convert_to_native($want);
1512eac174f2Safresh1  $want = <<"EOT";
1513b8851fccSafresh1#\$VAR1 = [
1514eac174f2Safresh1#  "$want"
1515898184e3Ssthen#];
1516898184e3SsthenEOT
1517898184e3Ssthen
1518898184e3Ssthen  $foo = [ join "", map chr, 0..255, 0x20ac ];
1519898184e3Ssthen  local $Data::Dumper::Useqq = 1;
1520eac174f2Safresh1  TEST_BOTH(q(Data::Dumper::DumperX($foo)),
1521eac174f2Safresh1            'All latin1 characters with utf8 flag including a wide character: DumperX',
1522eac174f2Safresh1            $want);
1523898184e3Ssthen}
1524898184e3Ssthen
1525b8851fccSafresh1#############
1526898184e3Ssthen{
1527*e0680481Safresh1  if (!Data::Dumper::SUPPORTS_CORE_BOOLS) {
1528*e0680481Safresh1      SKIP_BOTH("Core booleans not supported on older perls");
1529*e0680481Safresh1      last;
1530*e0680481Safresh1  }
1531*e0680481Safresh1  my $want = <<'EOT';
1532*e0680481Safresh1#$VAR1 = [
1533*e0680481Safresh1#  !!1,
1534*e0680481Safresh1#  !!0
1535*e0680481Safresh1#];
1536*e0680481Safresh1EOT
1537*e0680481Safresh1
1538*e0680481Safresh1  $foo = [ !!1, !!0 ];
1539*e0680481Safresh1  TEST_BOTH(q(Data::Dumper::DumperX($foo)),
1540*e0680481Safresh1            'Booleans',
1541*e0680481Safresh1            $want);
1542*e0680481Safresh1}
1543*e0680481Safresh1
1544*e0680481Safresh1
1545*e0680481Safresh1#############
1546*e0680481Safresh1{
1547898184e3Ssthen  # If XS cannot load, the pure-Perl version cannot deparse vstrings with
1548eac174f2Safresh1  # underscores properly.
1549eac174f2Safresh1  # Says the original comment. However, the story is more complex than that.
1550eac174f2Safresh1  # 1) If *all* XS cannot load, Data::Dumper fails hard, because it needs
1551eac174f2Safresh1  #    Scalar::Util.
1552eac174f2Safresh1  # 2) However, if Data::Dumper's XS cannot load, then Data::Dumper uses the
1553eac174f2Safresh1  #    "Pure Perl" implementation, which uses C<sprintf "%vd", $val> and the
1554eac174f2Safresh1  #    comment above applies.
1555eac174f2Safresh1  # 3) However, if we "just" set $Data::Dumper::Useperl true, then Dump *calls*
1556eac174f2Safresh1  #    the "Pure Perl" (general) implementation, but that calls a helper in the
1557eac174f2Safresh1  #    XS code (&_vstring) and it *does* deparse these vstrings properly
1558eac174f2Safresh1  # Meaning that for case 3, what we actually *test*, we get "VSTRINGS_CORRECT"
1559eac174f2Safresh1  # The "problem" comes that if one deletes Dumper.so and re-tests, it's case 2
1560eac174f2Safresh1  # and this test will fail, because case 2 output is:
1561eac174f2Safresh1  #
1562eac174f2Safresh1  #$a = \v65.66.67;
1563eac174f2Safresh1  #$b = \v65.66.67;
1564eac174f2Safresh1  #$c = \v65.66.67;
1565898184e3Ssthen  #$d = \'ABC';
1566eac174f2Safresh1  #
1567eac174f2Safresh1  # This is the test output removed by commit 55d1a9a4aa623c18 in Aug 2012:
1568eac174f2Safresh1  #     Data::Dumper: Fix tests for pure-Perl implementation
1569eac174f2Safresh1  #
1570eac174f2Safresh1  #     Father Chrysostomos fixed vstring handling in both XS and pure-Perl
1571eac174f2Safresh1  #     implementations of Data::Dumper in
1572eac174f2Safresh1  #     de5ef703c7d8db6517e7d56d9c018d3ad03f210e.
1573eac174f2Safresh1  #
1574eac174f2Safresh1  #     He also updated the tests for the default XS implementation, but it seems
1575eac174f2Safresh1  #     that he missed the test changes necessary for the pure-Perl implementation
1576eac174f2Safresh1  #     which now also does the right thing.
1577eac174f2Safresh1  #
1578eac174f2Safresh1  # (But the relevant previous commit is not de5ef703c7d8 but d036e907fea3)
1579eac174f2Safresh1  # Part of the confusion here comes because at commit d036e907fea3 it was *not*
1580eac174f2Safresh1  # possible to remove Dumper.so and have Data::Dumper load - that bug was fixed
1581eac174f2Safresh1  # later (commit 1e9285c2ad54ae39, Dec 2011)
1582eac174f2Safresh1  #
1583eac174f2Safresh1  # Sigh, but even the test output added in d036e907fea3 was not correct
1584eac174f2Safresh1  # at least not consistent, as it had \v65.66.67, but the code at the time
1585eac174f2Safresh1  # generated \65.66.77 (no v). Now fixed.
1586b8851fccSafresh1  my $ABC_native = chr(65) . chr(66) . chr(67);
1587eac174f2Safresh1  my $want = $XS ? <<"VSTRINGS_CORRECT" : <<"NO_vstring_HELPER";
1588b8851fccSafresh1#\$a = \\v65.66.67;
1589b8851fccSafresh1#\$b = \\v65.66.067;
1590b8851fccSafresh1#\$c = \\v65.66.6_7;
1591b8851fccSafresh1#\$d = \\'$ABC_native';
159291f110e0Safresh1VSTRINGS_CORRECT
1593eac174f2Safresh1#\$a = \\v65.66.67;
1594eac174f2Safresh1#\$b = \\v65.66.67;
1595eac174f2Safresh1#\$c = \\v65.66.67;
1596eac174f2Safresh1#\$d = \\'$ABC_native';
1597eac174f2Safresh1NO_vstring_HELPER
159891f110e0Safresh1
1599898184e3Ssthen  @::_v = (
1600898184e3Ssthen    \v65.66.67,
1601eac174f2Safresh1    \(eval 'v65.66.067'),
1602898184e3Ssthen    \v65.66.6_7,
1603898184e3Ssthen    \~v190.189.188
1604898184e3Ssthen  );
160591f110e0Safresh1  if ($] >= 5.010) {
1606eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->Dumpxs(\@::_v, [qw(a b c d)])),
1607eac174f2Safresh1              'vstrings',
1608eac174f2Safresh1              $want);
1609898184e3Ssthen  }
161091f110e0Safresh1  else { # Skip tests before 5.10. vstrings considered funny before
1611eac174f2Safresh1    SKIP_BOTH("vstrings considered funny before 5.10.0");
161291f110e0Safresh1  }
161391f110e0Safresh1}
1614898184e3Ssthen
1615b8851fccSafresh1#############
1616898184e3Ssthen{
1617898184e3Ssthen  # [perl #107372] blessed overloaded globs
1618eac174f2Safresh1  my $want = <<'EOW';
1619898184e3Ssthen#$VAR1 = bless( \*::finkle, 'overtest' );
1620898184e3SsthenEOW
1621898184e3Ssthen  {
1622898184e3Ssthen    package overtest;
1623898184e3Ssthen    use overload fallback=>1, q\""\=>sub{"oaoaa"};
1624898184e3Ssthen  }
1625eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([bless \*finkle, "overtest"])),
1626eac174f2Safresh1            'blessed overloaded globs',
1627eac174f2Safresh1            $want);
1628898184e3Ssthen}
1629b8851fccSafresh1#############
16306fb12b70Safresh1{
16316fb12b70Safresh1  # [perl #74798] uncovered behaviour
1632eac174f2Safresh1  my $want = <<'EOW';
16336fb12b70Safresh1#$VAR1 = "\0000";
16346fb12b70Safresh1EOW
16356fb12b70Safresh1  local $Data::Dumper::Useqq = 1;
1636eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs(["\x000"])),
1637eac174f2Safresh1            "\\ octal followed by digit",
1638eac174f2Safresh1            $want);
16396fb12b70Safresh1
1640eac174f2Safresh1  $want = <<'EOW';
16416fb12b70Safresh1#$VAR1 = "\x{100}\0000";
16426fb12b70Safresh1EOW
16436fb12b70Safresh1  local $Data::Dumper::Useqq = 1;
1644eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs(["\x{100}\x000"])),
1645eac174f2Safresh1            "\\ octal followed by digit unicode",
1646eac174f2Safresh1            $want);
16476fb12b70Safresh1
1648eac174f2Safresh1  $want = <<'EOW';
16496fb12b70Safresh1#$VAR1 = "\0\x{660}";
16506fb12b70Safresh1EOW
1651eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs(["\\x00\\x{0660}"])),
1652eac174f2Safresh1            "\\ octal followed by unicode digit",
1653eac174f2Safresh1            $want);
16546fb12b70Safresh1
16556fb12b70Safresh1  # [perl #118933 - handling of digits
1656eac174f2Safresh1  $want = <<'EOW';
16576fb12b70Safresh1#$VAR1 = 0;
16586fb12b70Safresh1#$VAR2 = 1;
16596fb12b70Safresh1#$VAR3 = 90;
16606fb12b70Safresh1#$VAR4 = -10;
16616fb12b70Safresh1#$VAR5 = "010";
16626fb12b70Safresh1#$VAR6 = 112345678;
16636fb12b70Safresh1#$VAR7 = "1234567890";
16646fb12b70Safresh1EOW
1665eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([0, 1, 90, -10, "010", "112345678", "1234567890" ])),
1666eac174f2Safresh1            "numbers and number-like scalars",
1667eac174f2Safresh1            $want);
1668eac174f2Safresh1}
1669eac174f2Safresh1#############
1670eac174f2Safresh1{
1671eac174f2Safresh1  # [github #18614 - handling of Unicode characters in regexes]
1672eac174f2Safresh1  # [github #18764 - ... without breaking subsequent Latin-1]
1673eac174f2Safresh1  if ($] lt '5.010') {
1674eac174f2Safresh1      SKIP_BOTH("Incomplete support for UTF-8 in old perls");
1675eac174f2Safresh1      last;
1676eac174f2Safresh1  }
1677eac174f2Safresh1  my $want = <<"EOW";
1678eac174f2Safresh1#\$VAR1 = [
1679eac174f2Safresh1#  "\\x{41f}",
1680eac174f2Safresh1#  qr/\x{8b80}/,
1681eac174f2Safresh1#  qr/\x{41f}/,
1682eac174f2Safresh1#  qr/\x{b6}/,
1683eac174f2Safresh1#  '\xb6'
1684eac174f2Safresh1#];
1685eac174f2Safresh1EOW
1686eac174f2Safresh1  if ($] lt '5.010001') {
1687eac174f2Safresh1      $want =~ s!qr/!qr/(?-xism:!g;
1688eac174f2Safresh1      $want =~ s!/,!)/,!g;
1689eac174f2Safresh1  }
1690eac174f2Safresh1  elsif ($] gt '5.014') {
1691eac174f2Safresh1      $want =~ s{/(,?)$}{/u$1}mg;
1692eac174f2Safresh1  }
1693eac174f2Safresh1  my $want_xs = $want;
1694eac174f2Safresh1  $want_xs =~ s/'\xb6'/"\\x{b6}"/;
1695eac174f2Safresh1  $want_xs =~ s<([[:^ascii:]])> <sprintf '\\x{%x}', ord $1>ge;
1696eac174f2Safresh1  TEST_BOTH(qq(Data::Dumper->Dumpxs([ [qq/\x{41f}/, qr/\x{8b80}/, qr/\x{41f}/, qr/\x{b6}/, "\xb6"] ])),
1697eac174f2Safresh1            "string with Unicode + regexp with Unicode",
1698eac174f2Safresh1            $want, $want_xs);
1699eac174f2Safresh1}
1700eac174f2Safresh1#############
1701eac174f2Safresh1{
1702eac174f2Safresh1  # [more perl #58608 tests]
1703eac174f2Safresh1  my $bs = "\\\\";
1704eac174f2Safresh1  my $want = <<"EOW";
1705eac174f2Safresh1#\$VAR1 = [
1706eac174f2Safresh1#  qr/ \\/ /,
1707eac174f2Safresh1#  qr/ \\?\\/ /,
1708eac174f2Safresh1#  qr/ $bs\\/ /,
1709eac174f2Safresh1#  qr/ $bs:\\/ /,
1710eac174f2Safresh1#  qr/ \\?$bs:\\/ /,
1711eac174f2Safresh1#  qr/ $bs$bs\\/ /,
1712eac174f2Safresh1#  qr/ $bs$bs:\\/ /,
1713eac174f2Safresh1#  qr/ $bs$bs$bs\\/ /
1714eac174f2Safresh1#];
1715eac174f2Safresh1EOW
1716eac174f2Safresh1  if ($] lt '5.010001') {
1717eac174f2Safresh1      $want =~ s!qr/!qr/(?-xism:!g;
1718eac174f2Safresh1      $want =~ s! /! )/!g;
1719eac174f2Safresh1  }
1720eac174f2Safresh1  TEST_BOTH(qq(Data::Dumper->Dumpxs([ [qr! / !, qr! \\?/ !, qr! $bs/ !, qr! $bs:/ !, qr! \\?$bs:/ !, qr! $bs$bs/ !, qr! $bs$bs:/ !, qr! $bs$bs$bs/ !, ] ])),
1721eac174f2Safresh1            "more perl #58608",
1722eac174f2Safresh1            $want);
1723eac174f2Safresh1}
1724eac174f2Safresh1#############
1725eac174f2Safresh1{
1726eac174f2Safresh1  # [github #18614, github #18764, perl #58608 corner cases]
1727eac174f2Safresh1  if ($] lt '5.010') {
1728eac174f2Safresh1      SKIP_BOTH("Incomplete support for UTF-8 in old perls");
1729eac174f2Safresh1      last;
1730eac174f2Safresh1  }
1731eac174f2Safresh1  my $bs = "\\\\";
1732eac174f2Safresh1  my $want = <<"EOW";
1733eac174f2Safresh1#\$VAR1 = [
1734eac174f2Safresh1#  "\\x{2e18}",
1735eac174f2Safresh1#  qr/ \x{203d}\\/ /,
1736eac174f2Safresh1#  qr/ \\\x{203d}\\/ /,
1737eac174f2Safresh1#  qr/ \\\x{203d}$bs:\\/ /,
1738eac174f2Safresh1#  '\xB6'
1739eac174f2Safresh1#];
1740eac174f2Safresh1EOW
1741eac174f2Safresh1  if ($] lt '5.010001') {
1742eac174f2Safresh1      $want =~ s!qr/!qr/(?-xism:!g;
1743eac174f2Safresh1      $want =~ s!/,!)/,!g;
1744eac174f2Safresh1  }
1745eac174f2Safresh1  elsif ($] gt '5.014') {
1746eac174f2Safresh1      $want =~ s{/(,?)$}{/u$1}mg;
1747eac174f2Safresh1  }
1748eac174f2Safresh1  my $want_xs = $want;
1749eac174f2Safresh1  $want_xs =~ s/'\x{B6}'/"\\x{b6}"/;
1750eac174f2Safresh1  $want_xs =~ s/\x{203D}/\\x{203d}/g;
1751eac174f2Safresh1  TEST_BOTH(qq(Data::Dumper->Dumpxs([ [ '\x{2e18}', qr! \x{203d}/ !, qr! \\\x{203d}/ !, qr! \\\x{203d}$bs:/ !, "\xb6"] ])),
1752eac174f2Safresh1            "github #18614, github #18764, perl #58608 corner cases",
1753eac174f2Safresh1            $want, $want_xs);
1754eac174f2Safresh1}
1755eac174f2Safresh1#############
1756eac174f2Safresh1{
1757eac174f2Safresh1  # [CPAN #84569]
1758eac174f2Safresh1  my $dollar = '${\q($)}';
1759eac174f2Safresh1  my $want = <<"EOW";
1760eac174f2Safresh1#\$VAR1 = [
1761eac174f2Safresh1#  "\\x{2e18}",
1762eac174f2Safresh1#  qr/^\$/,
1763eac174f2Safresh1#  qr/^\$/,
1764eac174f2Safresh1#  qr/${dollar}foo/,
1765eac174f2Safresh1#  qr/\\\$foo/,
1766eac174f2Safresh1#  qr/$dollar \x{B6} /u,
1767eac174f2Safresh1#  qr/$dollar \x{203d} /u,
1768eac174f2Safresh1#  qr/\\\$ \x{203d} /u,
1769eac174f2Safresh1#  qr/\\\\$dollar \x{203d} /u,
1770eac174f2Safresh1#  qr/ \$| \x{203d} /u,
1771eac174f2Safresh1#  qr/ (\$) \x{203d} /u,
1772eac174f2Safresh1#  '\xB6'
1773eac174f2Safresh1#];
1774eac174f2Safresh1EOW
1775eac174f2Safresh1  if ($] lt '5.014') {
1776eac174f2Safresh1      $want =~ s{/u,$}{/,}mg;
1777eac174f2Safresh1  }
1778eac174f2Safresh1  if ($] lt '5.010001') {
1779eac174f2Safresh1      $want =~ s!qr/!qr/(?-xism:!g;
1780eac174f2Safresh1      $want =~ s!/,!)/,!g;
1781eac174f2Safresh1  }
1782eac174f2Safresh1  my $want_xs = $want;
1783eac174f2Safresh1  $want_xs =~ s/'\x{B6}'/"\\x{b6}"/;
1784eac174f2Safresh1  $want_xs =~ s/\x{B6}/\\x{b6}/;
1785eac174f2Safresh1  $want_xs =~ s/\x{203D}/\\x{203d}/g;
1786eac174f2Safresh1  my $have = <<"EOT";
1787eac174f2Safresh1Data::Dumper->Dumpxs([ [
1788eac174f2Safresh1  "\\x{2e18}",
1789eac174f2Safresh1  qr/^\$/,
1790eac174f2Safresh1  qr'^\$',
1791eac174f2Safresh1  qr'\$foo',
1792eac174f2Safresh1  qr/\\\$foo/,
1793eac174f2Safresh1  qr'\$ \x{B6} ',
1794eac174f2Safresh1  qr'\$ \x{203d} ',
1795eac174f2Safresh1  qr/\\\$ \x{203d} /,
1796eac174f2Safresh1  qr'\\\\\$ \x{203d} ',
1797eac174f2Safresh1  qr/ \$| \x{203d} /,
1798eac174f2Safresh1  qr/ (\$) \x{203d} /,
1799eac174f2Safresh1  '\xB6'
1800eac174f2Safresh1] ]);
1801eac174f2Safresh1EOT
1802eac174f2Safresh1  TEST_BOTH($have, "CPAN #84569", $want, $want_xs);
18036fb12b70Safresh1}
1804b8851fccSafresh1#############
18056fb12b70Safresh1{
18066fb12b70Safresh1  # [perl #82948]
18076fb12b70Safresh1  # re::regexp_pattern was moved to universal.c in v5.10.0-252-g192c1e2
18086fb12b70Safresh1  # and apparently backported to maint-5.10
1809eac174f2Safresh1  my $want = $] > 5.010 ? <<'NEW' : <<'OLD';
18106fb12b70Safresh1#$VAR1 = qr/abc/;
18116fb12b70Safresh1#$VAR2 = qr/abc/i;
18126fb12b70Safresh1NEW
18136fb12b70Safresh1#$VAR1 = qr/(?-xism:abc)/;
18146fb12b70Safresh1#$VAR2 = qr/(?i-xsm:abc)/;
18156fb12b70Safresh1OLD
1816eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([ qr/abc/, qr/abc/i ])), "qr// xs", $want);
18176fb12b70Safresh1}
1818b8851fccSafresh1#############
1819b8851fccSafresh1
1820b8851fccSafresh1{
1821b8851fccSafresh1  sub foo {}
1822eac174f2Safresh1  my $want = <<'EOW';
1823b8851fccSafresh1#*a = sub { "DUMMY" };
1824b8851fccSafresh1#$b = \&a;
1825b8851fccSafresh1EOW
1826b8851fccSafresh1
1827eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->new([ \&foo, \\&foo ], [ "*a", "b" ])->Dumpxs),
1828eac174f2Safresh1            "name of code in *foo",
1829eac174f2Safresh1            $want);
1830b8851fccSafresh1}
1831b8851fccSafresh1############# [perl #124091]
1832b8851fccSafresh1{
1833eac174f2Safresh1    my $want = <<'EOT';
1834b8851fccSafresh1#$VAR1 = "\n";
1835b8851fccSafresh1EOT
1836b8851fccSafresh1    local $Data::Dumper::Useqq = 1;
1837eac174f2Safresh1    TEST_BOTH(qq(Data::Dumper::DumperX("\n")),
1838eac174f2Safresh1              '\n alone',
1839eac174f2Safresh1              $want);
1840b8851fccSafresh1}
18419f11ffb7Safresh1#############
1842eac174f2Safresh1{
1843eac174f2Safresh1    no strict 'refs';
1844eac174f2Safresh1    @globs = map { $_, \$_ } map { *$_ } map { $_, "s::$_" }
18459f11ffb7Safresh1        "foo", "\1bar", "L\x{e9}on", "m\x{100}cron", "snow\x{2603}";
1846eac174f2Safresh1}
1847eac174f2Safresh1
1848eac174f2Safresh1{
1849eac174f2Safresh1  my $want = change_glob_expectation(<<'EOT');
18509f11ffb7Safresh1#$globs = [
18519f11ffb7Safresh1#  *::foo,
18529f11ffb7Safresh1#  \*::foo,
18539f11ffb7Safresh1#  *s::foo,
18549f11ffb7Safresh1#  \*s::foo,
18559f11ffb7Safresh1#  *{"::\1bar"},
18569f11ffb7Safresh1#  \*{"::\1bar"},
18579f11ffb7Safresh1#  *{"s::\1bar"},
18589f11ffb7Safresh1#  \*{"s::\1bar"},
18599f11ffb7Safresh1#  *{"::L\351on"},
18609f11ffb7Safresh1#  \*{"::L\351on"},
18619f11ffb7Safresh1#  *{"s::L\351on"},
18629f11ffb7Safresh1#  \*{"s::L\351on"},
18639f11ffb7Safresh1#  *{"::m\x{100}cron"},
18649f11ffb7Safresh1#  \*{"::m\x{100}cron"},
18659f11ffb7Safresh1#  *{"s::m\x{100}cron"},
18669f11ffb7Safresh1#  \*{"s::m\x{100}cron"},
18679f11ffb7Safresh1#  *{"::snow\x{2603}"},
18689f11ffb7Safresh1#  \*{"::snow\x{2603}"},
18699f11ffb7Safresh1#  *{"s::snow\x{2603}"},
18709f11ffb7Safresh1#  \*{"s::snow\x{2603}"}
18719f11ffb7Safresh1#];
18729f11ffb7Safresh1EOT
18739f11ffb7Safresh1  local $Data::Dumper::Useqq = 1;
187456d68f1eSafresh1  if (ord("A") == 65) {
1875eac174f2Safresh1    TEST_BOTH(q(Data::Dumper->Dumpxs([\@globs], ["globs"])), 'globs: Dumpxs()',
1876eac174f2Safresh1              $want);
18779f11ffb7Safresh1  }
187856d68f1eSafresh1  else {
1879eac174f2Safresh1    SKIP_BOTH("ASCII-dependent test");
188056d68f1eSafresh1  }
188156d68f1eSafresh1}
18829f11ffb7Safresh1#############
1883eac174f2Safresh1{
1884eac174f2Safresh1  my $want = change_glob_expectation(<<'EOT');
18859f11ffb7Safresh1#$v = {
18869f11ffb7Safresh1#  a => \*::ppp,
18879f11ffb7Safresh1#  b => \*{'::a/b'},
18889f11ffb7Safresh1#  c => \*{"::a\x{2603}b"}
18899f11ffb7Safresh1#};
18909f11ffb7Safresh1#*::ppp = {
18919f11ffb7Safresh1#  a => 1
18929f11ffb7Safresh1#};
18939f11ffb7Safresh1#*{'::a/b'} = {
18949f11ffb7Safresh1#  b => 3
18959f11ffb7Safresh1#};
18969f11ffb7Safresh1#*{"::a\x{2603}b"} = {
18979f11ffb7Safresh1#  c => 5
18989f11ffb7Safresh1#};
18999f11ffb7Safresh1EOT
19009f11ffb7Safresh1  *ppp = { a => 1 };
1901eac174f2Safresh1  {
1902eac174f2Safresh1    no strict 'refs';
19039f11ffb7Safresh1    *{"a/b"} = { b => 3 };
19049f11ffb7Safresh1    *{"a\x{2603}b"} = { c => 5 };
1905eac174f2Safresh1    $v = { a => \*ppp, b => \*{"a/b"}, c => \*{"a\x{2603}b"} };
19069f11ffb7Safresh1  }
1907eac174f2Safresh1  local $Data::Dumper::Purity = 1;
1908eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([$v], ["v"])),
1909eac174f2Safresh1            'glob purity: Dumpxs()',
1910eac174f2Safresh1            $want);
1911eac174f2Safresh1  $want =~ tr/'/"/;
1912eac174f2Safresh1  local $Data::Dumper::Useqq = 1;
1913eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([$v], ["v"])),
1914eac174f2Safresh1            'glob purity, useqq: Dumpxs()',
1915eac174f2Safresh1            $want);
1916eac174f2Safresh1}
1917eac174f2Safresh1#############
1918eac174f2Safresh1{
1919eac174f2Safresh1  my $want = <<'EOT';
1920eac174f2Safresh1#$3 = {};
1921eac174f2Safresh1#$bang = [];
1922eac174f2Safresh1EOT
1923eac174f2Safresh1  {
1924eac174f2Safresh1    package fish;
1925eac174f2Safresh1
1926eac174f2Safresh1    use overload '""' => sub { return "bang" };
1927eac174f2Safresh1
1928eac174f2Safresh1    sub new {
1929eac174f2Safresh1      return bless qr//;
1930eac174f2Safresh1    }
1931eac174f2Safresh1  }
1932eac174f2Safresh1  # 4.5/1.5 generates the *NV* 3.0, which doesn't set SVf_POK true in 5.20.0+
1933eac174f2Safresh1  # overloaded strings never set SVf_POK true
1934eac174f2Safresh1  TEST_BOTH(q(Data::Dumper->Dumpxs([{}, []], [4.5/1.5, fish->new()])),
1935eac174f2Safresh1            'names that are not simple strings: Dumpxs()',
1936eac174f2Safresh1            $want);
1937eac174f2Safresh1}
1938eac174f2Safresh1
1939eac174f2Safresh1done_testing();
1940