0f775f4029f9b38a229ae0ffa940068874d97aaf
[dbsrgits/DBIx-Class.git] / t / 35exception_inaction.t
1 BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }
2
3 use strict;
4 use warnings;
5
6
7 use DBICTest::RunMode;
8 BEGIN {
9   if( DBICTest::RunMode->is_plain ) {
10     print "1..0 # SKIP not running dangerous segfault-prone test on plain install\n";
11     exit 0;
12   }
13 }
14
15 use DBICTest::Util 'tmpdir';
16 use File::Temp ();
17 use DBIx::Class::_Util 'scope_guard';
18 use DBIx::Class::Schema;
19
20 # Do not use T::B - the test is hard enough not to segfault as it is
21 my $test_count = 0;
22
23 # start with one failure, and decrement it at the end
24 my $failed = 1;
25
26 sub ok {
27   printf STDOUT ("%s %u - %s\n",
28     ( $_[0] ? 'ok' : 'not ok' ),
29     ++$test_count,
30     $_[1] || '',
31   );
32
33   unless( $_[0] ) {
34     $failed++;
35     printf STDERR ("# Failed test #%d at %s line %d\n",
36       $test_count,
37       (caller(0))[1,2]
38     );
39   }
40
41   return !!$_[0];
42 }
43
44 # yes, make it even dirtier
45 my $schema = 'DBIx::Class::Schema';
46
47 $schema->connection('dbi:SQLite::memory:');
48
49 # this is incredibly horrible...
50 # demonstrate utter breakage of the reconnection/retry logic
51 #
52 open(my $stderr_copy, '>&', *STDERR) or die "Unable to dup STDERR: $!";
53 my $tf = File::Temp->new( UNLINK => 1, DIR => tmpdir() );
54
55 my $output;
56
57 ESCAPE:
58 {
59   my $guard = scope_guard {
60     close STDERR;
61     open(STDERR, '>&', $stderr_copy);
62     $output = do { local (@ARGV, $/) = $tf; <> };
63     close $tf;
64     unlink $tf;
65     undef $tf;
66     close $stderr_copy;
67   };
68
69   close STDERR;
70   open(STDERR, '>&', $tf) or die "Unable to reopen STDERR: $!";
71
72   $schema->storage->ensure_connected;
73   $schema->storage->_dbh->disconnect;
74
75   # silences "exitting sub via last"
76   local $SIG{__WARN__} = sub {};
77
78   $schema->exception_action(sub {
79     ok(1, 'exception_action invoked');
80     # essentially what Dancer2's redirect() does after https://github.com/PerlDancer/Dancer2/pull/485
81     # which "nicely" combines with: https://metacpan.org/source/MARKOV/Log-Report-1.12/lib/Dancer2/Plugin/LogReport.pm#L143
82     # as encouraged by: https://metacpan.org/pod/release/MARKOV/Log-Report-1.12/lib/Dancer2/Plugin/LogReport.pod#Logging-DBIC-database-queries-and-errors
83     last ESCAPE;
84   });
85
86   # this *DOES* throw, but the exception will *NEVER SHOW UP*
87   $schema->storage->dbh_do(sub { $_[1]->selectall_arrayref("SELECT * FROM wfwqfdqefqef") } );
88
89   # NEITHER will this
90   ok(0, "Nope");
91 }
92
93 ok(1, "Post-escape reached");
94
95 ok(
96   !!( $output =~ /DBIx::Class INTERNAL PANIC.+FIX YOUR ERROR HANDLING/s ),
97   'Proper warning emitted on STDERR'
98 ) or print STDERR "Instead found:\n\n$output\n";
99
100 print "1..$test_count\n";
101
102 # this is our "done_testing"
103 $failed--;
104
105 # avoid tasty segfaults on 5.8.x
106 exit( $failed );