11 skip_all_without_config("usedtrace");
13 $dtrace = $Config::Config{dtrace};
17 `$dtrace -V` or skip_all("$dtrace unavailable");
19 my $result = `$dtrace -qnBEGIN -c'$Perl -e 1' 2>&1`;
20 $? && skip_all("Apparently can't probe using $dtrace (perhaps you need root?): $result");
31 'BEGIN { trace(42+666) }',
33 'really running DTrace',
38 sub outer { Your::inner() }
45 'sub-entry { printf("-> %s::%s at %s line %d!\n", copyinstr(arg3), copyinstr(arg0), copyinstr(arg1), arg2) }
46 sub-return { printf("<- %s::%s at %s line %d!\n", copyinstr(arg3), copyinstr(arg0), copyinstr(arg1), arg2) }',
48 qr/-> My::outer at - line 2!
49 -> Your::inner at - line 4!
50 <- Your::inner at - line 4!
51 <- My::outer at - line 2!
52 -> Your::inner at - line 4!
53 <- Your::inner at - line 4!/,
55 'traced multiple function calls',
60 'phase-change { printf("%s -> %s; ", copyinstr(arg1), copyinstr(arg0)) }',
61 qr/START -> RUN; RUN -> DESTRUCT;/,
62 'phase changes of a simple script',
65 # this code taken from t/op/magic_phase.t which tests all of the
66 # transitions of ${^GLOBAL_PHASE}. instead of printing (which will
67 # interact nondeterministically with the DTrace output), we increment
68 # an unused variable for side effects
69 dtrace_like(<< 'MAGIC_OP',
74 sub Moo::DESTROY { $x++ }
76 my $tiger = bless {}, Moo::;
78 sub Kooh::DESTROY { $x++ }
80 our $affe = bless {}, Kooh::;
85 'phase-change { printf("%s -> %s; ", copyinstr(arg1), copyinstr(arg0)) }',
87 qr/START -> CHECK; CHECK -> INIT; INIT -> RUN; RUN -> END; END -> DESTRUCT;/,
89 'phase-changes in a script that exercises all of ${^GLOBAL_PHASE}',
92 dtrace_like(<< 'PHASES',
104 BEGIN { starting = 1 }
106 phase-change { phase = arg0 }
107 phase-change /copyinstr(arg0) == "RUN"/ { starting = 0 }
108 phase-change /copyinstr(arg0) == "END"/ { ending = 1 }
110 sub-entry /copyinstr(arg0) != copyinstr(phase) && (starting || ending)/ {
111 printf("%s during %s; ", copyinstr(arg0), copyinstr(phase));
115 qr/foo during INIT; baz during END;/,
117 'make sure sub-entry and phase-change interact well',
120 dtrace_like(<< 'PERL_SCRIPT',
126 op-entry { printf("op-entry <%s>\n", copyinstr(arg0)) }
129 qr/op-entry <subst>/,
130 qr/op-entry <schop>/,
135 dtrace_like(<< 'PERL_SCRIPT',
141 loading-file { printf("loading-file <%s>\n", copyinstr(arg0)) }
142 loaded-file { printf("loaded-file <%s>\n", copyinstr(arg0)) }
145 # the original test made sure that each file generated a loading-file then a loaded-file,
146 # but that had a race condition when the kernel would push the perl process onto a different
147 # CPU, so the DTrace output would appear out of order
148 qr{loading-file <strict\.pm>.*loading-file <HTTP/Tiny\.pm>.*loading-file <run/dtrace\.pl>}s,
149 qr{loaded-file <strict\.pm>.*loaded-file <HTTP/Tiny\.pm>.*loaded-file <run/dtrace\.pl>}s,
151 'loading-file, loaded-file probes',
157 my $expected = shift;
160 my ($reader, $writer);
162 my $pid = open2($reader, $writer,
165 '-n', 'BEGIN { trace("ready!\n") }', # necessary! see below
170 # wait until DTrace tells us that it is initialized
171 # otherwise our probes won't properly fire
172 chomp(my $throwaway = <$reader>);
173 $throwaway eq "ready!" or die "Unexpected 'ready!' result from DTrace: $throwaway";
175 # now we can start executing our perl
179 # read all the dtrace results back in
181 my $result = <$reader>;
183 # make sure that dtrace is all done and successful
185 my $child_exit_status = $? >> 8;
186 die "Unexpected error from DTrace: $result"
187 if $child_exit_status != 0;
189 if (ref($expected) eq 'ARRAY') {
190 like($result, $_, $name) for @$expected;
193 like($result, $expected, $name);