Filename | /home/micha/.plenv/versions/5.38.2/lib/perl5/site_perl/5.38.2/Test2/API/Instance.pm |
Statements | Executed 140 statements in 2.22ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 541µs | 2.30ms | BEGIN@13 | Test2::API::Instance::
1 | 1 | 1 | 400µs | 3.31ms | BEGIN@14 | Test2::API::Instance::
3 | 1 | 1 | 36µs | 485µs | load | Test2::API::Instance::
1 | 1 | 1 | 33µs | 113µs | set_exit | Test2::API::Instance::
1 | 1 | 1 | 11µs | 13µs | _finalize | Test2::API::Instance::
1 | 1 | 1 | 11µs | 13µs | BEGIN@2 | Test2::API::Instance::
1 | 1 | 1 | 10µs | 11µs | reset | Test2::API::Instance::
1 | 1 | 1 | 10µs | 12µs | BEGIN@53 | Test2::API::Instance::
1 | 1 | 1 | 8µs | 12µs | BEGIN@62 | Test2::API::Instance::
1 | 1 | 1 | 7µs | 232µs | BEGIN@16 | Test2::API::Instance::
2 | 2 | 1 | 6µs | 21µs | __ANON__[:60] | Test2::API::Instance::
1 | 1 | 1 | 5µs | 8µs | add_post_load_callback | Test2::API::Instance::
1 | 1 | 1 | 4µs | 35µs | BEGIN@11 | Test2::API::Instance::
1 | 1 | 1 | 4µs | 24µs | BEGIN@8 | Test2::API::Instance::
1 | 1 | 1 | 4µs | 28µs | BEGIN@63 | Test2::API::Instance::
1 | 1 | 1 | 4µs | 22µs | BEGIN@3 | Test2::API::Instance::
1 | 1 | 1 | 4µs | 16µs | BEGIN@9 | Test2::API::Instance::
1 | 1 | 1 | 4µs | 26µs | import | Test2::API::Instance::
1 | 1 | 1 | 3µs | 3µs | add_formatter | Test2::API::Instance::
1 | 1 | 1 | 2µs | 3µs | add_context_acquire_callback | Test2::API::Instance::
1 | 1 | 1 | 2µs | 3µs | add_exit_callback | Test2::API::Instance::
1 | 1 | 1 | 2µs | 13µs | init | Test2::API::Instance::
1 | 1 | 1 | 2µs | 2µs | pid | Test2::API::Instance::
1 | 1 | 1 | 1µs | 1µs | tid | Test2::API::Instance::
1 | 1 | 1 | 1µs | 1µs | has_ipc | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | __ANON__[:195] | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | __ANON__[:215] | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | __ANON__[:375] | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | __ANON__[:418] | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | _check_pid | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | _ipc_wait | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | add_context_init_callback | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | add_context_release_callback | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | add_ipc_driver | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | add_pre_subtest_callback | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | disable_ipc_polling | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | enable_ipc_polling | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | formatter_set | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | get_ipc_pending | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | ipc_disable | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | post_preload_reset | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | set_ipc_pending | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | start_preload | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | stop_preload | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | test2_disable_trace_stamps | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | test2_enable_trace_stamps | Test2::API::Instance::
0 | 0 | 0 | 0s | 0s | test2_trace_stamps_enabled | Test2::API::Instance::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Test2::API::Instance; | ||||
2 | 2 | 26µs | 2 | 14µs | # spent 13µs (11+2) within Test2::API::Instance::BEGIN@2 which was called:
# once (11µs+2µs) by Test2::API::BEGIN@51 at line 2 # spent 13µs making 1 call to Test2::API::Instance::BEGIN@2
# spent 2µs making 1 call to strict::import |
3 | 2 | 35µs | 2 | 40µs | # spent 22µs (4+18) within Test2::API::Instance::BEGIN@3 which was called:
# once (4µs+18µs) by Test2::API::BEGIN@51 at line 3 # spent 22µs making 1 call to Test2::API::Instance::BEGIN@3
# spent 18µs making 1 call to warnings::import |
4 | |||||
5 | 1 | 300ns | our $VERSION = '1.302198'; | ||
6 | |||||
7 | 1 | 900ns | our @CARP_NOT = qw/Test2::API Test2::API::Instance Test2::IPC::Driver Test2::Formatter/; | ||
8 | 2 | 17µs | 2 | 44µs | # spent 24µs (4+20) within Test2::API::Instance::BEGIN@8 which was called:
# once (4µs+20µs) by Test2::API::BEGIN@51 at line 8 # spent 24µs making 1 call to Test2::API::Instance::BEGIN@8
# spent 20µs making 1 call to Exporter::import |
9 | 2 | 21µs | 2 | 28µs | # spent 16µs (4+12) within Test2::API::Instance::BEGIN@9 which was called:
# once (4µs+12µs) by Test2::API::BEGIN@51 at line 9 # spent 16µs making 1 call to Test2::API::Instance::BEGIN@9
# spent 12µs making 1 call to Exporter::import |
10 | |||||
11 | 2 | 17µs | 2 | 66µs | # spent 35µs (4+31) within Test2::API::Instance::BEGIN@11 which was called:
# once (4µs+31µs) by Test2::API::BEGIN@51 at line 11 # spent 35µs making 1 call to Test2::API::Instance::BEGIN@11
# spent 31µs making 1 call to Exporter::import |
12 | |||||
13 | 2 | 82µs | 1 | 2.30ms | # spent 2.30ms (541µs+1.76) within Test2::API::Instance::BEGIN@13 which was called:
# once (541µs+1.76ms) by Test2::API::BEGIN@51 at line 13 # spent 2.30ms making 1 call to Test2::API::Instance::BEGIN@13 |
14 | 2 | 88µs | 1 | 3.31ms | # spent 3.31ms (400µs+2.91) within Test2::API::Instance::BEGIN@14 which was called:
# once (400µs+2.91ms) by Test2::API::BEGIN@51 at line 14 # spent 3.31ms making 1 call to Test2::API::Instance::BEGIN@14 |
15 | |||||
16 | 1 | 3µs | 1 | 225µs | # spent 232µs (7+225) within Test2::API::Instance::BEGIN@16 which was called:
# once (7µs+225µs) by Test2::API::BEGIN@51 at line 41 # spent 225µs making 1 call to Test2::Util::HashBase::import |
17 | _pid _tid | ||||
18 | no_wait | ||||
19 | finalized loaded | ||||
20 | ipc stack formatter | ||||
21 | contexts | ||||
22 | |||||
23 | add_uuid_via | ||||
24 | |||||
25 | -preload | ||||
26 | |||||
27 | ipc_disabled | ||||
28 | ipc_polling | ||||
29 | ipc_drivers | ||||
30 | ipc_timeout | ||||
31 | formatters | ||||
32 | |||||
33 | exit_callbacks | ||||
34 | post_load_callbacks | ||||
35 | context_acquire_callbacks | ||||
36 | context_init_callbacks | ||||
37 | context_release_callbacks | ||||
38 | pre_subtest_callbacks | ||||
39 | |||||
40 | trace_stamps | ||||
41 | 1 | 139µs | 1 | 232µs | }; # spent 232µs making 1 call to Test2::API::Instance::BEGIN@16 |
42 | |||||
43 | sub DEFAULT_IPC_TIMEOUT() { 30 } | ||||
44 | |||||
45 | sub test2_enable_trace_stamps { $_[0]->{+TRACE_STAMPS} = 1 } | ||||
46 | sub test2_disable_trace_stamps { $_[0]->{+TRACE_STAMPS} = 0 } | ||||
47 | sub test2_trace_stamps_enabled { $_[0]->{+TRACE_STAMPS} } | ||||
48 | |||||
49 | 1 | 2µs | # spent 2µs within Test2::API::Instance::pid which was called:
# once (2µs+0s) by Test2::API::test2_set_is_end at line 35 of Test2/API.pm | ||
50 | 1 | 1µs | # spent 1µs within Test2::API::Instance::tid which was called:
# once (1µs+0s) by Test2::API::test2_set_is_end at line 36 of Test2/API.pm | ||
51 | |||||
52 | # Wrap around the getters that should call _finalize. | ||||
53 | # spent 12µs (10+2) within Test2::API::Instance::BEGIN@53 which was called:
# once (10µs+2µs) by Test2::API::BEGIN@51 at line 66 | ||||
54 | 1 | 2µs | for my $finalizer (IPC, FORMATTER) { | ||
55 | 2 | 6µs | 2 | 2µs | my $orig = __PACKAGE__->can($finalizer); # spent 2µs making 2 calls to UNIVERSAL::can, avg 1µs/call |
56 | # spent 21µs (6+14) within Test2::API::Instance::__ANON__[/home/micha/.plenv/versions/5.38.2/lib/perl5/site_perl/5.38.2/Test2/API/Instance.pm:60] which was called 2 times, avg 10µs/call:
# once (4µs+14µs) by Test2::API::test2_formatter at line 305 of Test2/API.pm
# once (2µs+700ns) by Test2::API::test2_ipc at line 282 of Test2/API.pm | ||||
57 | 2 | 200ns | my $self = shift; | ||
58 | 2 | 1µs | 1 | 13µs | $self->_finalize unless $self->{+FINALIZED}; # spent 13µs making 1 call to Test2::API::Instance::_finalize |
59 | 2 | 5µs | 2 | 1µs | $self->$orig; # spent 1µs making 2 calls to Test2::Util::HashBase::__ANON__[Test2/Util/HashBase.pm:84], avg 700ns/call |
60 | 2 | 2µs | }; | ||
61 | |||||
62 | 2 | 48µs | 2 | 17µs | # spent 12µs (8+5) within Test2::API::Instance::BEGIN@62 which was called:
# once (8µs+5µs) by Test2::API::BEGIN@51 at line 62 # spent 12µs making 1 call to Test2::API::Instance::BEGIN@62
# spent 5µs making 1 call to strict::unimport |
63 | 2 | 27µs | 2 | 51µs | # spent 28µs (4+24) within Test2::API::Instance::BEGIN@63 which was called:
# once (4µs+24µs) by Test2::API::BEGIN@51 at line 63 # spent 28µs making 1 call to Test2::API::Instance::BEGIN@63
# spent 24µs making 1 call to warnings::unimport |
64 | 2 | 2µs | *{$finalizer} = $new; | ||
65 | } | ||||
66 | 1 | 1.57ms | 1 | 12µs | } # spent 12µs making 1 call to Test2::API::Instance::BEGIN@53 |
67 | |||||
68 | 1 | 2µs | # spent 1µs within Test2::API::Instance::has_ipc which was called:
# once (1µs+0s) by Test2::API::test2_has_ipc at line 283 of Test2/API.pm | ||
69 | |||||
70 | # spent 26µs (4+23) within Test2::API::Instance::import which was called:
# once (4µs+23µs) by Test2::API::BEGIN@51 at line 51 of Test2/API.pm | ||||
71 | 1 | 300ns | my $class = shift; | ||
72 | 1 | 300ns | return unless @_; | ||
73 | 1 | 300ns | my ($ref) = @_; | ||
74 | 1 | 2µs | 1 | 23µs | $$ref = $class->new; # spent 23µs making 1 call to Test2::Util::HashBase::_new |
75 | } | ||||
76 | |||||
77 | 1 | 2µs | 1 | 11µs | # spent 13µs (2+11) within Test2::API::Instance::init which was called:
# once (2µs+11µs) by Test2::Util::HashBase::_new at line 155 of Test2/Util/HashBase.pm # spent 11µs making 1 call to Test2::API::Instance::reset |
78 | |||||
79 | sub start_preload { | ||||
80 | my $self = shift; | ||||
81 | |||||
82 | confess "preload cannot be started, Test2::API has already been initialized" | ||||
83 | if $self->{+FINALIZED} || $self->{+LOADED}; | ||||
84 | |||||
85 | return $self->{+PRELOAD} = 1; | ||||
86 | } | ||||
87 | |||||
88 | sub stop_preload { | ||||
89 | my $self = shift; | ||||
90 | |||||
91 | return 0 unless $self->{+PRELOAD}; | ||||
92 | $self->{+PRELOAD} = 0; | ||||
93 | |||||
94 | $self->post_preload_reset(); | ||||
95 | |||||
96 | return 1; | ||||
97 | } | ||||
98 | |||||
99 | sub post_preload_reset { | ||||
100 | my $self = shift; | ||||
101 | |||||
102 | delete $self->{+_PID}; | ||||
103 | delete $self->{+_TID}; | ||||
104 | |||||
105 | $self->{+ADD_UUID_VIA} = undef unless exists $self->{+ADD_UUID_VIA}; | ||||
106 | |||||
107 | $self->{+CONTEXTS} = {}; | ||||
108 | |||||
109 | $self->{+FORMATTERS} = []; | ||||
110 | |||||
111 | $self->{+FINALIZED} = undef; | ||||
112 | $self->{+IPC} = undef; | ||||
113 | $self->{+IPC_DISABLED} = $ENV{T2_NO_IPC} ? 1 : 0; | ||||
114 | |||||
115 | $self->{+IPC_TIMEOUT} = DEFAULT_IPC_TIMEOUT() unless defined $self->{+IPC_TIMEOUT}; | ||||
116 | |||||
117 | $self->{+LOADED} = 0; | ||||
118 | |||||
119 | $self->{+STACK} ||= Test2::API::Stack->new; | ||||
120 | } | ||||
121 | |||||
122 | # spent 11µs (10+1) within Test2::API::Instance::reset which was called:
# once (10µs+1µs) by Test2::API::Instance::init at line 77 | ||||
123 | 1 | 100ns | my $self = shift; | ||
124 | |||||
125 | 1 | 1µs | delete $self->{+_PID}; | ||
126 | 1 | 100ns | delete $self->{+_TID}; | ||
127 | |||||
128 | 1 | 600ns | $self->{+TRACE_STAMPS} = $ENV{T2_TRACE_STAMPS} || 0; | ||
129 | |||||
130 | 1 | 300ns | $self->{+ADD_UUID_VIA} = undef; | ||
131 | |||||
132 | 1 | 400ns | $self->{+CONTEXTS} = {}; | ||
133 | |||||
134 | 1 | 200ns | $self->{+IPC_DRIVERS} = []; | ||
135 | 1 | 200ns | $self->{+IPC_POLLING} = undef; | ||
136 | |||||
137 | 1 | 200ns | $self->{+FORMATTERS} = []; | ||
138 | 1 | 500ns | $self->{+FORMATTER} = undef; | ||
139 | |||||
140 | 1 | 200ns | $self->{+FINALIZED} = undef; | ||
141 | 1 | 200ns | $self->{+IPC} = undef; | ||
142 | 1 | 300ns | $self->{+IPC_DISABLED} = $ENV{T2_NO_IPC} ? 1 : 0; | ||
143 | |||||
144 | 1 | 900ns | $self->{+IPC_TIMEOUT} = DEFAULT_IPC_TIMEOUT() unless defined $self->{+IPC_TIMEOUT}; | ||
145 | |||||
146 | 1 | 100ns | $self->{+NO_WAIT} = 0; | ||
147 | 1 | 200ns | $self->{+LOADED} = 0; | ||
148 | |||||
149 | 1 | 200ns | $self->{+EXIT_CALLBACKS} = []; | ||
150 | 1 | 100ns | $self->{+POST_LOAD_CALLBACKS} = []; | ||
151 | 1 | 100ns | $self->{+CONTEXT_ACQUIRE_CALLBACKS} = []; | ||
152 | 1 | 200ns | $self->{+CONTEXT_INIT_CALLBACKS} = []; | ||
153 | 1 | 100ns | $self->{+CONTEXT_RELEASE_CALLBACKS} = []; | ||
154 | 1 | 200ns | $self->{+PRE_SUBTEST_CALLBACKS} = []; | ||
155 | |||||
156 | 1 | 2µs | 1 | 1µs | $self->{+STACK} = Test2::API::Stack->new; # spent 1µs making 1 call to Test2::API::Stack::new |
157 | } | ||||
158 | |||||
159 | # spent 13µs (11+2) within Test2::API::Instance::_finalize which was called:
# once (11µs+2µs) by Test2::API::Instance::__ANON__[/home/micha/.plenv/versions/5.38.2/lib/perl5/site_perl/5.38.2/Test2/API/Instance.pm:60] at line 58 | ||||
160 | 1 | 100ns | my $self = shift; | ||
161 | 1 | 300ns | my ($caller) = @_; | ||
162 | 1 | 3µs | $caller ||= [caller(1)]; | ||
163 | |||||
164 | confess "Attempt to initialize Test2::API during preload" | ||||
165 | 1 | 200ns | if $self->{+PRELOAD}; | ||
166 | |||||
167 | 1 | 200ns | $self->{+FINALIZED} = $caller; | ||
168 | |||||
169 | 1 | 300ns | $self->{+_PID} = $$ unless defined $self->{+_PID}; | ||
170 | 1 | 200ns | $self->{+_TID} = get_tid() unless defined $self->{+_TID}; | ||
171 | |||||
172 | 1 | 300ns | unless ($self->{+FORMATTER}) { | ||
173 | 1 | 200ns | my ($formatter, $source); | ||
174 | 1 | 2µs | if ($ENV{T2_FORMATTER}) { | ||
175 | $source = "set by the 'T2_FORMATTER' environment variable"; | ||||
176 | |||||
177 | if ($ENV{T2_FORMATTER} =~ m/^(\+)?(.*)$/) { | ||||
178 | $formatter = $1 ? $2 : "Test2::Formatter::$2" | ||||
179 | } | ||||
180 | else { | ||||
181 | $formatter = ''; | ||||
182 | } | ||||
183 | } | ||||
184 | elsif (@{$self->{+FORMATTERS}}) { | ||||
185 | 1 | 600ns | ($formatter) = @{$self->{+FORMATTERS}}; | ||
186 | 1 | 200ns | $source = "Most recently added"; | ||
187 | } | ||||
188 | else { | ||||
189 | $formatter = 'Test2::Formatter::TAP'; | ||||
190 | $source = 'default formatter'; | ||||
191 | } | ||||
192 | |||||
193 | 1 | 5µs | 1 | 2µs | unless (ref($formatter) || $formatter->can('write')) { # spent 2µs making 1 call to UNIVERSAL::can |
194 | my $file = pkg_to_file($formatter); | ||||
195 | my ($ok, $err) = try { require $file }; | ||||
196 | unless ($ok) { | ||||
197 | my $line = "* COULD NOT LOAD FORMATTER '$formatter' ($source) *"; | ||||
198 | my $border = '*' x length($line); | ||||
199 | die "\n\n $border\n $line\n $border\n\n$err"; | ||||
200 | } | ||||
201 | } | ||||
202 | |||||
203 | 1 | 400ns | $self->{+FORMATTER} = $formatter; | ||
204 | } | ||||
205 | |||||
206 | # Turn on IPC if threads are on, drivers are registered, or the Test2::IPC | ||||
207 | # module is loaded. | ||||
208 | 1 | 200ns | return if $self->{+IPC_DISABLED}; | ||
209 | 1 | 2µs | return unless USE_THREADS || $INC{'Test2/IPC.pm'} || @{$self->{+IPC_DRIVERS}}; | ||
210 | |||||
211 | # Turn on polling by default, people expect it. | ||||
212 | $self->enable_ipc_polling; | ||||
213 | |||||
214 | unless (@{$self->{+IPC_DRIVERS}}) { | ||||
215 | my ($ok, $error) = try { require Test2::IPC::Driver::Files }; | ||||
216 | die $error unless $ok; | ||||
217 | push @{$self->{+IPC_DRIVERS}} => 'Test2::IPC::Driver::Files'; | ||||
218 | } | ||||
219 | |||||
220 | for my $driver (@{$self->{+IPC_DRIVERS}}) { | ||||
221 | next unless $driver->can('is_viable') && $driver->is_viable; | ||||
222 | $self->{+IPC} = $driver->new or next; | ||||
223 | return; | ||||
224 | } | ||||
225 | |||||
226 | die "IPC has been requested, but no viable drivers were found. Aborting...\n"; | ||||
227 | } | ||||
228 | |||||
229 | sub formatter_set { $_[0]->{+FORMATTER} ? 1 : 0 } | ||||
230 | |||||
231 | # spent 3µs within Test2::API::Instance::add_formatter which was called:
# once (3µs+0s) by Test2::API::test2_formatter_add at line 309 of Test2/API.pm | ||||
232 | 1 | 100ns | my $self = shift; | ||
233 | 1 | 400ns | my ($formatter) = @_; | ||
234 | 1 | 900ns | unshift @{$self->{+FORMATTERS}} => $formatter; | ||
235 | |||||
236 | 1 | 4µs | return unless $self->{+FINALIZED}; | ||
237 | |||||
238 | # Why is the @CARP_NOT entry not enough? | ||||
239 | local %Carp::Internal = %Carp::Internal; | ||||
240 | $Carp::Internal{'Test2::Formatter'} = 1; | ||||
241 | |||||
242 | carp "Formatter $formatter loaded too late to be used as the global formatter"; | ||||
243 | } | ||||
244 | |||||
245 | # spent 3µs (2+300ns) within Test2::API::Instance::add_context_acquire_callback which was called:
# once (2µs+300ns) by Test2::API::test2_add_callback_context_aquire at line 263 of Test2/API.pm | ||||
246 | 1 | 200ns | my $self = shift; | ||
247 | 1 | 100ns | my ($code) = @_; | ||
248 | |||||
249 | 1 | 2µs | 1 | 300ns | my $rtype = reftype($code) || ""; # spent 300ns making 1 call to Scalar::Util::reftype |
250 | |||||
251 | 1 | 200ns | confess "Context-acquire callbacks must be coderefs" | ||
252 | unless $code && $rtype eq 'CODE'; | ||||
253 | |||||
254 | 1 | 2µs | push @{$self->{+CONTEXT_ACQUIRE_CALLBACKS}} => $code; | ||
255 | } | ||||
256 | |||||
257 | sub add_context_init_callback { | ||||
258 | my $self = shift; | ||||
259 | my ($code) = @_; | ||||
260 | |||||
261 | my $rtype = reftype($code) || ""; | ||||
262 | |||||
263 | confess "Context-init callbacks must be coderefs" | ||||
264 | unless $code && $rtype eq 'CODE'; | ||||
265 | |||||
266 | push @{$self->{+CONTEXT_INIT_CALLBACKS}} => $code; | ||||
267 | } | ||||
268 | |||||
269 | sub add_context_release_callback { | ||||
270 | my $self = shift; | ||||
271 | my ($code) = @_; | ||||
272 | |||||
273 | my $rtype = reftype($code) || ""; | ||||
274 | |||||
275 | confess "Context-release callbacks must be coderefs" | ||||
276 | unless $code && $rtype eq 'CODE'; | ||||
277 | |||||
278 | push @{$self->{+CONTEXT_RELEASE_CALLBACKS}} => $code; | ||||
279 | } | ||||
280 | |||||
281 | # spent 8µs (5+3) within Test2::API::Instance::add_post_load_callback which was called:
# once (5µs+3µs) by Test2::API::test2_add_callback_post_load at line 267 of Test2/API.pm | ||||
282 | 1 | 200ns | my $self = shift; | ||
283 | 1 | 200ns | my ($code) = @_; | ||
284 | |||||
285 | 1 | 6µs | 1 | 3µs | my $rtype = reftype($code) || ""; # spent 3µs making 1 call to Scalar::Util::reftype |
286 | |||||
287 | 1 | 500ns | confess "Post-load callbacks must be coderefs" | ||
288 | unless $code && $rtype eq 'CODE'; | ||||
289 | |||||
290 | 1 | 800ns | push @{$self->{+POST_LOAD_CALLBACKS}} => $code; | ||
291 | 1 | 2µs | $code->() if $self->{+LOADED}; | ||
292 | } | ||||
293 | |||||
294 | sub add_pre_subtest_callback { | ||||
295 | my $self = shift; | ||||
296 | my ($code) = @_; | ||||
297 | |||||
298 | my $rtype = reftype($code) || ""; | ||||
299 | |||||
300 | confess "Pre-subtest callbacks must be coderefs" | ||||
301 | unless $code && $rtype eq 'CODE'; | ||||
302 | |||||
303 | push @{$self->{+PRE_SUBTEST_CALLBACKS}} => $code; | ||||
304 | } | ||||
305 | |||||
306 | # spent 485µs (36+449) within Test2::API::Instance::load which was called 3 times, avg 162µs/call:
# 3 times (36µs+449µs) by Test2::API::test2_load at line 204 of Test2/API.pm, avg 162µs/call | ||||
307 | 3 | 800ns | my $self = shift; | ||
308 | 3 | 1µs | unless ($self->{+LOADED}) { | ||
309 | confess "Attempt to initialize Test2::API during preload" | ||||
310 | 1 | 300ns | if $self->{+PRELOAD}; | ||
311 | |||||
312 | 1 | 2µs | $self->{+_PID} = $$ unless defined $self->{+_PID}; | ||
313 | 1 | 500ns | $self->{+_TID} = get_tid() unless defined $self->{+_TID}; | ||
314 | |||||
315 | # This is for https://github.com/Test-More/test-more/issues/16 | ||||
316 | # and https://rt.perl.org/Public/Bug/Display.html?id=127774 | ||||
317 | # END blocks run in reverse order. This insures the END block is loaded | ||||
318 | # as late as possible. It will not solve all cases, but it helps. | ||||
319 | 1 | 21µs | eval "END { Test2::API::test2_set_is_end() }; 1" or die $@; # spent 3µs executing statements in string eval # includes 2µs spent executing 1 call to 1 sub defined therein. | ||
320 | |||||
321 | 1 | 2µs | $self->{+LOADED} = 1; | ||
322 | 1 | 2µs | 1 | 449µs | $_->() for @{$self->{+POST_LOAD_CALLBACKS}}; # spent 449µs making 1 call to Test::Builder::__ANON__[Test/Builder.pm:148] |
323 | } | ||||
324 | 3 | 4µs | return $self->{+LOADED}; | ||
325 | } | ||||
326 | |||||
327 | # spent 3µs (2+200ns) within Test2::API::Instance::add_exit_callback which was called:
# once (2µs+200ns) by Test2::API::test2_add_callback_exit at line 266 of Test2/API.pm | ||||
328 | 1 | 100ns | my $self = shift; | ||
329 | 1 | 100ns | my ($code) = @_; | ||
330 | 1 | 2µs | 1 | 200ns | my $rtype = reftype($code) || ""; # spent 200ns making 1 call to Scalar::Util::reftype |
331 | |||||
332 | 1 | 500ns | confess "End callbacks must be coderefs" | ||
333 | unless $code && $rtype eq 'CODE'; | ||||
334 | |||||
335 | 1 | 1µs | push @{$self->{+EXIT_CALLBACKS}} => $code; | ||
336 | } | ||||
337 | |||||
338 | sub ipc_disable { | ||||
339 | my $self = shift; | ||||
340 | |||||
341 | confess "Attempt to disable IPC after it has been initialized" | ||||
342 | if $self->{+IPC}; | ||||
343 | |||||
344 | $self->{+IPC_DISABLED} = 1; | ||||
345 | } | ||||
346 | |||||
347 | sub add_ipc_driver { | ||||
348 | my $self = shift; | ||||
349 | my ($driver) = @_; | ||||
350 | unshift @{$self->{+IPC_DRIVERS}} => $driver; | ||||
351 | |||||
352 | return unless $self->{+FINALIZED}; | ||||
353 | |||||
354 | # Why is the @CARP_NOT entry not enough? | ||||
355 | local %Carp::Internal = %Carp::Internal; | ||||
356 | $Carp::Internal{'Test2::IPC::Driver'} = 1; | ||||
357 | |||||
358 | carp "IPC driver $driver loaded too late to be used as the global ipc driver"; | ||||
359 | } | ||||
360 | |||||
361 | sub enable_ipc_polling { | ||||
362 | my $self = shift; | ||||
363 | |||||
364 | $self->{+_PID} = $$ unless defined $self->{+_PID}; | ||||
365 | $self->{+_TID} = get_tid() unless defined $self->{+_TID}; | ||||
366 | |||||
367 | $self->add_context_init_callback( | ||||
368 | # This is called every time a context is created, it needs to be fast. | ||||
369 | # $_[0] is a context object | ||||
370 | sub { | ||||
371 | return unless $self->{+IPC_POLLING}; | ||||
372 | return unless $self->{+IPC}; | ||||
373 | return unless $self->{+IPC}->pending(); | ||||
374 | return $_[0]->{hub}->cull; | ||||
375 | } | ||||
376 | ) unless defined $self->ipc_polling; | ||||
377 | |||||
378 | $self->set_ipc_polling(1); | ||||
379 | } | ||||
380 | |||||
381 | sub get_ipc_pending { | ||||
382 | my $self = shift; | ||||
383 | return -1 unless $self->{+IPC}; | ||||
384 | $self->{+IPC}->pending(); | ||||
385 | } | ||||
386 | |||||
387 | sub _check_pid { | ||||
388 | my $self = shift; | ||||
389 | my ($pid) = @_; | ||||
390 | return kill(0, $pid); | ||||
391 | } | ||||
392 | |||||
393 | sub set_ipc_pending { | ||||
394 | my $self = shift; | ||||
395 | return unless $self->{+IPC}; | ||||
396 | my ($val) = @_; | ||||
397 | |||||
398 | confess "value is required for set_ipc_pending" | ||||
399 | unless $val; | ||||
400 | |||||
401 | $self->{+IPC}->set_pending($val); | ||||
402 | } | ||||
403 | |||||
404 | sub disable_ipc_polling { | ||||
405 | my $self = shift; | ||||
406 | return unless defined $self->{+IPC_POLLING}; | ||||
407 | $self->{+IPC_POLLING} = 0; | ||||
408 | } | ||||
409 | |||||
410 | sub _ipc_wait { | ||||
411 | my ($timeout) = @_; | ||||
412 | my $fail = 0; | ||||
413 | |||||
414 | $timeout = DEFAULT_IPC_TIMEOUT() unless defined $timeout; | ||||
415 | |||||
416 | my $ok = eval { | ||||
417 | if (CAN_FORK) { | ||||
418 | local $SIG{ALRM} = sub { die "Timeout waiting on child processes" }; | ||||
419 | alarm $timeout; | ||||
420 | |||||
421 | while (1) { | ||||
422 | my $pid = CORE::wait(); | ||||
423 | my $err = $?; | ||||
424 | last if $pid == -1; | ||||
425 | next unless $err; | ||||
426 | $fail++; | ||||
427 | |||||
428 | my $sig = $err & 127; | ||||
429 | my $exit = $err >> 8; | ||||
430 | warn "Process $pid did not exit cleanly (wstat: $err, exit: $exit, sig: $sig)\n"; | ||||
431 | } | ||||
432 | |||||
433 | alarm 0; | ||||
434 | } | ||||
435 | |||||
436 | if (USE_THREADS) { | ||||
437 | my $start = time; | ||||
438 | |||||
439 | while (1) { | ||||
440 | last unless threads->list(); | ||||
441 | die "Timeout waiting on child thread" if time - $start >= $timeout; | ||||
442 | sleep 1; | ||||
443 | for my $t (threads->list) { | ||||
444 | # threads older than 1.34 do not have this :-( | ||||
445 | next if $t->can('is_joinable') && !$t->is_joinable; | ||||
446 | $t->join; | ||||
447 | # In older threads we cannot check if a thread had an error unless | ||||
448 | # we control it and its return. | ||||
449 | my $err = $t->can('error') ? $t->error : undef; | ||||
450 | next unless $err; | ||||
451 | my $tid = $t->tid(); | ||||
452 | $fail++; | ||||
453 | chomp($err); | ||||
454 | warn "Thread $tid did not end cleanly: $err\n"; | ||||
455 | } | ||||
456 | } | ||||
457 | } | ||||
458 | |||||
459 | 1; | ||||
460 | }; | ||||
461 | my $error = $@; | ||||
462 | |||||
463 | return 0 if $ok && !$fail; | ||||
464 | warn $error unless $ok; | ||||
465 | return 255; | ||||
466 | } | ||||
467 | |||||
468 | # spent 113µs (33+80) within Test2::API::Instance::set_exit which was called:
# once (33µs+80µs) by Test2::API::END at line 56 of Test2/API.pm | ||||
469 | 1 | 300ns | my $self = shift; | ||
470 | |||||
471 | 1 | 400ns | return if $self->{+PRELOAD}; | ||
472 | |||||
473 | 1 | 600ns | my $exit = $?; | ||
474 | 1 | 300ns | my $new_exit = $exit; | ||
475 | |||||
476 | 1 | 1µs | if ($INC{'Test/Builder.pm'} && $Test::Builder::VERSION ne $Test2::API::VERSION) { | ||
477 | print STDERR <<" EOT"; | ||||
478 | |||||
479 | ******************************************************************************** | ||||
480 | * * | ||||
481 | * Test::Builder -- Test2::API version mismatch detected * | ||||
482 | * * | ||||
483 | ******************************************************************************** | ||||
484 | Test2::API Version: $Test2::API::VERSION | ||||
485 | Test::Builder Version: $Test::Builder::VERSION | ||||
486 | |||||
487 | This is not a supported configuration, you will have problems. | ||||
488 | |||||
489 | EOT | ||||
490 | } | ||||
491 | |||||
492 | 1 | 2µs | for my $ctx (values %{$self->{+CONTEXTS}}) { | ||
493 | next unless $ctx; | ||||
494 | |||||
495 | next if $ctx->_aborted && ${$ctx->_aborted}; | ||||
496 | |||||
497 | # Only worry about contexts in this PID | ||||
498 | my $trace = $ctx->trace || next; | ||||
499 | next unless $trace->pid && $trace->pid == $$; | ||||
500 | |||||
501 | # Do not worry about contexts that have no hub | ||||
502 | my $hub = $ctx->hub || next; | ||||
503 | |||||
504 | # Do not worry if the state came to a sudden end. | ||||
505 | next if $hub->bailed_out; | ||||
506 | next if defined $hub->skip_reason; | ||||
507 | |||||
508 | # now we worry | ||||
509 | $trace->alert("context object was never released! This means a testing tool is behaving very badly"); | ||||
510 | |||||
511 | $exit = 255; | ||||
512 | $new_exit = 255; | ||||
513 | } | ||||
514 | |||||
515 | 1 | 3µs | if (!defined($self->{+_PID}) or !defined($self->{+_TID}) or $self->{+_PID} != $$ or $self->{+_TID} != get_tid()) { | ||
516 | $? = $exit; | ||||
517 | return; | ||||
518 | } | ||||
519 | |||||
520 | 1 | 2µs | 1 | 2µs | my @hubs = $self->{+STACK} ? $self->{+STACK}->all : (); # spent 2µs making 1 call to Test2::API::Stack::all |
521 | |||||
522 | 1 | 700ns | if (@hubs and $self->{+IPC} and !$self->{+NO_WAIT}) { | ||
523 | local $?; | ||||
524 | my %seen; | ||||
525 | for my $hub (reverse @hubs) { | ||||
526 | my $ipc = $hub->ipc or next; | ||||
527 | next if $seen{$ipc}++; | ||||
528 | $ipc->waiting(); | ||||
529 | } | ||||
530 | |||||
531 | my $ipc_exit = _ipc_wait($self->{+IPC_TIMEOUT}); | ||||
532 | $new_exit ||= $ipc_exit; | ||||
533 | } | ||||
534 | |||||
535 | # None of this is necessary if we never got a root hub | ||||
536 | 1 | 800ns | if(my $root = shift @hubs) { | ||
537 | 1 | 3µs | 1 | 7µs | my $trace = Test2::EventFacet::Trace->new( # spent 7µs making 1 call to Test2::Util::HashBase::_new |
538 | frame => [__PACKAGE__, __FILE__, 0, __PACKAGE__ . '::END'], | ||||
539 | detail => __PACKAGE__ . ' END Block finalization', | ||||
540 | ); | ||||
541 | 1 | 800ns | 1 | 8µs | my $ctx = Test2::API::Context->new( # spent 8µs making 1 call to Test2::Util::HashBase::_new |
542 | trace => $trace, | ||||
543 | hub => $root, | ||||
544 | ); | ||||
545 | |||||
546 | 1 | 300ns | if (@hubs) { | ||
547 | $ctx->diag("Test ended with extra hubs on the stack!"); | ||||
548 | $new_exit = 255; | ||||
549 | } | ||||
550 | |||||
551 | 1 | 4µs | 2 | 2µs | unless ($root->no_ending) { # spent 1µs making 1 call to Test2::Util::HashBase::__ANON__[Test2/Util/HashBase.pm:84]
# spent 600ns making 1 call to Test2::API::Context::DESTROY |
552 | 1 | 600ns | local $?; | ||
553 | 1 | 2µs | 1 | 1µs | $root->finalize($trace) unless $root->ended; # spent 1µs making 1 call to Test2::Util::HashBase::__ANON__[Test2/Util/HashBase.pm:84] |
554 | 1 | 14µs | 1 | 58µs | $_->($ctx, $exit, \$new_exit) for @{$self->{+EXIT_CALLBACKS}}; # spent 58µs making 1 call to Test::Builder::__ANON__[Test/Builder.pm:156] |
555 | 1 | 1µs | 1 | 300ns | $new_exit ||= $root->failed; # spent 300ns making 1 call to Test2::Util::HashBase::__ANON__[Test2/Util/HashBase.pm:84] |
556 | 1 | 1µs | 1 | 2µs | $new_exit ||= 255 unless $root->is_passing; # spent 2µs making 1 call to Test2::Hub::is_passing |
557 | } | ||||
558 | } | ||||
559 | |||||
560 | 1 | 300ns | $new_exit = 255 if $new_exit > 255; | ||
561 | |||||
562 | 1 | 300ns | if ($new_exit && eval { require Test2::API::Breakage; 1 }) { | ||
563 | my @warn = Test2::API::Breakage->report(); | ||||
564 | |||||
565 | if (@warn) { | ||||
566 | print STDERR "\nYou have loaded versions of test modules known to have problems with Test2.\nThis could explain some test failures.\n"; | ||||
567 | print STDERR "$_\n" for @warn; | ||||
568 | print STDERR "\n"; | ||||
569 | } | ||||
570 | } | ||||
571 | |||||
572 | 1 | 2µs | $? = $new_exit; | ||
573 | } | ||||
574 | |||||
575 | 1 | 3µs | 1; | ||
576 | |||||
577 | __END__ |