4 require Config; import Config;
5 if ($Config{'extensions'} !~ /\bDevel\/Peek\b/) {
6 print "1..0 # Skip: Devel::Peek was not built\n";
11 my $core = !!$ENV{PERL_CORE};
12 require($core ? '../../t/test.pl' : './t/test.pl');
21 open(SAVERR, ">&STDERR") or die "Can't dup STDERR: $!";
23 # If I reference any lexicals in this, I get the entire outer subroutine (or
24 # MAIN) dumped too, which isn't really what I want, as it's a lot of faff to
33 use constant thr => $Config{useithreads};
37 my $repeat_todo = $_[4];
40 if (open(OUT,">peek$$")) {
41 open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
43 my $sub = eval "sub { Dump $_[1] }";
45 print STDERR "*****\n";
46 # second dump to compare with the first to make sure nothing
52 print STDERR "*****\n";
53 # second dump to compare with the first to make sure nothing
57 open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
59 if (open(IN, "peek$$")) {
61 $pattern =~ s/\$ADDR/0x[[:xdigit:]]+/g;
62 $pattern =~ s/\$FLOAT/(?:\\d*\\.\\d+(?:e[-+]\\d+)?|\\d+)/g;
63 # handle DEBUG_LEAKING_SCALARS prefix
64 $pattern =~ s/^(\s*)(SV =.* at )/(?:$1ALLOCATED at .*?\n)?$1$2/mg;
66 # Need some clear generic mechanism to eliminate (or add) lines
67 # of dump output dependant on perl version. The (previous) use of
68 # things like $IVNV gave the illusion that the string passed in was
69 # a regexp into which variables were interpolated, but this wasn't
70 # actually true as those 'variables' actually also ate the
71 # whitespace on the line. So it seems better to mark lines that
72 # need to be eliminated. I considered (?# ... ) and (?{ ... }),
73 # but whilst embedded code or comment syntax would keep it as a
74 # legitimate regexp, it still isn't true. Seems easier and clearer
75 # things that look like comments.
77 # Could do this is in a s///mge but seems clearer like this:
78 $pattern = join '', map {
79 # If we identify the version condition, take *it* out whatever
82 : $_ # Didn't match, so this line is in
83 } split /^/, $pattern;
85 $pattern =~ s/\$PADMY,/
86 $] < 5.012005 ? 'PADMY,' : '';
89 ($] < 5.011) ? 'RV' : 'IV';
91 $pattern =~ s/^\h+COW_REFCNT = .*\n//mg
92 if $Config{ccflags} =~
93 /-DPERL_(?:OLD_COPY_ON_WRITE|NO_COW)\b/
95 print $pattern, "\n" if $DEBUG;
96 my ($dump, $dump2) = split m/\*\*\*\*\*\n/, scalar <IN>;
97 print $dump, "\n" if $DEBUG;
98 like( $dump, qr/\A$pattern\Z/ms, $_[0])
99 or note("line " . (caller)[2]);
101 local $TODO = $repeat_todo;
102 is($dump2, $dump, "$_[0] (unchanged by dump)")
103 or note("line " . (caller)[2]);
109 die "$0: failed to open peek$$: !\n";
112 die "$0: failed to create peek$$: $!\n";
122 1 while unlink("peek$$");
125 do_test('assignment of immediate constant (string)',
127 'SV = PV\\($ADDR\\) at $ADDR
129 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
136 do_test('immediate constant (string)',
138 'SV = PV\\($ADDR\\) at $ADDR
140 FLAGS = \\(.*POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005
141 FLAGS = \\(.*POK,(?:IsCOW,)?READONLY,PROTECT,pPOK\\) # $] >=5.021005
148 do_test('assignment of immediate constant (integer)',
150 'SV = IV\\($ADDR\\) at $ADDR
152 FLAGS = \\(IOK,pIOK\\)
155 do_test('immediate constant (integer)',
157 'SV = IV\\($ADDR\\) at $ADDR
159 FLAGS = \\(.*IOK,READONLY,pIOK\\) # $] < 5.021005
160 FLAGS = \\(.*IOK,READONLY,PROTECT,pIOK\\) # $] >=5.021005
163 do_test('assignment of immediate constant (integer)',
165 'SV = IV\\($ADDR\\) at $ADDR
167 FLAGS = \\($PADMY,IOK,pIOK\\)
170 # If perl is built with PERL_PRESERVE_IVUV then maths is done as integers
171 # where possible and this scalar will be an IV. If NO_PERL_PRESERVE_IVUV then
172 # maths is done in floating point always, and this scalar will be an NV.
173 # ([NI]) captures the type, referred to by \1 in this regexp and $type for
174 # building subsequent regexps.
175 my $type = do_test('result of addition',
177 'SV = ([NI])V\\($ADDR\\) at $ADDR
179 FLAGS = \\(PADTMP,\1OK,p\1OK\\) # $] < 5.019003
180 FLAGS = \\(\1OK,p\1OK\\) # $] >=5.019003
185 do_test('floating point value',
188 || $Config{ccflags} =~ /-DPERL_(?:NO_COW|OLD_COPY_ON_WRITE)\b/
190 'SV = PVNV\\($ADDR\\) at $ADDR
192 FLAGS = \\(NOK,pNOK\\)
194 NV = 789\\.(?:1(?:000+\d+)?|0999+\d+)
199 'SV = PVNV\\($ADDR\\) at $ADDR
201 FLAGS = \\(NOK,pNOK\\)
203 NV = 789\\.(?:1(?:000+\d+)?|0999+\d+)
206 do_test('integer constant',
208 'SV = IV\\($ADDR\\) at $ADDR
210 FLAGS = \\(.*IOK,READONLY,pIOK\\) # $] < 5.021005
211 FLAGS = \\(.*IOK,READONLY,PROTECT,pIOK\\) # $] >=5.021005
216 'SV = NULL\\(0x0\\) at $ADDR
218 FLAGS = \\(READONLY\\) # $] < 5.021005
219 FLAGS = \\(READONLY,PROTECT\\) # $] >=5.021005
222 do_test('reference to scalar',
224 'SV = $RV\\($ADDR\\) at $ADDR
228 SV = PV\\($ADDR\\) at $ADDR
230 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
240 SV = PVNV\\($ADDR\\) at $ADDR
242 FLAGS = \\(IOK,NOK,pIOK,pNOK\\)
248 SV = IV\\($ADDR\\) at $ADDR
250 FLAGS = \\(IOK,pIOK\\)
253 do_test('reference to array',
255 'SV = $RV\\($ADDR\\) at $ADDR
259 SV = PVAV\\($ADDR\\) at $ADDR
267 SV = IV\\($ADDR\\) at $ADDR
269 FLAGS = \\(IOK,pIOK\\)
271 Elt No. 1' . $c_pattern);
273 do_test('reference to hash',
275 'SV = $RV\\($ADDR\\) at $ADDR
279 SV = PVHV\\($ADDR\\) at $ADDR
281 FLAGS = \\(SHAREKEYS\\)
282 ARRAY = $ADDR \\(0:7, 1:1\\)
283 hash quality = 100.0%
287 Elt "123" HASH = $ADDR' . $c_pattern,
290 && 'The hash iterator used in dump.c sets the OOK flag');
292 do_test('reference to anon sub with empty prototype',
294 'SV = $RV\\($ADDR\\) at $ADDR
298 SV = PVCV\\($ADDR\\) at $ADDR
300 FLAGS = \\($PADMY,POK,pPOK,ANON,WEAKOUTSIDE,CVGV_RC\\) # $] < 5.015 || !thr
301 FLAGS = \\($PADMY,POK,pPOK,ANON,WEAKOUTSIDE,CVGV_RC,DYNFILE\\) # $] >= 5.015 && thr
303 COMP_STASH = $ADDR\\t"main"
304 START = $ADDR ===> \\d+
306 GVGV::GV = $ADDR\\t"main" :: "__ANON__[^"]*"
307 FILE = ".*\\b(?i:peek\\.t)"
311 FLAGS = 0x490 # $] < 5.015 || !thr
312 FLAGS = 0x1490 # $] >= 5.015 && thr
315 PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\)
316 OUTSIDE = $ADDR \\(MAIN\\)');
318 do_test('reference to named subroutine without prototype',
320 'SV = $RV\\($ADDR\\) at $ADDR
324 SV = PVCV\\($ADDR\\) at $ADDR
326 FLAGS = \\((?:HASEVAL(?:,NAMED)?)?\\) # $] < 5.015 || !thr
327 FLAGS = \\(DYNFILE(?:,HASEVAL(?:,NAMED)?)?\\) # $] >= 5.015 && thr
328 COMP_STASH = $ADDR\\t"main"
329 START = $ADDR ===> \\d+
331 NAME = "do_test" # $] >=5.021004
332 GVGV::GV = $ADDR\\t"main" :: "do_test" # $] < 5.021004
333 FILE = ".*\\b(?i:peek\\.t)"
337 FLAGS = 0x(?:[c4]00)?0 # $] < 5.015 || !thr
338 FLAGS = 0x[cd145]000 # $] >= 5.015 && thr
341 PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\)
342 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$todo"
343 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$repeat_todo"
344 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$pattern"
345 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$do_eval"
346 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$sub"
347 \\d+\\. $ADDR<\\d+> FAKE "\\$DEBUG" flags=0x0 index=0
348 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$dump"
349 \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$dump2"
350 OUTSIDE = $ADDR \\(MAIN\\)');
353 # note the conditionals on ENGINE and INTFLAGS were introduced in 5.19.9
354 do_test('reference to regexp',
356 'SV = $RV\\($ADDR\\) at $ADDR
360 SV = REGEXP\\($ADDR\\) at $ADDR
362 FLAGS = \\(OBJECT,POK,FAKE,pPOK\\) # $] < 5.017006
363 FLAGS = \\(OBJECT,FAKE\\) # $] >= 5.017006
364 PV = $ADDR "\\(\\?\\^:tic\\)"
366 LEN = 0 # $] < 5.017006
367 STASH = $ADDR\\t"Regexp"'
371 EXTFLAGS = 0x680000 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
372 (?: ENGINE = $ADDR \(STANDARD\)
373 )? INTFLAGS = 0x0(?: \(\))?
386 )? MOTHER_RE = $ADDR'
387 . ($] < 5.019003 ? '' : '
388 SV = REGEXP\($ADDR\) at $ADDR
391 PV = $ADDR "\(\?\^:tic\)"
394 EXTFLAGS = 0x680000 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
395 (?: ENGINE = $ADDR \(STANDARD\)
396 )? INTFLAGS = 0x0(?: \(\))?
415 SAVED_COPY = 0x0)?') . '
424 do_test('reference to regexp',
426 'SV = $RV\\($ADDR\\) at $ADDR
430 SV = PVMG\\($ADDR\\) at $ADDR
432 FLAGS = \\(OBJECT,SMG\\)
438 MG_TYPE = PERL_MAGIC_qr\(r\)
442 STASH = $ADDR\\t"Regexp"');
445 do_test('reference to blessed hash',
447 'SV = $RV\\($ADDR\\) at $ADDR
451 SV = PVHV\\($ADDR\\) at $ADDR
453 FLAGS = \\(OBJECT,SHAREKEYS\\)
454 STASH = $ADDR\\t"Tac"
461 : 'The hash iterator used in dump.c sets the OOK flag');
465 'SV = PVGV\\($ADDR\\) at $ADDR
467 FLAGS = \\(MULTI(?:,IN_PAD)?\\)
470 GvSTASH = $ADDR\\t"main"
471 FLAGS = $ADDR # $] >=5.021004
481 GPFLAGS = 0x0 \(\) # $] >= 5.021004
483 FILE = ".*\\b(?i:peek\\.t)"
484 FLAGS = $ADDR # $] < 5.021004
487 if (ord('A') == 193) {
488 do_test('string with Unicode',
489 chr(256).chr(0).chr(512),
490 'SV = PV\\($ADDR\\) at $ADDR
492 FLAGS = \\((?:PADTMP,)?POK,READONLY,pPOK,UTF8\\) # $] < 5.019003
493 FLAGS = \\((?:PADTMP,)?POK,(?:IsCOW,)?pPOK,UTF8\\) # $] >=5.019003
494 PV = $ADDR "\\\214\\\101\\\0\\\235\\\101"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\]
497 COW_REFCNT = 1 # $] < 5.019007
500 do_test('string with Unicode',
501 chr(256).chr(0).chr(512),
502 'SV = PV\\($ADDR\\) at $ADDR
504 FLAGS = \\((?:PADTMP,)?POK,READONLY,pPOK,UTF8\\) # $] < 5.019003
505 FLAGS = \\((?:PADTMP,)?POK,(?:IsCOW,)?pPOK,UTF8\\) # $] >=5.019003
506 PV = $ADDR "\\\304\\\200\\\0\\\310\\\200"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\]
509 COW_REFCNT = 1 # $] < 5.019007
513 if (ord('A') == 193) {
514 do_test('reference to hash containing Unicode',
515 {chr(256)=>chr(512)},
516 'SV = $RV\\($ADDR\\) at $ADDR
520 SV = PVHV\\($ADDR\\) at $ADDR
522 FLAGS = \\(SHAREKEYS,HASKFLAGS\\)
523 ARRAY = $ADDR \\(0:7, 1:1\\)
524 hash quality = 100.0%
528 Elt "\\\214\\\101" \[UTF8 "\\\x\{100\}"\] HASH = $ADDR
529 SV = PV\\($ADDR\\) at $ADDR
531 FLAGS = \\(POK,(?:IsCOW,)?pPOK,UTF8\\)
532 PV = $ADDR "\\\235\\\101"\\\0 \[UTF8 "\\\x\{200\}"\]
535 COW_REFCNT = 1 # $] < 5.019007
539 : 'The hash iterator used in dump.c sets the OOK flag');
541 do_test('reference to hash containing Unicode',
542 {chr(256)=>chr(512)},
543 'SV = $RV\\($ADDR\\) at $ADDR
547 SV = PVHV\\($ADDR\\) at $ADDR
549 FLAGS = \\(SHAREKEYS,HASKFLAGS\\)
550 ARRAY = $ADDR \\(0:7, 1:1\\)
551 hash quality = 100.0%
555 Elt "\\\304\\\200" \[UTF8 "\\\x\{100\}"\] HASH = $ADDR
556 SV = PV\\($ADDR\\) at $ADDR
558 FLAGS = \\(POK,(?:IsCOW,)?pPOK,UTF8\\)
559 PV = $ADDR "\\\310\\\200"\\\0 \[UTF8 "\\\x\{200\}"\]
562 COW_REFCNT = 1 # $] < 5.019007
566 : 'The hash iterator used in dump.c sets the OOK flag');
571 do_test('scalar with pos magic',
573 'SV = PVMG\\($ADDR\\) at $ADDR
575 FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?pPOK\\)
583 MG_VIRTUAL = &PL_vtbl_mglob
584 MG_TYPE = PERL_MAGIC_regex_global\\(g\\)
585 MG_FLAGS = 0x01 # $] < 5.019003
586 MG_FLAGS = 0x41 # $] >=5.019003
588 BYTES # $] >=5.019003
592 # TAINTEDDIR is not set on: OS2, AMIGAOS, WIN32, MSDOS
593 # environment variables may be invisibly case-forced, hence the (?i:PATH)
594 # C<scalar(@ARGV)> is turned into an IV on VMS hence the (?:IV)?
595 # Perl 5.18 ensures all env vars end up as strings only, hence the (?:,pIOK)?
596 # Perl 5.18 ensures even magic vars have public OK, hence the (?:,POK)?
597 # VMS is setting FAKE and READONLY flags. What VMS uses for storing
598 # ENV hashes is also not always null terminated.
601 # Save and restore PATH, since fresh_perl ends up using that in Windows.
602 my $path = $ENV{PATH};
603 do_test('tainted value in %ENV',
604 $ENV{PATH}=@ARGV, # scalar(@ARGV) is a handy known tainted value
605 'SV = PVMG\\($ADDR\\) at $ADDR
607 FLAGS = \\(GMG,SMG,RMG(?:,POK)?(?:,pIOK)?,pPOK\\)
614 MG_VIRTUAL = &PL_vtbl_envelem
615 MG_TYPE = PERL_MAGIC_envelem\\(e\\)
619 MG_PTR = $ADDR (?:"(?i:PATH)"|=> HEf_SVKEY
620 SV = PV(?:IV)?\\($ADDR\\) at $ADDR
622 FLAGS = \\((?:TEMP,)?POK,(?:FAKE,READONLY,)?pPOK\\)
624 )? PV = $ADDR "(?i:PATH)"(?:\\\0)?
628 MG_VIRTUAL = &PL_vtbl_taint
629 MG_TYPE = PERL_MAGIC_taint\\(t\\)');
633 do_test('blessed reference',
634 bless(\\undef, 'Foobar'),
635 'SV = $RV\\($ADDR\\) at $ADDR
639 SV = PVMG\\($ADDR\\) at $ADDR
641 FLAGS = \\(OBJECT,ROK\\)
645 SV = NULL\\(0x0\\) at $ADDR
647 FLAGS = \\(READONLY\\) # $] < 5.021005
648 FLAGS = \\(READONLY,PROTECT\\) # $] >=5.021005
652 STASH = $ADDR\s+"Foobar"');
658 do_test('constant subroutine',
660 'SV = $RV\\($ADDR\\) at $ADDR
664 SV = PVCV\\($ADDR\\) at $ADDR
666 FLAGS = \\(POK,pPOK,CONST,ISXSUB\\) # $] < 5.015
667 FLAGS = \\(POK,pPOK,CONST,DYNFILE,ISXSUB\\) # $] >= 5.015
669 COMP_STASH = 0x0 # $] < 5.021004
670 COMP_STASH = $ADDR "main" # $] >=5.021004
672 XSUBANY = $ADDR \\(CONST SV\\)
673 SV = PV\\($ADDR\\) at $ADDR
675 FLAGS = \\(.*POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005
676 FLAGS = \\(.*POK,(?:IsCOW,)?READONLY,PROTECT,pPOK\\) # $] >=5.021005
677 PV = $ADDR "Perl rules"\\\0
681 GVGV::GV = $ADDR\\t"main" :: "const"
682 FILE = ".*\\b(?i:peek\\.t)"
686 FLAGS = 0xc00 # $] < 5.013
687 FLAGS = 0xc # $] >= 5.013 && $] < 5.015
688 FLAGS = 0x100c # $] >= 5.015
690 PADLIST = 0x0 # $] < 5.021006
691 HSCXT = $ADDR # $] >= 5.021006
692 OUTSIDE = 0x0 \\(null\\)');
694 do_test('isUV should show on PVMG',
695 do { my $v = $1; $v = ~0; $v },
696 'SV = PVMG\\($ADDR\\) at $ADDR
698 FLAGS = \\(IOK,pIOK,IsUV\\)
705 'SV = $RV\\($ADDR\\) at $ADDR
709 SV = PVIO\\($ADDR\\) at $ADDR
714 STASH = $ADDR\s+"IO::File"
730 'SV = $RV\\($ADDR\\) at $ADDR
734 SV = PVFM\\($ADDR\\) at $ADDR
736 FLAGS = \\(\\) # $] < 5.015 || !thr
737 FLAGS = \\(DYNFILE\\) # $] >= 5.015 && thr
740 START = $ADDR ===> \\d+
742 GVGV::GV = $ADDR\\t"main" :: "PIE"
743 FILE = ".*\\b(?i:peek\\.t)"(?:
747 FLAGS = 0x0 # $] < 5.015 || !thr
748 FLAGS = 0x1000 # $] >= 5.015 && thr
750 LINES = 0 # $] < 5.017_003
752 PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\)
753 OUTSIDE = $ADDR \\(MAIN\\)');
755 do_test('blessing to a class with embedded NUL characters',
756 (bless {}, "\0::foo::\n::baz::\t::\0"),
757 'SV = $RV\\($ADDR\\) at $ADDR
761 SV = PVHV\\($ADDR\\) at $ADDR
763 FLAGS = \\(OBJECT,SHAREKEYS\\)
764 STASH = $ADDR\\t"\\\\0::foo::\\\\n::baz::\\\\t::\\\\0"
771 : 'The hash iterator used in dump.c sets the OOK flag');
773 do_test('ENAME on a stash',
775 'SV = $RV\\($ADDR\\) at $ADDR
779 SV = PVHV\\($ADDR\\) at $ADDR
781 FLAGS = \\(OOK,SHAREKEYS\\)
782 AUX_FLAGS = 0 # $] > 5.019008
791 ENAME = "RWOM" # $] > 5.012
796 do_test('ENAMEs on a stash',
798 'SV = $RV\\($ADDR\\) at $ADDR
802 SV = PVHV\\($ADDR\\) at $ADDR
804 FLAGS = \\(OOK,SHAREKEYS\\)
805 AUX_FLAGS = 0 # $] > 5.019008
814 NAMECOUNT = 2 # $] > 5.012
815 ENAME = "RWOM", "KLANK" # $] > 5.012
820 do_test('ENAMEs on a stash with no NAME',
822 'SV = $RV\\($ADDR\\) at $ADDR
826 SV = PVHV\\($ADDR\\) at $ADDR
828 FLAGS = \\(OOK,SHAREKEYS\\) # $] < 5.017
829 FLAGS = \\(OOK,OVERLOAD,SHAREKEYS\\) # $] >=5.017 && $]<5.021005
830 FLAGS = \\(OOK,SHAREKEYS,OVERLOAD\\) # $] >=5.021005
831 AUX_FLAGS = 0 # $] > 5.019008
839 NAMECOUNT = -3 # $] > 5.012
840 ENAME = "RWOM", "KLANK" # $] > 5.012
843 my %small = ("Perl", "Rules", "Beer", "Foamy");
845 do_test('small hash',
847 'SV = $RV\\($ADDR\\) at $ADDR
851 SV = PVHV\\($ADDR\\) at $ADDR
853 FLAGS = \\($PADMY,SHAREKEYS\\)
854 ARRAY = $ADDR \\(0:[67],.*\\)
855 hash quality = [0-9.]+%
859 (?: Elt "(?:Perl|Beer)" HASH = $ADDR
860 SV = PV\\($ADDR\\) at $ADDR
862 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
863 PV = $ADDR "(?:Rules|Foamy)"\\\0
871 do_test('small hash after keys',
873 'SV = $RV\\($ADDR\\) at $ADDR
877 SV = PVHV\\($ADDR\\) at $ADDR
879 FLAGS = \\($PADMY,OOK,SHAREKEYS\\)
880 AUX_FLAGS = 0 # $] > 5.019008
881 ARRAY = $ADDR \\(0:[67],.*\\)
882 hash quality = [0-9.]+%
889 (?: Elt "(?:Perl|Beer)" HASH = $ADDR
890 SV = PV\\($ADDR\\) at $ADDR
892 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
893 PV = $ADDR "(?:Rules|Foamy)"\\\0
901 do_test('small hash after keys and scalar',
903 'SV = $RV\\($ADDR\\) at $ADDR
907 SV = PVHV\\($ADDR\\) at $ADDR
909 FLAGS = \\($PADMY,OOK,SHAREKEYS\\)
910 AUX_FLAGS = 0 # $] > 5.019008
911 ARRAY = $ADDR \\(0:[67],.*\\)
912 hash quality = [0-9.]+%
919 (?: Elt "(?:Perl|Beer)" HASH = $ADDR
920 SV = PV\\($ADDR\\) at $ADDR
922 FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
923 PV = $ADDR "(?:Rules|Foamy)"\\\0
929 # Dump with arrays, hashes, and operator return values
931 do_test('Dump @array', '@array', <<'ARRAY', '', '', 1);
932 SV = PVAV\($ADDR\) at $ADDR
940 SV = IV\($ADDR\) at $ADDR
945 SV = IV\($ADDR\) at $ADDR
950 SV = IV\($ADDR\) at $ADDR
956 do_test('Dump @array,1', '@array,1', <<'ARRAY', '', '', 1);
957 SV = PVAV\($ADDR\) at $ADDR
965 SV = IV\($ADDR\) at $ADDR
972 do_test('Dump %hash', '%hash', <<'HASH', '', '', 1);
973 SV = PVHV\($ADDR\) at $ADDR
975 FLAGS = \(SHAREKEYS\)
976 ARRAY = $ADDR \(0:7, 1:1\)
977 hash quality = 100.0%
982 SV = IV\($ADDR\) at $ADDR
989 do_test('rvalue substr', 'substr $_, 1, 2', <<'SUBSTR', '', '', 1);
990 SV = PV\($ADDR\) at $ADDR
992 FLAGS = \(PADTMP,POK,pPOK\)
998 # Dump with no arguments
1000 like $@, qr/^Not enough arguments for Devel::Peek::Dump/, 'Dump;';
1002 like $@, qr/^Not enough arguments for Devel::Peek::Dump/, 'Dump()';
1005 skip "Not built with usemymalloc", 2
1006 unless $Config{usemymalloc} eq 'y';
1007 my $x = __PACKAGE__;
1008 ok eval { fill_mstats($x); 1 }, 'fill_mstats on COW scalar'
1011 ok eval { fill_mstats($y); 1 }, 'fill_mstats on undef scalar';
1014 # This is more a test of fbm_compile/pp_study (non) interaction than dumping
1015 # prowess, but short of duplicating all the gubbins of this file, I can't see
1016 # a way to make a better place for it:
1020 # The length of the rhs string must be such that if chr() is applied to it
1021 # doesn't yield a character with a backslash mnemonic. For example, if it
1022 # were 'rules' instead of 'rule', it would have 5 characters, and on
1023 # EBCDIC, chr(5) is \t. The dumping code would translate all the 5's in
1024 # MG_PTR into "\t", and this test code would be expecting \5's, so the
1025 # tests would fail. No platform that Perl works on translates chr(4) into
1031 unless ($Config{useithreads}) {
1032 # These end up as copies in pads under ithreads, which rather defeats the
1033 # the point of what we're trying to test here.
1035 do_test('regular string constant', perl,
1036 'SV = PV\\($ADDR\\) at $ADDR
1038 FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005
1039 FLAGS = \\(POK,(?:IsCOW,)?READONLY,pPOK\\) # $] >=5.021005
1040 PV = $ADDR "rule"\\\0
1046 eval 'index "", perl';
1048 do_test('string constant now an FBM', perl,
1049 'SV = PVMG\\($ADDR\\) at $ADDR
1051 FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?READONLY,(?:IsCOW,)?pPOK,VALID\\)
1052 PV = $ADDR "rule"\\\0
1057 MG_VIRTUAL = &PL_vtbl_regexp
1058 MG_TYPE = PERL_MAGIC_bm\\(B\\)
1060 MG_PTR = $ADDR "(?:\\\\\d){256}"
1061 RARE = \d+ # $] < 5.019002
1062 PREVIOUS = 1 # $] < 5.019002
1066 is(study perl, '', "Not allowed to study an FBM");
1068 do_test('string constant still an FBM', perl,
1069 'SV = PVMG\\($ADDR\\) at $ADDR
1071 FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?READONLY,(?:IsCOW,)?pPOK,VALID\\)
1072 PV = $ADDR "rule"\\\0
1077 MG_VIRTUAL = &PL_vtbl_regexp
1078 MG_TYPE = PERL_MAGIC_bm\\(B\\)
1080 MG_PTR = $ADDR "(?:\\\\\d){256}"
1081 RARE = \d+ # $] < 5.019002
1082 PREVIOUS = 1 # $] < 5.019002
1086 do_test('regular string constant', beer,
1087 'SV = PV\\($ADDR\\) at $ADDR
1089 FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005
1090 FLAGS = \\(POK,(?:IsCOW,)?READONLY,pPOK\\) # $] >=5.021005
1091 PV = $ADDR "foam"\\\0
1097 is(study beer, 1, "Our studies were successful");
1099 do_test('string constant quite unaffected', beer, 'SV = PV\\($ADDR\\) at $ADDR
1101 FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\) # $] < 5.021005
1102 FLAGS = \\(POK,(?:IsCOW,)?READONLY,pPOK\\) # $] >=5.021005
1103 PV = $ADDR "foam"\\\0
1109 my $want = 'SV = PVMG\\($ADDR\\) at $ADDR
1111 FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?READONLY,(?:IsCOW,)?pPOK,VALID\\)
1112 PV = $ADDR "foam"\\\0
1117 MG_VIRTUAL = &PL_vtbl_regexp
1118 MG_TYPE = PERL_MAGIC_bm\\(B\\)
1120 MG_PTR = $ADDR "(?:\\\\\d){256}"
1121 RARE = \d+ # $] < 5.019002
1122 PREVIOUS = \d+ # $] < 5.019002
1126 is (eval 'index "not too foamy", beer', 8, 'correct index');
1128 do_test('string constant now FBMed', beer, $want);
1132 is(study $pie, 1, "Our studies were successful");
1134 do_test('string constant still FBMed', beer, $want);
1136 do_test('second string also unaffected', $pie, 'SV = PV\\($ADDR\\) at $ADDR
1138 FLAGS = \\($PADMY,POK,(?:IsCOW,)?pPOK\\)
1139 PV = $ADDR "good"\\\0
1146 # (One block of study tests removed when study was made a no-op.)
1149 open(OUT,">peek$$") or die "Failed to open peek $$: $!";
1150 open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
1152 open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
1153 pass "no crash with DeadCode";
1156 # note the conditionals on ENGINE and INTFLAGS were introduced in 5.19.9
1157 do_test('UTF-8 in a regular expression',
1159 'SV = IV\($ADDR\) at $ADDR
1163 SV = REGEXP\($ADDR\) at $ADDR
1165 FLAGS = \(OBJECT,FAKE,UTF8\)
1166 PV = $ADDR "\(\?\^u:\\\\\\\\x\{100\}\)" \[UTF8 "\(\?\^u:\\\\\\\\x\{100\}\)"\]
1168 STASH = $ADDR "Regexp"
1169 COMPFLAGS = 0x0 \(\)
1170 EXTFLAGS = $ADDR \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
1171 (?: ENGINE = $ADDR \(STANDARD\)
1172 )? INTFLAGS = 0x0(?: \(\))?
1185 )? MOTHER_RE = $ADDR'
1186 . ($] < 5.019003 ? '' : '
1187 SV = REGEXP\($ADDR\) at $ADDR
1190 PV = $ADDR "\(\?\^u:\\\\\\\\x\{100\}\)" \[UTF8 "\(\?\^u:\\\\\\\\x\{100\}\)"\]
1192 COMPFLAGS = 0x0 \(\)
1193 EXTFLAGS = $ADDR \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
1194 (?: ENGINE = $ADDR \(STANDARD\)
1195 )? INTFLAGS = 0x0(?: \(\))?
1214 SAVED_COPY = 0x0)?') . '
1223 { # perl #117793: Extend SvREFCNT* to work on any perl variable type
1225 my $base_count = Devel::Peek::SvREFCNT(%hash);
1227 is(Devel::Peek::SvREFCNT(%hash), $base_count + 1, "SvREFCNT on non-scalar");
1228 ok(!eval { &Devel::Peek::SvREFCNT(1) }, "requires prototype");
1235 open(OUT,">peek$$") or die $!;
1236 open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
1238 open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
1240 open(IN, "peek$$") or die $!;
1241 my $dump = do { local $/; <IN> };
1243 1 while unlink "peek$$";
1250 eval "sub $x {}; 1" or die $@;
1255 _dump(_get_coderef("\x{df}::\xdf")),
1256 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\xdf" :: "\xdf"/,
1257 "GVGV's are correctly escaped for latin1 :: latin1",
1261 _dump(_get_coderef("\x{30cd}::\x{30cd}")),
1262 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cd}" :: "\x{30cd}"/,
1263 "GVGV's are correctly escaped for UTF8 :: UTF8",
1267 _dump(_get_coderef("\x{df}::\x{30cd}")),
1268 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\xdf" :: "\x{30cd}"/,
1269 "GVGV's are correctly escaped for latin1 :: UTF8",
1273 _dump(_get_coderef("\x{30cd}::\x{df}")),
1274 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cd}" :: "\xdf"/,
1275 "GVGV's are correctly escaped for UTF8 :: latin1",
1279 _dump(_get_coderef("\x{30cb}::\x{df}::\x{30cd}")),
1280 qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cb}::\x{df}" :: "\x{30cd}"/,
1281 "GVGV's are correctly escaped for UTF8 :: latin 1 :: UTF8",
1284 my $dump = _dump(*{"\x{30cb}::\x{df}::\x{30dc}"});
1288 qr/NAME = \Q"\x{30dc}"/,
1289 "NAME is correctly escaped for UTF8 globs",
1294 qr/GvSTASH = 0x[[:xdigit:]]+\s+\Q"\x{30cb}::\x{df}"/,
1295 "GvSTASH is correctly escaped for UTF8 globs"
1300 qr/EGV = 0x[[:xdigit:]]+\s+\Q"\x{30dc}"/,
1301 "EGV is correctly escaped for UTF8 globs"
1304 $dump = _dump(*{"\x{df}::\x{30cc}"});
1308 qr/NAME = \Q"\x{30cc}"/,
1309 "NAME is correctly escaped for UTF8 globs with latin1 stashes",
1314 qr/GvSTASH = 0x[[:xdigit:]]+\s+\Q"\xdf"/,
1315 "GvSTASH is correctly escaped for UTF8 globs with latin1 stashes"
1320 qr/EGV = 0x[[:xdigit:]]+\s+\Q"\x{30cc}"/,
1321 "EGV is correctly escaped for UTF8 globs with latin1 stashes"
1325 _dump(bless {}, "\0::\1::\x{30cd}"),
1326 qr/STASH = 0x[[:xdigit:]]+\s+\Q"\0::\x{01}::\x{30cd}"/,
1327 "STASH for blessed hashrefs is correct"
1330 BEGIN { $::{doof} = "\0\1\x{30cd}" }
1333 qr/PROTOTYPE = \Q"\0\x{01}\x{30cd}"/,
1334 "PROTOTYPE is escaped correctly"
1338 my $coderef = eval <<"EOP";
1339 use feature 'lexical_subs';
1340 no warnings 'experimental::lexical_subs';
1341 my sub bar (\$\x{30cd}) {1}; \\&bar
1345 qr/PROTOTYPE = "\$\Q\x{30cd}"/,
1346 "PROTOTYPE works on lexical subs"
1351 eval "sub $_[0] { my \$x; \$x++; return sub { eval q{\$x} } } $_[0]()";
1353 sub basic { my $x; return eval q{sub { eval q{$x} }} }
1356 qr/OUTSIDE = 0x[[:xdigit:]]+\s+\Q(basic)/,
1361 _dump(get_outside("\x{30ce}")),
1362 qr/OUTSIDE = 0x[[:xdigit:]]+\s+\Q(\x{30ce})/,
1363 'OUTSIDE + UTF8 works'
1366 # TODO AUTOLOAD = stashname, which requires using a XS autoload
1367 # and calling Dump() on the cv
1371 sub test_utf8_stashes {
1372 my ($stash_name, $test) = @_;
1374 $dump = _dump(\%{"${stash_name}::"});
1376 my $format = utf8::is_utf8($stash_name) ? '\x{%2x}' : '\x%2x';
1377 $escaped_stash_name = join "", map {
1378 $_ eq ':' ? $_ : sprintf $format, ord $_
1379 } split //, $stash_name;
1383 qr/\QNAME = "$escaped_stash_name"/,
1384 "NAME is correct escaped for $test"
1389 qr/\QENAME = "$escaped_stash_name"/,
1390 "ENAME is correct escaped for $test"
1395 [ "\x{30cd}", "UTF8 stashes" ],
1396 [ "\x{df}", "latin 1 stashes" ],
1397 [ "\x{df}::\x{30cd}", "latin1 + UTF8 stashes" ],
1398 [ "\x{30cd}::\x{df}", "UTF8 + latin1 stashes" ],
1400 test_utf8_stashes(@$test);
1405 my $runperl_args = { switches => ['-Ilib'] };
1407 my ($prog, $expected, $name, $test) = @_;
1410 my $u = 'use Devel::Peek "DumpProg"; DumpProg();';
1412 # Interface between Test::Builder & test.pl
1413 my $builder = Test::More->builder();
1414 t::curr_test($builder->current_test() + 1);
1416 utf8::encode($prog);
1418 if ( $test eq 'is' ) {
1419 t::fresh_perl_is($prog . $u, $expected, $runperl_args, $name)
1422 t::fresh_perl_like($prog . $u, $expected, $runperl_args, $name)
1425 $builder->current_test(t::curr_test() - 1);
1428 my $threads = $Config{'useithreads'};
1433 qr/PACKAGE = "test"/,
1434 "DumpProg() + package declaration"
1437 "use utf8; package \x{30cd};",
1438 qr/PACKAGE = "\\x\Q{30cd}"/,
1439 "DumpProg() + UTF8 package declaration"
1442 "use utf8; sub \x{30cc}::\x{30cd} {1}; \x{30cc}::\x{30cd};",
1443 ($threads ? qr/PADIX = \d+/ : qr/GV = \Q\x{30cc}::\x{30cd}\E/)
1446 "use utf8; \x{30cc}: { last \x{30cc} }",
1447 qr/LABEL = \Q"\x{30cc}"/
1451 test_DumpProg(@$test);
1455 local $TODO = 'This gets mangled by the current pipe implementation' if $^O eq 'VMS';
1457 dumpindent is 4 at -e line 1.
1459 1 TYPE = leave ===> NULL
1461 FLAGS = (VOID,KIDS,PARENS,SLABBED)
1465 2 TYPE = enter ===> 3
1466 FLAGS = (UNKNOWN,SLABBED,MORESIB)
1469 3 TYPE = nextstate ===> 4
1470 FLAGS = (VOID,SLABBED,MORESIB)
1475 5 TYPE = entersub ===> 1
1477 FLAGS = (VOID,KIDS,STACKED,SLABBED)
1480 6 TYPE = null ===> (5)
1482 FLAGS = (UNKNOWN,KIDS,SLABBED)
1484 4 TYPE = pushmark ===> 7
1485 FLAGS = (SCALAR,SLABBED,MORESIB)
1488 8 TYPE = null ===> (6)
1490 FLAGS = (SCALAR,KIDS,SLABBED)
1494 FLAGS = (SCALAR,SLABBED)
1503 $e =~ s/GV_OR_PADIX/$threads ? "PADIX = 2" : "GV = t::DumpProg"/e;
1504 $e =~ s/.*PRIVATE = \(0x1\).*\n// if $] < 5.021004;
1505 my $out = t::runperl
1506 switches => ['-Ilib'],
1507 prog => 'package t; use Devel::Peek q-DumpProg-; DumpProg();',
1509 $out =~ s/ *SEQ = .*\n//;
1510 is $out, $e, "DumpProg() has no 'Attempt to free X prematurely' warning";