This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Devel::Peek: test 2-arg form of Dump
[perl5.git] / ext / Devel-Peek / t / Peek.t
1 #!./perl -T
2
3 BEGIN {
4     require Config; import Config;
5     if ($Config{'extensions'} !~ /\bDevel\/Peek\b/) {
6         print "1..0 # Skip: Devel::Peek was not built\n";
7         exit 0;
8     }
9     {
10     package t;
11        my $core = !!$ENV{PERL_CORE};
12        require($core ? '../../t/test.pl' : './t/test.pl');
13     }
14 }
15
16 use Test::More;
17
18 use Devel::Peek;
19
20 our $DEBUG = 0;
21 open(SAVERR, ">&STDERR") or die "Can't dup STDERR: $!";
22
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
25 # maintain that.
26 format PIE =
27 Pie     @<<<<<
28 $::type
29 Good    @>>>>>
30 $::mmmm
31 .
32
33 use constant thr => $Config{useithreads};
34
35 sub do_test {
36     my $todo = $_[3];
37     my $repeat_todo = $_[4];
38     my $pattern = $_[2];
39     my $do_eval = $_[5];
40     if (open(OUT,">peek$$")) {
41         open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
42         if ($do_eval) {
43             my $sub = eval "sub { Dump $_[1] }";
44             $sub->();
45             print STDERR "*****\n";
46             # second dump to compare with the first to make sure nothing
47             # changed.
48             $sub->();
49         }
50         else {
51             Dump($_[1]);
52             print STDERR "*****\n";
53             # second dump to compare with the first to make sure nothing
54             # changed.
55             Dump($_[1]);
56         }
57         open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
58         close(OUT);
59         if (open(IN, "peek$$")) {
60             local $/;
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;
65
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.
76
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
80                 s/\s*# (\$].*)$//
81                     ? (eval $1 ? $_ : '')
82                     : $_ # Didn't match, so this line is in
83             } split /^/, $pattern;
84             
85             $pattern =~ s/\$PADMY/
86                 ($] < 5.009) ? 'PADBUSY,PADMY' : 'PADMY';
87             /mge;
88             $pattern =~ s/\$PADTMP/
89                 ($] < 5.009) ? 'PADBUSY,PADTMP' : 'PADTMP';
90             /mge;
91             $pattern =~ s/\$RV/
92                 ($] < 5.011) ? 'RV' : 'IV';
93             /mge;
94             $pattern =~ s/^\h+COW_REFCNT = .*\n//mg
95                 if $Config{ccflags} =~
96                         /-DPERL_(?:OLD_COPY_ON_WRITE|NO_COW)/
97                             || $] < 5.019003;
98             print $pattern, "\n" if $DEBUG;
99             my ($dump, $dump2) = split m/\*\*\*\*\*\n/, scalar <IN>;
100             print $dump, "\n"    if $DEBUG;
101             like( $dump, qr/\A$pattern\Z/ms, $_[0])
102               or note("line " . (caller)[2]);
103
104             local $TODO = $repeat_todo;
105             is($dump2, $dump, "$_[0] (unchanged by dump)")
106               or note("line " . (caller)[2]);
107
108             close(IN);
109
110             return $1;
111         } else {
112             die "$0: failed to open peek$$: !\n";
113         }
114     } else {
115         die "$0: failed to create peek$$: $!\n";
116     }
117 }
118
119 our   $a;
120 our   $b;
121 my    $c;
122 local $d = 0;
123
124 END {
125     1 while unlink("peek$$");
126 }
127
128 do_test('assignment of immediate constant (string)',
129         $a = "foo",
130 'SV = PV\\($ADDR\\) at $ADDR
131   REFCNT = 1
132   FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
133   PV = $ADDR "foo"\\\0
134   CUR = 3
135   LEN = \\d+
136   COW_REFCNT = 1
137 ');
138
139 do_test('immediate constant (string)',
140         "bar",
141 'SV = PV\\($ADDR\\) at $ADDR
142   REFCNT = 1
143   FLAGS = \\(.*POK,READONLY,(?:IsCOW,)?pPOK\\)
144   PV = $ADDR "bar"\\\0
145   CUR = 3
146   LEN = \\d+
147   COW_REFCNT = 0
148 ');
149
150 do_test('assignment of immediate constant (integer)',
151         $b = 123,
152 'SV = IV\\($ADDR\\) at $ADDR
153   REFCNT = 1
154   FLAGS = \\(IOK,pIOK\\)
155   IV = 123');
156
157 do_test('immediate constant (integer)',
158         456,
159 'SV = IV\\($ADDR\\) at $ADDR
160   REFCNT = 1
161   FLAGS = \\(.*IOK,READONLY,pIOK\\)
162   IV = 456');
163
164 do_test('assignment of immediate constant (integer)',
165         $c = 456,
166 'SV = IV\\($ADDR\\) at $ADDR
167   REFCNT = 1
168   FLAGS = \\($PADMY,IOK,pIOK\\)
169   IV = 456');
170
171 # If perl is built with PERL_PRESERVE_IVUV then maths is done as integers
172 # where possible and this scalar will be an IV. If NO_PERL_PRESERVE_IVUV then
173 # maths is done in floating point always, and this scalar will be an NV.
174 # ([NI]) captures the type, referred to by \1 in this regexp and $type for
175 # building subsequent regexps.
176 my $type = do_test('result of addition',
177         $c + $d,
178 'SV = ([NI])V\\($ADDR\\) at $ADDR
179   REFCNT = 1
180   FLAGS = \\(PADTMP,\1OK,p\1OK\\)               # $] < 5.019003
181   FLAGS = \\(\1OK,p\1OK\\)                      # $] >=5.019003
182   \1V = 456');
183
184 ($d = "789") += 0.1;
185
186 do_test('floating point value',
187        $d,
188        $] < 5.019003
189         || $Config{ccflags} =~ /-DPERL_(?:NO_COW|OLD_COPY_ON_WRITE)/
190        ?
191 'SV = PVNV\\($ADDR\\) at $ADDR
192   REFCNT = 1
193   FLAGS = \\(NOK,pNOK\\)
194   IV = \d+
195   NV = 789\\.(?:1(?:000+\d+)?|0999+\d+)
196   PV = $ADDR "789"\\\0
197   CUR = 3
198   LEN = \\d+'
199        :
200 'SV = PVNV\\($ADDR\\) at $ADDR
201   REFCNT = 1
202   FLAGS = \\(NOK,pNOK\\)
203   IV = \d+
204   NV = 789\\.(?:1(?:000+\d+)?|0999+\d+)
205   PV = 0');
206
207 do_test('integer constant',
208         0xabcd,
209 'SV = IV\\($ADDR\\) at $ADDR
210   REFCNT = 1
211   FLAGS = \\(.*IOK,READONLY,pIOK\\)
212   IV = 43981');
213
214 do_test('undef',
215         undef,
216 'SV = NULL\\(0x0\\) at $ADDR
217   REFCNT = \d+
218   FLAGS = \\(READONLY\\)');
219
220 do_test('reference to scalar',
221         \$a,
222 'SV = $RV\\($ADDR\\) at $ADDR
223   REFCNT = 1
224   FLAGS = \\(ROK\\)
225   RV = $ADDR
226   SV = PV\\($ADDR\\) at $ADDR
227     REFCNT = 2
228     FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
229     PV = $ADDR "foo"\\\0
230     CUR = 3
231     LEN = \\d+
232     COW_REFCNT = 1
233 ');
234
235 my $c_pattern;
236 if ($type eq 'N') {
237   $c_pattern = '
238     SV = PVNV\\($ADDR\\) at $ADDR
239       REFCNT = 1
240       FLAGS = \\(IOK,NOK,pIOK,pNOK\\)
241       IV = 456
242       NV = 456
243       PV = 0';
244 } else {
245   $c_pattern = '
246     SV = IV\\($ADDR\\) at $ADDR
247       REFCNT = 1
248       FLAGS = \\(IOK,pIOK\\)
249       IV = 456';
250 }
251 do_test('reference to array',
252        [$b,$c],
253 'SV = $RV\\($ADDR\\) at $ADDR
254   REFCNT = 1
255   FLAGS = \\(ROK\\)
256   RV = $ADDR
257   SV = PVAV\\($ADDR\\) at $ADDR
258     REFCNT = 1
259     FLAGS = \\(\\)
260     IV = 0                                      # $] < 5.009
261     NV = 0                                      # $] < 5.009
262     ARRAY = $ADDR
263     FILL = 1
264     MAX = 1
265     ARYLEN = 0x0
266     FLAGS = \\(REAL\\)
267     Elt No. 0
268     SV = IV\\($ADDR\\) at $ADDR
269       REFCNT = 1
270       FLAGS = \\(IOK,pIOK\\)
271       IV = 123
272     Elt No. 1' . $c_pattern);
273
274 do_test('reference to hash',
275        {$b=>$c},
276 'SV = $RV\\($ADDR\\) at $ADDR
277   REFCNT = 1
278   FLAGS = \\(ROK\\)
279   RV = $ADDR
280   SV = PVHV\\($ADDR\\) at $ADDR
281     REFCNT = [12]
282     FLAGS = \\(SHAREKEYS\\)
283     IV = 1                                      # $] < 5.009
284     NV = $FLOAT                                 # $] < 5.009
285     ARRAY = $ADDR  \\(0:7, 1:1\\)
286     hash quality = 100.0%
287     KEYS = 1
288     FILL = 1
289     MAX = 7
290     Elt "123" HASH = $ADDR' . $c_pattern,
291         '',
292         $] > 5.009 && $] < 5.015
293          && 'The hash iterator used in dump.c sets the OOK flag');
294
295 do_test('reference to anon sub with empty prototype',
296         sub(){@_},
297 'SV = $RV\\($ADDR\\) at $ADDR
298   REFCNT = 1
299   FLAGS = \\(ROK\\)
300   RV = $ADDR
301   SV = PVCV\\($ADDR\\) at $ADDR
302     REFCNT = 2
303     FLAGS = \\($PADMY,POK,pPOK,ANON,WEAKOUTSIDE,CVGV_RC\\) # $] < 5.015 || !thr
304     FLAGS = \\($PADMY,POK,pPOK,ANON,WEAKOUTSIDE,CVGV_RC,DYNFILE\\) # $] >= 5.015 && thr
305     IV = 0                                      # $] < 5.009
306     NV = 0                                      # $] < 5.009
307     PROTOTYPE = ""
308     COMP_STASH = $ADDR\\t"main"
309     START = $ADDR ===> \\d+
310     ROOT = $ADDR
311     XSUB = 0x0                                  # $] < 5.009
312     XSUBANY = 0                                 # $] < 5.009
313     GVGV::GV = $ADDR\\t"main" :: "__ANON__[^"]*"
314     FILE = ".*\\b(?i:peek\\.t)"
315     DEPTH = 0(?:
316     MUTEXP = $ADDR
317     OWNER = $ADDR)?
318     FLAGS = 0x404                               # $] < 5.009
319     FLAGS = 0x490               # $] >= 5.009 && ($] < 5.015 || !thr)
320     FLAGS = 0x1490                              # $] >= 5.015 && thr
321     OUTSIDE_SEQ = \\d+
322     PADLIST = $ADDR
323     PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\)
324     OUTSIDE = $ADDR \\(MAIN\\)');
325
326 do_test('reference to named subroutine without prototype',
327         \&do_test,
328 'SV = $RV\\($ADDR\\) at $ADDR
329   REFCNT = 1
330   FLAGS = \\(ROK\\)
331   RV = $ADDR
332   SV = PVCV\\($ADDR\\) at $ADDR
333     REFCNT = (3|4)
334     FLAGS = \\((?:HASEVAL)?\\)                  # $] < 5.015 || !thr
335     FLAGS = \\(DYNFILE(?:,HASEVAL)?\\)          # $] >= 5.015 && thr
336     IV = 0                                      # $] < 5.009
337     NV = 0                                      # $] < 5.009
338     COMP_STASH = $ADDR\\t"main"
339     START = $ADDR ===> \\d+
340     ROOT = $ADDR
341     XSUB = 0x0                                  # $] < 5.009
342     XSUBANY = 0                                 # $] < 5.009
343     GVGV::GV = $ADDR\\t"main" :: "do_test"
344     FILE = ".*\\b(?i:peek\\.t)"
345     DEPTH = 1(?:
346     MUTEXP = $ADDR
347     OWNER = $ADDR)?
348     FLAGS = 0x(?:400)?0                         # $] < 5.015 || !thr
349     FLAGS = 0x[145]000                          # $] >= 5.015 && thr
350     OUTSIDE_SEQ = \\d+
351     PADLIST = $ADDR
352     PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\)
353        \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$todo"
354        \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$repeat_todo"
355        \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$pattern"
356        \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$do_eval"
357       \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$sub"
358       \\d+\\. $ADDR<\\d+> FAKE "\\$DEBUG"                       # $] < 5.009
359       \\d+\\. $ADDR<\\d+> FAKE "\\$DEBUG" flags=0x0 index=0     # $] >= 5.009
360       \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$dump"
361       \\d+\\. $ADDR<\\d+> \\(\\d+,\\d+\\) "\\$dump2"
362     OUTSIDE = $ADDR \\(MAIN\\)');
363
364 if ($] >= 5.011) {
365 # note the conditionals on ENGINE and INTFLAGS were introduced in 5.19.9
366 do_test('reference to regexp',
367         qr(tic),
368 'SV = $RV\\($ADDR\\) at $ADDR
369   REFCNT = 1
370   FLAGS = \\(ROK\\)
371   RV = $ADDR
372   SV = REGEXP\\($ADDR\\) at $ADDR
373     REFCNT = 1
374     FLAGS = \\(OBJECT,POK,FAKE,pPOK\\)          # $] < 5.017006
375     FLAGS = \\(OBJECT,FAKE\\)                   # $] >= 5.017006
376     PV = $ADDR "\\(\\?\\^:tic\\)"
377     CUR = 8
378     LEN = 0                                     # $] < 5.017006
379     STASH = $ADDR\\t"Regexp"'
380 . ($] < 5.013 ? '' :
381 '
382     COMPFLAGS = 0x0 \(\)
383     EXTFLAGS = 0x680000 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
384 (?:    ENGINE = $ADDR \(STANDARD\)
385 )?    INTFLAGS = 0x0(?: \(\))?
386     NPARENS = 0
387     LASTPAREN = 0
388     LASTCLOSEPAREN = 0
389     MINLEN = 3
390     MINLENRET = 3
391     GOFS = 0
392     PRE_PREFIX = 4
393     SUBLEN = 0
394     SUBOFFSET = 0
395     SUBCOFFSET = 0
396     SUBBEG = 0x0
397 (?:    ENGINE = $ADDR
398 )?    MOTHER_RE = $ADDR'
399 . ($] < 5.019003 ? '' : '
400     SV = REGEXP\($ADDR\) at $ADDR
401       REFCNT = 2
402       FLAGS = \(\)
403       PV = $ADDR "\(\?\^:tic\)"
404       CUR = 8
405       COMPFLAGS = 0x0 \(\)
406       EXTFLAGS = 0x680000 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
407 (?:      ENGINE = $ADDR \(STANDARD\)
408 )?      INTFLAGS = 0x0(?: \(\))?
409       NPARENS = 0
410       LASTPAREN = 0
411       LASTCLOSEPAREN = 0
412       MINLEN = 3
413       MINLENRET = 3
414       GOFS = 0
415       PRE_PREFIX = 4
416       SUBLEN = 0
417       SUBOFFSET = 0
418       SUBCOFFSET = 0
419       SUBBEG = 0x0
420 (?:    ENGINE = $ADDR
421 )?      MOTHER_RE = 0x0
422       PAREN_NAMES = 0x0
423       SUBSTRS = $ADDR
424       PPRIVATE = $ADDR
425       OFFS = $ADDR
426       QR_ANONCV = 0x0(?:
427       SAVED_COPY = 0x0)?') . '
428     PAREN_NAMES = 0x0
429     SUBSTRS = $ADDR
430     PPRIVATE = $ADDR
431     OFFS = $ADDR
432     QR_ANONCV = 0x0(?:
433     SAVED_COPY = 0x0)?'
434 ));
435 } else {
436 do_test('reference to regexp',
437         qr(tic),
438 'SV = $RV\\($ADDR\\) at $ADDR
439   REFCNT = 1
440   FLAGS = \\(ROK\\)
441   RV = $ADDR
442   SV = PVMG\\($ADDR\\) at $ADDR
443     REFCNT = 1
444     FLAGS = \\(OBJECT,SMG\\)
445     IV = 0
446     NV = 0
447     PV = 0
448     MAGIC = $ADDR
449       MG_VIRTUAL = $ADDR
450       MG_TYPE = PERL_MAGIC_qr\(r\)
451       MG_OBJ = $ADDR
452         PAT = "\(\?^:tic\)"                     # $] >= 5.009
453         REFCNT = 2                              # $] >= 5.009
454     STASH = $ADDR\\t"Regexp"');
455 }
456
457 do_test('reference to blessed hash',
458         (bless {}, "Tac"),
459 'SV = $RV\\($ADDR\\) at $ADDR
460   REFCNT = 1
461   FLAGS = \\(ROK\\)
462   RV = $ADDR
463   SV = PVHV\\($ADDR\\) at $ADDR
464     REFCNT = [12]
465     FLAGS = \\(OBJECT,SHAREKEYS\\)
466     IV = 0                                      # $] < 5.009
467     NV = 0                                      # $] < 5.009
468     STASH = $ADDR\\t"Tac"
469     ARRAY = 0x0
470     KEYS = 0
471     FILL = 0
472     MAX = 7', '',
473         $] > 5.009
474         ? $] >= 5.015
475              ? 0
476              : 'The hash iterator used in dump.c sets the OOK flag'
477         : "Something causes the HV's array to become allocated");
478
479 do_test('typeglob',
480         *a,
481 'SV = PVGV\\($ADDR\\) at $ADDR
482   REFCNT = 5
483   FLAGS = \\(MULTI(?:,IN_PAD)?\\)               # $] >= 5.009
484   FLAGS = \\(GMG,SMG,MULTI(?:,IN_PAD)?\\)       # $] < 5.009
485   IV = 0                                        # $] < 5.009
486   NV = 0                                        # $] < 5.009
487   PV = 0                                        # $] < 5.009
488   MAGIC = $ADDR                                 # $] < 5.009
489     MG_VIRTUAL = &PL_vtbl_glob                  # $] < 5.009
490     MG_TYPE = PERL_MAGIC_glob\(\*\)             # $] < 5.009
491     MG_OBJ = $ADDR                              # $] < 5.009
492   NAME = "a"
493   NAMELEN = 1
494   GvSTASH = $ADDR\\t"main"
495   GP = $ADDR
496     SV = $ADDR
497     REFCNT = 1
498     IO = 0x0
499     FORM = 0x0  
500     AV = 0x0
501     HV = 0x0
502     CV = 0x0
503     CVGEN = 0x0
504     GPFLAGS = 0x0                               # $] < 5.009
505     LINE = \\d+
506     FILE = ".*\\b(?i:peek\\.t)"
507     FLAGS = $ADDR
508     EGV = $ADDR\\t"a"');
509
510 if (ord('A') == 193) {
511 do_test('string with Unicode',
512         chr(256).chr(0).chr(512),
513 'SV = PV\\($ADDR\\) at $ADDR
514   REFCNT = 1
515   FLAGS = \\((?:$PADTMP,)?POK,READONLY,pPOK,UTF8\\)     # $] < 5.019003
516   FLAGS = \\((?:$PADTMP,)?POK,(?:IsCOW,)?pPOK,UTF8\\)   # $] >=5.019003
517   PV = $ADDR "\\\214\\\101\\\0\\\235\\\101"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\]
518   CUR = 5
519   LEN = \\d+
520   COW_REFCNT = 1                                        # $] < 5.019007
521 ');
522 } else {
523 do_test('string with Unicode',
524         chr(256).chr(0).chr(512),
525 'SV = PV\\($ADDR\\) at $ADDR
526   REFCNT = 1
527   FLAGS = \\((?:$PADTMP,)?POK,READONLY,pPOK,UTF8\\)     # $] < 5.019003
528   FLAGS = \\((?:$PADTMP,)?POK,(?:IsCOW,)?pPOK,UTF8\\)   # $] >=5.019003
529   PV = $ADDR "\\\304\\\200\\\0\\\310\\\200"\\\0 \[UTF8 "\\\x\{100\}\\\x\{0\}\\\x\{200\}"\]
530   CUR = 5
531   LEN = \\d+
532   COW_REFCNT = 1                                        # $] < 5.019007
533 ');
534 }
535
536 if (ord('A') == 193) {
537 do_test('reference to hash containing Unicode',
538         {chr(256)=>chr(512)},
539 'SV = $RV\\($ADDR\\) at $ADDR
540   REFCNT = 1
541   FLAGS = \\(ROK\\)
542   RV = $ADDR
543   SV = PVHV\\($ADDR\\) at $ADDR
544     REFCNT = [12]
545     FLAGS = \\(SHAREKEYS,HASKFLAGS\\)
546     UV = 1                                      # $] < 5.009
547     NV = $FLOAT                                 # $] < 5.009
548     ARRAY = $ADDR  \\(0:7, 1:1\\)
549     hash quality = 100.0%
550     KEYS = 1
551     FILL = 1
552     MAX = 7
553     Elt "\\\214\\\101" \[UTF8 "\\\x\{100\}"\] HASH = $ADDR
554     SV = PV\\($ADDR\\) at $ADDR
555       REFCNT = 1
556       FLAGS = \\(POK,(?:IsCOW,)?pPOK,UTF8\\)
557       PV = $ADDR "\\\235\\\101"\\\0 \[UTF8 "\\\x\{200\}"\]
558       CUR = 2
559       LEN = \\d+
560       COW_REFCNT = 1                            # $] < 5.019007
561 ',      '',
562         $] > 5.009
563         ? $] >= 5.015
564             ?  0
565             : 'The hash iterator used in dump.c sets the OOK flag'
566         : 'sv_length has been called on the element, and cached the result in MAGIC');
567 } else {
568 do_test('reference to hash containing Unicode',
569         {chr(256)=>chr(512)},
570 'SV = $RV\\($ADDR\\) at $ADDR
571   REFCNT = 1
572   FLAGS = \\(ROK\\)
573   RV = $ADDR
574   SV = PVHV\\($ADDR\\) at $ADDR
575     REFCNT = [12]
576     FLAGS = \\(SHAREKEYS,HASKFLAGS\\)
577     UV = 1                                      # $] < 5.009
578     NV = 0                                      # $] < 5.009
579     ARRAY = $ADDR  \\(0:7, 1:1\\)
580     hash quality = 100.0%
581     KEYS = 1
582     FILL = 1
583     MAX = 7
584     Elt "\\\304\\\200" \[UTF8 "\\\x\{100\}"\] HASH = $ADDR
585     SV = PV\\($ADDR\\) at $ADDR
586       REFCNT = 1
587       FLAGS = \\(POK,(?:IsCOW,)?pPOK,UTF8\\)
588       PV = $ADDR "\\\310\\\200"\\\0 \[UTF8 "\\\x\{200\}"\]
589       CUR = 2
590       LEN = \\d+
591       COW_REFCNT = 1                            # $] < 5.019007
592 ',      '',
593         $] > 5.009
594         ? $] >= 5.015
595             ?  0
596             : 'The hash iterator used in dump.c sets the OOK flag'
597         : 'sv_length has been called on the element, and cached the result in MAGIC');
598 }
599
600 my $x="";
601 $x=~/.??/g;
602 do_test('scalar with pos magic',
603         $x,
604 'SV = PVMG\\($ADDR\\) at $ADDR
605   REFCNT = 1
606   FLAGS = \\($PADMY,SMG,POK,(?:IsCOW,)?pPOK\\)
607   IV = \d+
608   NV = 0
609   PV = $ADDR ""\\\0
610   CUR = 0
611   LEN = \d+
612   COW_REFCNT = [12]
613   MAGIC = $ADDR
614     MG_VIRTUAL = &PL_vtbl_mglob
615     MG_TYPE = PERL_MAGIC_regex_global\\(g\\)
616     MG_FLAGS = 0x01                                     # $] < 5.019003
617     MG_FLAGS = 0x41                                     # $] >=5.019003
618       MINMATCH
619       BYTES                                             # $] >=5.019003
620 ');
621
622 #
623 # TAINTEDDIR is not set on: OS2, AMIGAOS, WIN32, MSDOS
624 # environment variables may be invisibly case-forced, hence the (?i:PATH)
625 # C<scalar(@ARGV)> is turned into an IV on VMS hence the (?:IV)?
626 # Perl 5.18 ensures all env vars end up as strings only, hence the (?:,pIOK)?
627 # Perl 5.18 ensures even magic vars have public OK, hence the (?:,POK)?
628 # VMS is setting FAKE and READONLY flags.  What VMS uses for storing
629 # ENV hashes is also not always null terminated.
630 #
631 if (${^TAINT}) {
632   # Save and restore PATH, since fresh_perl ends up using that in Windows.
633   my $path = $ENV{PATH};
634   do_test('tainted value in %ENV',
635           $ENV{PATH}=@ARGV,  # scalar(@ARGV) is a handy known tainted value
636 'SV = PVMG\\($ADDR\\) at $ADDR
637   REFCNT = 1
638   FLAGS = \\(GMG,SMG,RMG(?:,POK)?(?:,pIOK)?,pPOK\\)
639   IV = 0
640   NV = 0
641   PV = $ADDR "0"\\\0
642   CUR = 1
643   LEN = \d+
644   MAGIC = $ADDR
645     MG_VIRTUAL = &PL_vtbl_envelem
646     MG_TYPE = PERL_MAGIC_envelem\\(e\\)
647 (?:    MG_FLAGS = 0x01
648       TAINTEDDIR
649 )?    MG_LEN = -?\d+
650     MG_PTR = $ADDR (?:"(?i:PATH)"|=> HEf_SVKEY
651     SV = PV(?:IV)?\\($ADDR\\) at $ADDR
652       REFCNT = \d+
653       FLAGS = \\((?:TEMP,)?POK,(?:FAKE,READONLY,)?pPOK\\)
654 (?:      IV = 0
655 )?      PV = $ADDR "(?i:PATH)"(?:\\\0)?
656       CUR = \d+
657       LEN = \d+)
658   MAGIC = $ADDR
659     MG_VIRTUAL = &PL_vtbl_taint
660     MG_TYPE = PERL_MAGIC_taint\\(t\\)');
661     $ENV{PATH} = $path;
662 }
663
664 do_test('blessed reference',
665         bless(\\undef, 'Foobar'),
666 'SV = $RV\\($ADDR\\) at $ADDR
667   REFCNT = 1
668   FLAGS = \\(ROK\\)
669   RV = $ADDR
670   SV = PVMG\\($ADDR\\) at $ADDR
671     REFCNT = 2
672     FLAGS = \\(OBJECT,ROK\\)
673     IV = -?\d+
674     NV = $FLOAT
675     RV = $ADDR
676     SV = NULL\\(0x0\\) at $ADDR
677       REFCNT = \d+
678       FLAGS = \\(READONLY\\)
679     PV = $ADDR ""
680     CUR = 0
681     LEN = 0
682     STASH = $ADDR\s+"Foobar"');
683
684 sub const () {
685     "Perl rules";
686 }
687
688 do_test('constant subroutine',
689         \&const,
690 'SV = $RV\\($ADDR\\) at $ADDR
691   REFCNT = 1
692   FLAGS = \\(ROK\\)
693   RV = $ADDR
694   SV = PVCV\\($ADDR\\) at $ADDR
695     REFCNT = (2)
696     FLAGS = \\(POK,pPOK,CONST,ISXSUB\\)         # $] < 5.015
697     FLAGS = \\(POK,pPOK,CONST,DYNFILE,ISXSUB\\) # $] >= 5.015
698     IV = 0                                      # $] < 5.009
699     NV = 0                                      # $] < 5.009
700     PROTOTYPE = ""
701     COMP_STASH = 0x0
702     ROOT = 0x0                                  # $] < 5.009
703     XSUB = $ADDR
704     XSUBANY = $ADDR \\(CONST SV\\)
705     SV = PV\\($ADDR\\) at $ADDR
706       REFCNT = 1
707       FLAGS = \\(.*POK,READONLY,(?:IsCOW,)?pPOK\\)
708       PV = $ADDR "Perl rules"\\\0
709       CUR = 10
710       LEN = \\d+
711       COW_REFCNT = 0
712     GVGV::GV = $ADDR\\t"main" :: "const"
713     FILE = ".*\\b(?i:peek\\.t)"
714     DEPTH = 0(?:
715     MUTEXP = $ADDR
716     OWNER = $ADDR)?
717     FLAGS = 0x200                               # $] < 5.009
718     FLAGS = 0xc00                               # $] >= 5.009 && $] < 5.013
719     FLAGS = 0xc                                 # $] >= 5.013 && $] < 5.015
720     FLAGS = 0x100c                              # $] >= 5.015
721     OUTSIDE_SEQ = 0
722     PADLIST = 0x0
723     OUTSIDE = 0x0 \\(null\\)'); 
724
725 do_test('isUV should show on PVMG',
726         do { my $v = $1; $v = ~0; $v },
727 'SV = PVMG\\($ADDR\\) at $ADDR
728   REFCNT = 1
729   FLAGS = \\(IOK,pIOK,IsUV\\)
730   UV = \d+
731   NV = 0
732   PV = 0');
733
734 do_test('IO',
735         *STDOUT{IO},
736 'SV = $RV\\($ADDR\\) at $ADDR
737   REFCNT = 1
738   FLAGS = \\(ROK\\)
739   RV = $ADDR
740   SV = PVIO\\($ADDR\\) at $ADDR
741     REFCNT = 3
742     FLAGS = \\(OBJECT\\)
743     IV = 0                                      # $] < 5.011
744     NV = 0                                      # $] < 5.011
745     STASH = $ADDR\s+"IO::File"
746     IFP = $ADDR
747     OFP = $ADDR
748     DIRP = 0x0
749     LINES = 0
750     PAGE = 0
751     PAGE_LEN = 60
752     LINES_LEFT = 0
753     TOP_GV = 0x0
754     FMT_GV = 0x0
755     BOTTOM_GV = 0x0
756     SUBPROCESS = 0                              # $] < 5.009
757     TYPE = \'>\'
758     FLAGS = 0x4');
759
760 do_test('FORMAT',
761         *PIE{FORMAT},
762 'SV = $RV\\($ADDR\\) at $ADDR
763   REFCNT = 1
764   FLAGS = \\(ROK\\)
765   RV = $ADDR
766   SV = PVFM\\($ADDR\\) at $ADDR
767     REFCNT = 2
768     FLAGS = \\(\\)                              # $] < 5.015 || !thr
769     FLAGS = \\(DYNFILE\\)                       # $] >= 5.015 && thr
770     IV = 0                                      # $] < 5.009
771     NV = 0                                      # $] < 5.009
772 (?:    PV = 0
773 )?    COMP_STASH = 0x0
774     START = $ADDR ===> \\d+
775     ROOT = $ADDR
776     XSUB = 0x0                                  # $] < 5.009
777     XSUBANY = 0                                 # $] < 5.009
778     GVGV::GV = $ADDR\\t"main" :: "PIE"
779     FILE = ".*\\b(?i:peek\\.t)"(?:
780     DEPTH = 0)?(?:
781     MUTEXP = $ADDR
782     OWNER = $ADDR)?
783     FLAGS = 0x0                                 # $] < 5.015 || !thr
784     FLAGS = 0x1000                              # $] >= 5.015 && thr
785     OUTSIDE_SEQ = \\d+
786     LINES = 0                                   # $] < 5.017_003
787     PADLIST = $ADDR
788     PADNAME = $ADDR\\($ADDR\\) PAD = $ADDR\\($ADDR\\)
789     OUTSIDE = $ADDR \\(MAIN\\)');
790
791 do_test('blessing to a class with embedded NUL characters',
792         (bless {}, "\0::foo::\n::baz::\t::\0"),
793 'SV = $RV\\($ADDR\\) at $ADDR
794   REFCNT = 1
795   FLAGS = \\(ROK\\)
796   RV = $ADDR
797   SV = PVHV\\($ADDR\\) at $ADDR
798     REFCNT = [12]
799     FLAGS = \\(OBJECT,SHAREKEYS\\)
800     IV = 0                                      # $] < 5.009
801     NV = 0                                      # $] < 5.009
802     STASH = $ADDR\\t"\\\\0::foo::\\\\n::baz::\\\\t::\\\\0"
803     ARRAY = $ADDR
804     KEYS = 0
805     FILL = 0
806     MAX = 7', '',
807         $] > 5.009
808         ? $] >= 5.015
809             ?  0
810             : 'The hash iterator used in dump.c sets the OOK flag'
811         : "Something causes the HV's array to become allocated");
812
813 do_test('ENAME on a stash',
814         \%RWOM::,
815 'SV = $RV\\($ADDR\\) at $ADDR
816   REFCNT = 1
817   FLAGS = \\(ROK\\)
818   RV = $ADDR
819   SV = PVHV\\($ADDR\\) at $ADDR
820     REFCNT = 2
821     FLAGS = \\(OOK,SHAREKEYS\\)
822     IV = 1                                      # $] < 5.009
823     NV = $FLOAT                                 # $] < 5.009
824     AUX_FLAGS = 0                               # $] > 5.019008
825     ARRAY = $ADDR
826     KEYS = 0
827     FILL = 0 \(cached = 0\)
828     MAX = 7
829     RITER = -1
830     EITER = 0x0
831     RAND = $ADDR
832     NAME = "RWOM"
833     ENAME = "RWOM"                              # $] > 5.012
834 ');
835
836 *KLANK:: = \%RWOM::;
837
838 do_test('ENAMEs on a stash',
839         \%RWOM::,
840 'SV = $RV\\($ADDR\\) at $ADDR
841   REFCNT = 1
842   FLAGS = \\(ROK\\)
843   RV = $ADDR
844   SV = PVHV\\($ADDR\\) at $ADDR
845     REFCNT = 3
846     FLAGS = \\(OOK,SHAREKEYS\\)
847     IV = 1                                      # $] < 5.009
848     NV = $FLOAT                                 # $] < 5.009
849     AUX_FLAGS = 0                               # $] > 5.019008
850     ARRAY = $ADDR
851     KEYS = 0
852     FILL = 0 \(cached = 0\)
853     MAX = 7
854     RITER = -1
855     EITER = 0x0
856     RAND = $ADDR
857     NAME = "RWOM"
858     NAMECOUNT = 2                               # $] > 5.012
859     ENAME = "RWOM", "KLANK"                     # $] > 5.012
860 ');
861
862 undef %RWOM::;
863
864 do_test('ENAMEs on a stash with no NAME',
865         \%RWOM::,
866 'SV = $RV\\($ADDR\\) at $ADDR
867   REFCNT = 1
868   FLAGS = \\(ROK\\)
869   RV = $ADDR
870   SV = PVHV\\($ADDR\\) at $ADDR
871     REFCNT = 3
872     FLAGS = \\(OOK,SHAREKEYS\\)                 # $] < 5.017
873     FLAGS = \\(OOK,OVERLOAD,SHAREKEYS\\)        # $] >=5.017
874     IV = 1                                      # $] < 5.009
875     NV = $FLOAT                                 # $] < 5.009
876     AUX_FLAGS = 0                               # $] > 5.019008
877     ARRAY = $ADDR
878     KEYS = 0
879     FILL = 0 \(cached = 0\)
880     MAX = 7
881     RITER = -1
882     EITER = 0x0
883     RAND = $ADDR
884     NAMECOUNT = -3                              # $] > 5.012
885     ENAME = "RWOM", "KLANK"                     # $] > 5.012
886 ');
887
888 my %small = ("Perl", "Rules", "Beer", "Foamy");
889 my $b = %small;
890 do_test('small hash',
891         \%small,
892 'SV = $RV\\($ADDR\\) at $ADDR
893   REFCNT = 1
894   FLAGS = \\(ROK\\)
895   RV = $ADDR
896   SV = PVHV\\($ADDR\\) at $ADDR
897     REFCNT = 2
898     FLAGS = \\(PADMY,SHAREKEYS\\)
899     IV = 1                                      # $] < 5.009
900     NV = $FLOAT                                 # $] < 5.009
901     ARRAY = $ADDR  \\(0:[67],.*\\)
902     hash quality = [0-9.]+%
903     KEYS = 2
904     FILL = [12]
905     MAX = 7
906 (?:    Elt "(?:Perl|Beer)" HASH = $ADDR
907     SV = PV\\($ADDR\\) at $ADDR
908       REFCNT = 1
909       FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
910       PV = $ADDR "(?:Rules|Foamy)"\\\0
911       CUR = \d+
912       LEN = \d+
913       COW_REFCNT = 1
914 ){2}');
915
916 $b = keys %small;
917
918 do_test('small hash after keys',
919         \%small,
920 'SV = $RV\\($ADDR\\) at $ADDR
921   REFCNT = 1
922   FLAGS = \\(ROK\\)
923   RV = $ADDR
924   SV = PVHV\\($ADDR\\) at $ADDR
925     REFCNT = 2
926     FLAGS = \\(PADMY,OOK,SHAREKEYS\\)
927     IV = 1                                      # $] < 5.009
928     NV = $FLOAT                                 # $] < 5.009
929     AUX_FLAGS = 0                               # $] > 5.019008
930     ARRAY = $ADDR  \\(0:[67],.*\\)
931     hash quality = [0-9.]+%
932     KEYS = 2
933     FILL = [12] \\(cached = 0\\)
934     MAX = 7
935     RITER = -1
936     EITER = 0x0
937     RAND = $ADDR
938 (?:    Elt "(?:Perl|Beer)" HASH = $ADDR
939     SV = PV\\($ADDR\\) at $ADDR
940       REFCNT = 1
941       FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
942       PV = $ADDR "(?:Rules|Foamy)"\\\0
943       CUR = \d+
944       LEN = \d+
945       COW_REFCNT = 1
946 ){2}');
947
948 $b = %small;
949
950 do_test('small hash after keys and scalar',
951         \%small,
952 'SV = $RV\\($ADDR\\) at $ADDR
953   REFCNT = 1
954   FLAGS = \\(ROK\\)
955   RV = $ADDR
956   SV = PVHV\\($ADDR\\) at $ADDR
957     REFCNT = 2
958     FLAGS = \\(PADMY,OOK,SHAREKEYS\\)
959     IV = 1                                      # $] < 5.009
960     NV = $FLOAT                                 # $] < 5.009
961     AUX_FLAGS = 0                               # $] > 5.019008
962     ARRAY = $ADDR  \\(0:[67],.*\\)
963     hash quality = [0-9.]+%
964     KEYS = 2
965     FILL = ([12]) \\(cached = \1\\)
966     MAX = 7
967     RITER = -1
968     EITER = 0x0
969     RAND = $ADDR
970 (?:    Elt "(?:Perl|Beer)" HASH = $ADDR
971     SV = PV\\($ADDR\\) at $ADDR
972       REFCNT = 1
973       FLAGS = \\(POK,(?:IsCOW,)?pPOK\\)
974       PV = $ADDR "(?:Rules|Foamy)"\\\0
975       CUR = \d+
976       LEN = \d+
977       COW_REFCNT = 1
978 ){2}');
979
980 # This should immediately start with the FILL cached correctly.
981 my %large = (0..1999);
982 $b = %large;
983 do_test('large hash',
984         \%large,
985 'SV = $RV\\($ADDR\\) at $ADDR
986   REFCNT = 1
987   FLAGS = \\(ROK\\)
988   RV = $ADDR
989   SV = PVHV\\($ADDR\\) at $ADDR
990     REFCNT = 2
991     FLAGS = \\(PADMY,OOK,SHAREKEYS\\)
992     IV = 1                                      # $] < 5.009
993     NV = $FLOAT                                 # $] < 5.009
994     AUX_FLAGS = 0                               # $] > 5.019008
995     ARRAY = $ADDR  \\(0:\d+,.*\\)
996     hash quality = \d+\\.\d+%
997     KEYS = 1000
998     FILL = (\d+) \\(cached = \1\\)
999     MAX = 1023
1000     RITER = -1
1001     EITER = 0x0
1002     RAND = $ADDR
1003     Elt .*
1004 ');
1005
1006 # Dump with arrays, hashes, and operator return values
1007 @array = 1..3;
1008 do_test('Dump @array', '@array', <<'ARRAY', '', '', 1);
1009 SV = PVAV\($ADDR\) at $ADDR
1010   REFCNT = 1
1011   FLAGS = \(\)
1012   ARRAY = $ADDR
1013   FILL = 2
1014   MAX = 3
1015   ARYLEN = 0x0
1016   FLAGS = \(REAL\)
1017   Elt No. 0
1018   SV = IV\($ADDR\) at $ADDR
1019     REFCNT = 1
1020     FLAGS = \(IOK,pIOK\)
1021     IV = 1
1022   Elt No. 1
1023   SV = IV\($ADDR\) at $ADDR
1024     REFCNT = 1
1025     FLAGS = \(IOK,pIOK\)
1026     IV = 2
1027   Elt No. 2
1028   SV = IV\($ADDR\) at $ADDR
1029     REFCNT = 1
1030     FLAGS = \(IOK,pIOK\)
1031     IV = 3
1032 ARRAY
1033
1034 do_test('Dump @array,1', '@array,1', <<'ARRAY', '', '', 1);
1035 SV = PVAV\($ADDR\) at $ADDR
1036   REFCNT = 1
1037   FLAGS = \(\)
1038   ARRAY = $ADDR
1039   FILL = 2
1040   MAX = 3
1041   ARYLEN = 0x0
1042   FLAGS = \(REAL\)
1043   Elt No. 0
1044   SV = IV\($ADDR\) at $ADDR
1045     REFCNT = 1
1046     FLAGS = \(IOK,pIOK\)
1047     IV = 1
1048 ARRAY
1049
1050 %hash = 1..2;
1051 do_test('Dump %hash', '%hash', <<'HASH', '', '', 1);
1052 SV = PVHV\($ADDR\) at $ADDR
1053   REFCNT = 1
1054   FLAGS = \(SHAREKEYS\)
1055   ARRAY = $ADDR  \(0:7, 1:1\)
1056   hash quality = 100.0%
1057   KEYS = 1
1058   FILL = 1
1059   MAX = 7
1060   Elt "1" HASH = $ADDR
1061   SV = IV\($ADDR\) at $ADDR
1062     REFCNT = 1
1063     FLAGS = \(IOK,pIOK\)
1064     IV = 2
1065 HASH
1066
1067 $_ = "hello";
1068 do_test('rvalue substr', 'substr $_, 1, 2', <<'SUBSTR', '', '', 1);
1069 SV = PV\($ADDR\) at $ADDR
1070   REFCNT = 1
1071   FLAGS = \(PADTMP,POK,pPOK\)
1072   PV = $ADDR "el"\\0
1073   CUR = 2
1074   LEN = \d+
1075 SUBSTR
1076
1077 # Dump with no arguments
1078 eval 'Dump';
1079 like $@, qr/^Not enough arguments for Devel::Peek::Dump/, 'Dump;';
1080 eval 'Dump()';
1081 like $@, qr/^Not enough arguments for Devel::Peek::Dump/, 'Dump()';
1082
1083 SKIP: {
1084     skip "Not built with usemymalloc", 2
1085       unless $Config{usemymalloc} eq 'y';
1086     my $x = __PACKAGE__;
1087     ok eval { fill_mstats($x); 1 }, 'fill_mstats on COW scalar'
1088      or diag $@;
1089     my $y;
1090     ok eval { fill_mstats($y); 1 }, 'fill_mstats on undef scalar';
1091 }
1092
1093 # This is more a test of fbm_compile/pp_study (non) interaction than dumping
1094 # prowess, but short of duplicating all the gubbins of this file, I can't see
1095 # a way to make a better place for it:
1096
1097 use constant {
1098     perl => 'rules',
1099     beer => 'foamy',
1100 };
1101
1102 unless ($Config{useithreads}) {
1103     # These end up as copies in pads under ithreads, which rather defeats the
1104     # the point of what we're trying to test here.
1105
1106     do_test('regular string constant', perl,
1107 'SV = PV\\($ADDR\\) at $ADDR
1108   REFCNT = 5
1109   FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\)
1110   PV = $ADDR "rules"\\\0
1111   CUR = 5
1112   LEN = \d+
1113   COW_REFCNT = 0
1114 ');
1115
1116     eval 'index "", perl';
1117
1118     # FIXME - really this shouldn't say EVALED. It's a false posistive on
1119     # 0x40000000 being used for several things, not a flag for "I'm in a string
1120     # eval"
1121
1122     do_test('string constant now an FBM', perl,
1123 'SV = PVMG\\($ADDR\\) at $ADDR
1124   REFCNT = 5
1125   FLAGS = \\(PADMY,SMG,POK,READONLY,(?:IsCOW,)?pPOK,VALID,EVALED\\)
1126   PV = $ADDR "rules"\\\0
1127   CUR = 5
1128   LEN = \d+
1129   COW_REFCNT = 0
1130   MAGIC = $ADDR
1131     MG_VIRTUAL = &PL_vtbl_regexp
1132     MG_TYPE = PERL_MAGIC_bm\\(B\\)
1133     MG_LEN = 256
1134     MG_PTR = $ADDR "(?:\\\\\d){256}"
1135   RARE = \d+                                    # $] < 5.019002
1136   PREVIOUS = 1                                  # $] < 5.019002
1137   USEFUL = 100
1138 ');
1139
1140     is(study perl, '', "Not allowed to study an FBM");
1141
1142     do_test('string constant still an FBM', perl,
1143 'SV = PVMG\\($ADDR\\) at $ADDR
1144   REFCNT = 5
1145   FLAGS = \\(PADMY,SMG,POK,READONLY,(?:IsCOW,)?pPOK,VALID,EVALED\\)
1146   PV = $ADDR "rules"\\\0
1147   CUR = 5
1148   LEN = \d+
1149   COW_REFCNT = 0
1150   MAGIC = $ADDR
1151     MG_VIRTUAL = &PL_vtbl_regexp
1152     MG_TYPE = PERL_MAGIC_bm\\(B\\)
1153     MG_LEN = 256
1154     MG_PTR = $ADDR "(?:\\\\\d){256}"
1155   RARE = \d+                                    # $] < 5.019002
1156   PREVIOUS = 1                                  # $] < 5.019002
1157   USEFUL = 100
1158 ');
1159
1160     do_test('regular string constant', beer,
1161 'SV = PV\\($ADDR\\) at $ADDR
1162   REFCNT = 6
1163   FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\)
1164   PV = $ADDR "foamy"\\\0
1165   CUR = 5
1166   LEN = \d+
1167   COW_REFCNT = 0
1168 ');
1169
1170     is(study beer, 1, "Our studies were successful");
1171
1172     do_test('string constant quite unaffected', beer, 'SV = PV\\($ADDR\\) at $ADDR
1173   REFCNT = 6
1174   FLAGS = \\(PADMY,POK,READONLY,(?:IsCOW,)?pPOK\\)
1175   PV = $ADDR "foamy"\\\0
1176   CUR = 5
1177   LEN = \d+
1178   COW_REFCNT = 0
1179 ');
1180
1181     my $want = 'SV = PVMG\\($ADDR\\) at $ADDR
1182   REFCNT = 6
1183   FLAGS = \\(PADMY,SMG,POK,READONLY,(?:IsCOW,)?pPOK,VALID,EVALED\\)
1184   PV = $ADDR "foamy"\\\0
1185   CUR = 5
1186   LEN = \d+
1187   COW_REFCNT = 0
1188   MAGIC = $ADDR
1189     MG_VIRTUAL = &PL_vtbl_regexp
1190     MG_TYPE = PERL_MAGIC_bm\\(B\\)
1191     MG_LEN = 256
1192     MG_PTR = $ADDR "(?:\\\\\d){256}"
1193   RARE = \d+                                    # $] < 5.019002
1194   PREVIOUS = \d+                                # $] < 5.019002
1195   USEFUL = 100
1196 ';
1197
1198     is (eval 'index "not too foamy", beer', 8, 'correct index');
1199
1200     do_test('string constant now FBMed', beer, $want);
1201
1202     my $pie = 'good';
1203
1204     is(study $pie, 1, "Our studies were successful");
1205
1206     do_test('string constant still FBMed', beer, $want);
1207
1208     do_test('second string also unaffected', $pie, 'SV = PV\\($ADDR\\) at $ADDR
1209   REFCNT = 1
1210   FLAGS = \\(PADMY,POK,(?:IsCOW,)?pPOK\\)
1211   PV = $ADDR "good"\\\0
1212   CUR = 4
1213   LEN = \d+
1214   COW_REFCNT = 1
1215 ');
1216 }
1217
1218 # (One block of study tests removed when study was made a no-op.)
1219
1220 {
1221     open(OUT,">peek$$") or die "Failed to open peek $$: $!";
1222     open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
1223     DeadCode();
1224     open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
1225     pass "no crash with DeadCode";
1226     close OUT;
1227 }
1228 # note the conditionals on ENGINE and INTFLAGS were introduced in 5.19.9
1229 do_test('UTF-8 in a regular expression',
1230         qr/\x{100}/,
1231 'SV = IV\($ADDR\) at $ADDR
1232   REFCNT = 1
1233   FLAGS = \(ROK\)
1234   RV = $ADDR
1235   SV = REGEXP\($ADDR\) at $ADDR
1236     REFCNT = 1
1237     FLAGS = \(OBJECT,FAKE,UTF8\)
1238     PV = $ADDR "\(\?\^u:\\\\\\\\x\{100\}\)" \[UTF8 "\(\?\^u:\\\\\\\\x\{100\}\)"\]
1239     CUR = 13
1240     STASH = $ADDR       "Regexp"
1241     COMPFLAGS = 0x0 \(\)
1242     EXTFLAGS = 0x680040 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
1243 (?:    ENGINE = $ADDR \(STANDARD\)
1244 )?    INTFLAGS = 0x0(?: \(\))?
1245     NPARENS = 0
1246     LASTPAREN = 0
1247     LASTCLOSEPAREN = 0
1248     MINLEN = 1
1249     MINLENRET = 1
1250     GOFS = 0
1251     PRE_PREFIX = 5
1252     SUBLEN = 0
1253     SUBOFFSET = 0
1254     SUBCOFFSET = 0
1255     SUBBEG = 0x0
1256 (?:    ENGINE = $ADDR
1257 )?    MOTHER_RE = $ADDR'
1258 . ($] < 5.019003 ? '' : '
1259     SV = REGEXP\($ADDR\) at $ADDR
1260       REFCNT = 2
1261       FLAGS = \(UTF8\)
1262       PV = $ADDR "\(\?\^u:\\\\\\\\x\{100\}\)" \[UTF8 "\(\?\^u:\\\\\\\\x\{100\}\)"\]
1263       CUR = 13
1264       COMPFLAGS = 0x0 \(\)
1265       EXTFLAGS = 0x680040 \(CHECK_ALL,USE_INTUIT_NOML,USE_INTUIT_ML\)
1266 (?:      ENGINE = $ADDR \(STANDARD\)
1267 )?      INTFLAGS = 0x0(?: \(\))?
1268       NPARENS = 0
1269       LASTPAREN = 0
1270       LASTCLOSEPAREN = 0
1271       MINLEN = 1
1272       MINLENRET = 1
1273       GOFS = 0
1274       PRE_PREFIX = 5
1275       SUBLEN = 0
1276       SUBOFFSET = 0
1277       SUBCOFFSET = 0
1278       SUBBEG = 0x0
1279 (?:    ENGINE = $ADDR
1280 )?      MOTHER_RE = 0x0
1281       PAREN_NAMES = 0x0
1282       SUBSTRS = $ADDR
1283       PPRIVATE = $ADDR
1284       OFFS = $ADDR
1285       QR_ANONCV = 0x0(?:
1286       SAVED_COPY = 0x0)?') . '
1287     PAREN_NAMES = 0x0
1288     SUBSTRS = $ADDR
1289     PPRIVATE = $ADDR
1290     OFFS = $ADDR
1291     QR_ANONCV = 0x0(?:
1292     SAVED_COPY = 0x0)?
1293 ');
1294
1295 { # perl #117793: Extend SvREFCNT* to work on any perl variable type
1296   my %hash;
1297   my $base_count = Devel::Peek::SvREFCNT(%hash);
1298   my $ref = \%hash;
1299   is(Devel::Peek::SvREFCNT(%hash), $base_count + 1, "SvREFCNT on non-scalar");
1300   ok(!eval { &Devel::Peek::SvREFCNT(1) }, "requires prototype");
1301 }
1302 {
1303 # utf8 tests
1304 use utf8;
1305
1306 sub _dump {
1307    open(OUT,">peek$$") or die $!;
1308    open(STDERR, ">&OUT") or die "Can't dup OUT: $!";
1309    Dump($_[0]);
1310    open(STDERR, ">&SAVERR") or die "Can't restore STDERR: $!";
1311    close(OUT);
1312    open(IN, "peek$$") or die $!;
1313    my $dump = do { local $/; <IN> };
1314    close(IN);
1315    1 while unlink "peek$$";
1316    return $dump;
1317 }
1318
1319 sub _get_coderef {
1320    my $x = $_[0];
1321    utf8::upgrade($x);
1322    eval "sub $x {}; 1" or die $@;
1323    return *{$x}{CODE};
1324 }
1325
1326 like(
1327    _dump(_get_coderef("\x{df}::\xdf")),
1328    qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\xdf" :: "\xdf"/,
1329    "GVGV's are correctly escaped for latin1 :: latin1",
1330 );
1331
1332 like(
1333    _dump(_get_coderef("\x{30cd}::\x{30cd}")),
1334    qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cd}" :: "\x{30cd}"/,
1335    "GVGV's are correctly escaped for UTF8 :: UTF8",
1336 );
1337
1338 like(
1339    _dump(_get_coderef("\x{df}::\x{30cd}")),
1340    qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\xdf" :: "\x{30cd}"/,
1341    "GVGV's are correctly escaped for latin1 :: UTF8",
1342 );
1343
1344 like(
1345    _dump(_get_coderef("\x{30cd}::\x{df}")),
1346    qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cd}" :: "\xdf"/,
1347    "GVGV's are correctly escaped for UTF8 :: latin1",
1348 );
1349
1350 like(
1351    _dump(_get_coderef("\x{30cb}::\x{df}::\x{30cd}")),
1352    qr/GVGV::GV = 0x[[:xdigit:]]+\s+\Q"\x{30cb}::\x{df}" :: "\x{30cd}"/,
1353    "GVGV's are correctly escaped for UTF8 :: latin 1 :: UTF8",
1354 );
1355
1356 my $dump = _dump(*{"\x{30cb}::\x{df}::\x{30dc}"});
1357
1358 like(
1359    $dump,
1360    qr/NAME = \Q"\x{30dc}"/,
1361    "NAME is correctly escaped for UTF8 globs",
1362 );
1363
1364 like(
1365    $dump,
1366    qr/GvSTASH = 0x[[:xdigit:]]+\s+\Q"\x{30cb}::\x{df}"/,
1367    "GvSTASH is correctly escaped for UTF8 globs"
1368 );
1369
1370 like(
1371    $dump,
1372    qr/EGV = 0x[[:xdigit:]]+\s+\Q"\x{30dc}"/,
1373    "EGV is correctly escaped for UTF8 globs"
1374 );
1375
1376 $dump = _dump(*{"\x{df}::\x{30cc}"});
1377
1378 like(
1379    $dump,
1380    qr/NAME = \Q"\x{30cc}"/,
1381    "NAME is correctly escaped for UTF8 globs with latin1 stashes",
1382 );
1383
1384 like(
1385    $dump,
1386    qr/GvSTASH = 0x[[:xdigit:]]+\s+\Q"\xdf"/,
1387    "GvSTASH is correctly escaped for UTF8 globs with latin1 stashes"
1388 );
1389
1390 like(
1391    $dump,
1392    qr/EGV = 0x[[:xdigit:]]+\s+\Q"\x{30cc}"/,
1393    "EGV is correctly escaped for UTF8 globs with latin1 stashes"
1394 );
1395
1396 like(
1397    _dump(bless {}, "\0::\1::\x{30cd}"),
1398    qr/STASH = 0x[[:xdigit:]]+\s+\Q"\0::\x{01}::\x{30cd}"/,
1399    "STASH for blessed hashrefs is correct"
1400 );
1401
1402 BEGIN { $::{doof} = "\0\1\x{30cd}" }
1403 like(
1404    _dump(\&doof),
1405    qr/PROTOTYPE = \Q"\0\x{01}\x{30cd}"/,
1406    "PROTOTYPE is escaped correctly"
1407 );
1408
1409 {
1410     my $coderef = eval <<"EOP";
1411     use feature 'lexical_subs';
1412     no warnings 'experimental::lexical_subs';
1413     my sub bar (\$\x{30cd}) {1}; \\&bar
1414 EOP
1415     like(
1416        _dump($coderef),
1417        qr/PROTOTYPE = "\$\Q\x{30cd}"/,
1418        "PROTOTYPE works on lexical subs"
1419     )
1420 }
1421
1422 sub get_outside {
1423    eval "sub $_[0] { my \$x; \$x++; return sub { eval q{\$x} } } $_[0]()";
1424 }
1425 sub basic { my $x; return eval q{sub { eval q{$x} }} }
1426 like(
1427     _dump(basic()),
1428     qr/OUTSIDE = 0x[[:xdigit:]]+\s+\Q(basic)/,
1429     'OUTSIDE works'
1430 );
1431
1432 like(
1433     _dump(get_outside("\x{30ce}")),
1434     qr/OUTSIDE = 0x[[:xdigit:]]+\s+\Q(\x{30ce})/,
1435     'OUTSIDE + UTF8 works'
1436 );
1437
1438 # TODO AUTOLOAD = stashname, which requires using a XS autoload
1439 # and calling Dump() on the cv
1440
1441
1442
1443 sub test_utf8_stashes {
1444    my ($stash_name, $test) = @_;
1445
1446    $dump = _dump(\%{"${stash_name}::"});
1447
1448    my $format = utf8::is_utf8($stash_name) ? '\x{%2x}' : '\x%2x';
1449    $escaped_stash_name = join "", map {
1450          $_ eq ':' ? $_ : sprintf $format, ord $_
1451    } split //, $stash_name;
1452
1453    like(
1454       $dump,
1455       qr/\QNAME = "$escaped_stash_name"/,
1456       "NAME is correct escaped for $test"
1457    );
1458
1459    like(
1460       $dump,
1461       qr/\QENAME = "$escaped_stash_name"/,
1462       "ENAME is correct escaped for $test"
1463    );
1464 }
1465
1466 for my $test (
1467   [ "\x{30cd}", "UTF8 stashes" ],
1468    [ "\x{df}", "latin 1 stashes" ],
1469    [ "\x{df}::\x{30cd}", "latin1 + UTF8 stashes" ],
1470    [ "\x{30cd}::\x{df}", "UTF8 + latin1 stashes" ],
1471 ) {
1472    test_utf8_stashes(@$test);
1473 }
1474
1475 }
1476
1477 sub test_DumpProg {
1478     my ($prog, $expected, $name, $test) = @_;
1479     $test ||= 'like';
1480
1481     my $u = 'use Devel::Peek "DumpProg"; DumpProg();';
1482
1483     # Interface between Test::Builder & test.pl
1484     my $builder = Test::More->builder();
1485     t::curr_test($builder->current_test() + 1);
1486
1487     utf8::encode($prog);
1488     
1489     if ( $test eq 'is' ) {
1490         t::fresh_perl_is($prog . $u, $expected, undef, $name)
1491     }
1492     else {
1493         t::fresh_perl_like($prog . $u, $expected, undef, $name)
1494     }
1495
1496     $builder->current_test(t::curr_test() - 1);
1497 }
1498
1499 my $threads = $Config{'useithreads'};
1500
1501 for my $test (
1502 [
1503     "package test;",
1504     qr/PACKAGE = "test"/,
1505     "DumpProg() + package declaration"
1506 ],
1507 [
1508     "use utf8; package \x{30cd};",
1509     qr/PACKAGE = "\\x\Q{30cd}"/,
1510     "DumpProg() + UTF8 package declaration"
1511 ],
1512 [
1513     "use utf8; sub \x{30cc}::\x{30cd} {1}; \x{30cc}::\x{30cd};",
1514     ($threads ? qr/PADIX = \d+/ : qr/GV = \Q\x{30cc}::\x{30cd}\E/)
1515 ],
1516 [
1517     "use utf8; \x{30cc}: { last \x{30cc} }",
1518     qr/LABEL = \Q"\x{30cc}"/
1519 ],
1520 )
1521 {
1522    test_DumpProg(@$test);
1523 }
1524
1525 my $e = <<'EODUMP';
1526 dumpindent is 4 at - line 1.
1527 {
1528 1   TYPE = leave  ===> NULL
1529     TARG = 1
1530     FLAGS = (VOID,KIDS,PARENS,SLABBED)
1531     PRIVATE = (REFCOUNTED)
1532     REFCNT = 1
1533     {
1534 2       TYPE = enter  ===> 3
1535         FLAGS = (UNKNOWN,SLABBED)
1536     }
1537     {
1538 3       TYPE = nextstate  ===> 4
1539         FLAGS = (VOID,SLABBED)
1540         LINE = 1
1541         PACKAGE = "t"
1542     }
1543     {
1544 5       TYPE = entersub  ===> 1
1545         TARG = TARGS_REPLACE
1546         FLAGS = (VOID,KIDS,STACKED,SLABBED)
1547         PRIVATE = (HASTARG)
1548         {
1549 6           TYPE = null  ===> (5)
1550               (was list)
1551             FLAGS = (UNKNOWN,KIDS,SLABBED)
1552             {
1553 4               TYPE = pushmark  ===> 7
1554                 FLAGS = (SCALAR,SLABBED)
1555             }
1556             {
1557 8               TYPE = null  ===> (6)
1558                   (was rv2cv)
1559                 FLAGS = (SCALAR,KIDS,SLABBED)
1560                 {
1561 7                   TYPE = gv  ===> 5
1562                     FLAGS = (SCALAR,SLABBED)
1563                     GV_OR_PADIX
1564                 }
1565             }
1566         }
1567     }
1568 }
1569 EODUMP
1570
1571 $e =~ s/TARGS_REPLACE/$threads ? 3 : 1/e;
1572 $e =~ s/GV_OR_PADIX/$threads ? "PADIX = 2" : "GV = t::DumpProg"/e;
1573
1574 test_DumpProg("package t;", $e, "DumpProg() has no 'Attempt to free X prematurely' warning", "is" );
1575
1576 done_testing();