This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
skip a Tets-Simple test that's leaking shm blocks
[perl5.git] / cpan / Test-Simple / t / Test2 / modules / API / Instance.t
CommitLineData
b4514920
CG
1use strict;
2use warnings;
3
4use Test2::IPC;
5BEGIN { require "t/tools.pl" };
6use Test2::Util qw/CAN_THREAD CAN_REALLY_FORK USE_THREADS get_tid/;
7
33d95a65
TC
8skip_all("Leaks shm blocks");
9
b4514920
CG
10my $CLASS = 'Test2::API::Instance';
11
12my $one = $CLASS->new;
13is_deeply(
14 $one,
15 {
b4514920
CG
16 contexts => {},
17
18 finalized => undef,
19 ipc => undef,
20 formatter => undef,
21
22 ipc_polling => undef,
23 ipc_drivers => [],
24
25 formatters => [],
26
27 no_wait => 0,
28 loaded => 0,
29
30 exit_callbacks => [],
31 post_load_callbacks => [],
32 context_acquire_callbacks => [],
33 context_init_callbacks => [],
34 context_release_callbacks => [],
35
36 stack => [],
37 },
38 "Got initial settings"
39);
40
41%$one = ();
42is_deeply($one, {}, "wiped object");
43
44$one->reset;
45is_deeply(
46 $one,
47 {
b4514920
CG
48 contexts => {},
49
50 ipc_polling => undef,
51 ipc_drivers => [],
52
53 formatters => [],
54
55 finalized => undef,
56 ipc => undef,
57 formatter => undef,
58
59 no_wait => 0,
60 loaded => 0,
61
62 exit_callbacks => [],
63 post_load_callbacks => [],
64 context_acquire_callbacks => [],
65 context_init_callbacks => [],
66 context_release_callbacks => [],
67
68 stack => [],
69 },
70 "Reset Object"
71);
72
73ok(!$one->formatter_set, "no formatter set");
74$one->set_formatter('Foo');
75ok($one->formatter_set, "formatter set");
76$one->reset;
77
78my $ran = 0;
79my $callback = sub { $ran++ };
80$one->add_post_load_callback($callback);
81ok(!$ran, "did not run yet");
82is_deeply($one->post_load_callbacks, [$callback], "stored callback for later");
83
84ok(!$one->loaded, "not loaded");
85$one->load;
86ok($one->loaded, "loaded");
87is($ran, 1, "ran the callback");
88
89$one->load;
90is($ran, 1, "Did not run the callback again");
91
92$one->add_post_load_callback($callback);
93is($ran, 2, "ran the new callback");
94is_deeply($one->post_load_callbacks, [$callback, $callback], "stored callback for the record");
95
96like(
97 exception { $one->add_post_load_callback({}) },
98 qr/Post-load callbacks must be coderefs/,
99 "Post-load callbacks must be coderefs"
100);
101
102$one->reset;
103ok($one->ipc, 'got ipc');
104ok($one->finalized, "calling ipc finalized the object");
105
106$one->reset;
107ok($one->stack, 'got stack');
108ok(!$one->finalized, "calling stack did not finaliz the object");
109
110$one->reset;
111ok($one->formatter, 'Got formatter');
112ok($one->finalized, "calling format finalized the object");
113
114$one->reset;
115$one->set_formatter('Foo');
116is($one->formatter, 'Foo', "got specified formatter");
117ok($one->finalized, "calling format finalized the object");
118
119{
120 local $ENV{T2_FORMATTER} = 'TAP';
121 $one->reset;
122 is($one->formatter, 'Test2::Formatter::TAP', "got specified formatter");
123 ok($one->finalized, "calling format finalized the object");
124
125 local $ENV{T2_FORMATTER} = '+Test2::Formatter::TAP';
126 $one->reset;
127 is($one->formatter, 'Test2::Formatter::TAP', "got specified formatter");
128 ok($one->finalized, "calling format finalized the object");
129
130 local $ENV{T2_FORMATTER} = '+Fake';
131 $one->reset;
132 like(
133 exception { $one->formatter },
134 qr/COULD NOT LOAD FORMATTER 'Fake' \(set by the 'T2_FORMATTER' environment variable\)/,
135 "Bad formatter"
136 );
137}
138
139$ran = 0;
140$one->reset;
141$one->add_exit_callback($callback);
142is(@{$one->exit_callbacks}, 1, "added an exit callback");
143$one->add_exit_callback($callback);
144is(@{$one->exit_callbacks}, 2, "added another exit callback");
145
146like(
147 exception { $one->add_exit_callback({}) },
148 qr/End callbacks must be coderefs/,
149 "Exit callbacks must be coderefs"
150);
151
152if (CAN_REALLY_FORK) {
153 $one->reset;
154 my $pid = fork;
155 die "Failed to fork!" unless defined $pid;
156 unless($pid) { exit 0 }
157
158 is($one->_ipc_wait, 0, "No errors");
159
160 $pid = fork;
161 die "Failed to fork!" unless defined $pid;
162 unless($pid) { exit 255 }
163 my @warnings;
164 {
165 local $SIG{__WARN__} = sub { push @warnings => @_ };
166 is($one->_ipc_wait, 255, "Process exited badly");
167 }
168 like($warnings[0], qr/Process .* did not exit cleanly \(status: 255\)/, "Warn about exit");
169}
170
171if (CAN_THREAD && $] ge '5.010') {
172 require threads;
173 $one->reset;
174
175 threads->new(sub { 1 });
176 is($one->_ipc_wait, 0, "No errors");
177
178 if (threads->can('error')) {
179 threads->new(sub {
180 close(STDERR);
181 close(STDOUT);
182 die "xxx"
183 });
184 my @warnings;
185 {
186 local $SIG{__WARN__} = sub { push @warnings => @_ };
187 is($one->_ipc_wait, 255, "Thread exited badly");
188 }
189 like($warnings[0], qr/Thread .* did not end cleanly: xxx/, "Warn about exit");
190 }
191}
192
193{
194 $one->reset();
195 local $? = 0;
196 $one->set_exit;
197 is($?, 0, "no errors on exit");
198}
199
200{
201 $one->reset();
58818a66 202 $one->set__tid(1);
b4514920
CG
203 local $? = 0;
204 $one->set_exit;
205 is($?, 0, "no errors on exit");
206}
207
208{
209 $one->reset();
210 $one->stack->top;
211 $one->no_wait(1);
212 local $? = 0;
213 $one->set_exit;
214 is($?, 0, "no errors on exit");
215}
216
217{
218 $one->reset();
219 $one->stack->top->set_no_ending(1);
220 local $? = 0;
221 $one->set_exit;
222 is($?, 0, "no errors on exit");
223}
224
225{
226 $one->reset();
58818a66 227 $one->load();
b4514920
CG
228 $one->stack->top->set_failed(2);
229 local $? = 0;
230 $one->set_exit;
231 is($?, 2, "number of failures");
232}
233
234{
235 $one->reset();
58818a66 236 $one->load();
b4514920
CG
237 local $? = 500;
238 $one->set_exit;
239 is($?, 255, "set exit code to a sane number");
240}
241
242{
243 local %INC = %INC;
244 delete $INC{'Test2/IPC.pm'};
245 $one->reset();
58818a66 246 $one->load();
b4514920
CG
247 my @events;
248 $one->stack->top->filter(sub { push @events => $_[1]; undef});
249 $one->stack->new_hub;
250 local $? = 0;
251 $one->set_exit;
252 is($?, 255, "errors on exit");
253 like($events[0]->message, qr/Test ended with extra hubs on the stack!/, "got diag");
254}
255
256{
257 $one->reset;
258 my $stderr = "";
259 {
260 local $INC{'Test/Builder.pm'} = __FILE__;
261 local $Test2::API::VERSION = '0.002';
262 local $Test::Builder::VERSION = '0.001';
263 local *STDERR;
264 open(STDERR, '>', \$stderr) or print "Failed to open new STDERR";
265
266 $one->set_exit;
267 }
268
269 is($stderr, <<' EOT', "Got warning about version mismatch");
270
271********************************************************************************
272* *
273* Test::Builder -- Test2::API version mismatch detected *
274* *
275********************************************************************************
276 Test2::API Version: 0.002
277Test::Builder Version: 0.001
278
279This is not a supported configuration, you will have problems.
280
281 EOT
282}
283
284{
285 require Test2::API::Breakage;
286 no warnings qw/redefine once/;
287 my $ran = 0;
288 local *Test2::API::Breakage::report = sub { $ran++; return "foo" };
289 use warnings qw/redefine once/;
290 $one->reset();
58818a66 291 $one->load();
b4514920
CG
292
293 my $stderr = "";
294 {
295 local *STDERR;
296 open(STDERR, '>', \$stderr) or print "Failed to open new STDERR";
297 local $? = 255;
298 $one->set_exit;
299 }
300
301 is($stderr, <<" EOT", "Reported bad modules");
302
303You have loaded versions of test modules known to have problems with Test2.
304This could explain some test failures.
305foo
306
307 EOT
308}
309
310
311{
312 $one->reset();
58818a66 313 $one->load();
b4514920
CG
314 my @events;
315 $one->stack->top->filter(sub { push @events => $_[1]; undef});
316 $one->stack->new_hub;
317 ok($one->stack->top->ipc, "Have IPC");
318 $one->stack->new_hub;
319 ok($one->stack->top->ipc, "Have IPC");
320 $one->stack->top->set_ipc(undef);
321 ok(!$one->stack->top->ipc, "no IPC");
322 $one->stack->new_hub;
323 local $? = 0;
324 $one->set_exit;
325 is($?, 255, "errors on exit");
326 like($events[0]->message, qr/Test ended with extra hubs on the stack!/, "got diag");
327}
328
329if (CAN_REALLY_FORK) {
330 local $SIG{__WARN__} = sub { };
331 $one->reset();
332 my $pid = fork;
333 die "Failed to fork!" unless defined $pid;
334 unless ($pid) { exit 255 }
335 $one->_finalize;
336 $one->stack->top;
337
338 local $? = 0;
339 $one->set_exit;
340 is($?, 255, "errors on exit");
341
342 $one->reset();
343 $pid = fork;
344 die "Failed to fork!" unless defined $pid;
345 unless ($pid) { exit 255 }
346 $one->_finalize;
347 $one->stack->top;
348
349 local $? = 122;
350 $one->set_exit;
351 is($?, 122, "kept original exit");
352}
353
354{
355 my $ctx = bless {
356 trace => Test2::Util::Trace->new(frame => ['Foo::Bar', 'Foo/Bar.pm', 42, 'xxx']),
357 hub => Test2::Hub->new(),
358 }, 'Test2::API::Context';
359 $one->contexts->{1234} = $ctx;
360
361 local $? = 500;
362 my $warnings = warnings { $one->set_exit };
363 is($?, 255, "set exit code to a sane number");
364
365 is_deeply(
366 $warnings,
367 [
368 "context object was never released! This means a testing tool is behaving very badly at Foo/Bar.pm line 42.\n"
369 ],
370 "Warned about unfreed context"
371 );
372}
373
374{
375 local %INC = %INC;
376 delete $INC{'Test2/IPC.pm'};
377 delete $INC{'threads.pm'};
378 ok(!USE_THREADS, "Sanity Check");
379
380 $one->reset;
381 ok(!$one->ipc, 'IPC not loaded, no IPC object');
382 ok($one->finalized, "calling ipc finalized the object");
383 is($one->ipc_polling, undef, "no polling defined");
384 ok(!@{$one->ipc_drivers}, "no driver");
385
386 if (CAN_THREAD) {
387 local $INC{'threads.pm'} = 1;
388 no warnings 'once';
389 local *threads::tid = sub { 0 } unless threads->can('tid');
390 $one->reset;
391 ok($one->ipc, 'IPC loaded if threads are');
392 ok($one->finalized, "calling ipc finalized the object");
393 ok($one->ipc_polling, "polling on by default");
394 is($one->ipc_drivers->[0], 'Test2::IPC::Driver::Files', "default driver");
395 }
396
397 {
398 local $INC{'Test2/IPC.pm'} = 1;
399 $one->reset;
400 ok($one->ipc, 'IPC loaded if Test2::IPC is');
401 ok($one->finalized, "calling ipc finalized the object");
402 ok($one->ipc_polling, "polling on by default");
403 is($one->ipc_drivers->[0], 'Test2::IPC::Driver::Files', "default driver");
404 }
405
406 require Test2::IPC::Driver::Files;
407 $one->reset;
408 $one->add_ipc_driver('Test2::IPC::Driver::Files');
409 ok($one->ipc, 'IPC loaded if drivers have been added');
410 ok($one->finalized, "calling ipc finalized the object");
411 ok($one->ipc_polling, "polling on by default");
412
413 my $file = __FILE__;
414 my $line = __LINE__ + 1;
415 my $warnings = warnings { $one->add_ipc_driver('Test2::IPC::Driver::Files') };
416 like(
417 $warnings->[0],
418 qr{^IPC driver Test2::IPC::Driver::Files loaded too late to be used as the global ipc driver at \Q$file\E line $line},
419 "Got warning at correct frame"
420 );
421
422 $one->reset;
423 $one->add_ipc_driver('Fake::Fake::XXX');
424 is(
425 exception { $one->ipc },
426 "IPC has been requested, but no viable drivers were found. Aborting...\n",
427 "Failed without viable IPC driver"
428 );
429}
430
431{
432 $one->reset;
433 ok(!@{$one->context_init_callbacks}, "no callbacks");
434 is($one->ipc_polling, undef, "no polling, undef");
435
436 $one->disable_ipc_polling;
437 ok(!@{$one->context_init_callbacks}, "no callbacks");
438 is($one->ipc_polling, undef, "no polling, still undef");
439
440 my $cull = 0;
441 no warnings 'once';
442 local *Fake::Hub::cull = sub { $cull++ };
443 use warnings;
444
445 $one->enable_ipc_polling;
446 is(@{$one->context_init_callbacks}, 1, "added the callback");
447 is($one->ipc_polling, 1, "polling on");
448 $one->set_ipc_shm_last('abc1');
449 $one->context_init_callbacks->[0]->({'hub' => 'Fake::Hub'});
450 is($cull, 1, "called cull once");
451 $cull = 0;
452
453 $one->disable_ipc_polling;
454 is(@{$one->context_init_callbacks}, 1, "kept the callback");
455 is($one->ipc_polling, 0, "no polling, set to 0");
456 $one->set_ipc_shm_last('abc3');
457 $one->context_init_callbacks->[0]->({'hub' => 'Fake::Hub'});
458 is($cull, 0, "did not call cull");
459 $cull = 0;
460
461 $one->enable_ipc_polling;
462 is(@{$one->context_init_callbacks}, 1, "did not add the callback");
463 is($one->ipc_polling, 1, "polling on");
464 $one->set_ipc_shm_last('abc3');
465 $one->context_init_callbacks->[0]->({'hub' => 'Fake::Hub'});
466 is($cull, 1, "called cull once");
467}
468
469done_testing;