File: 35exception_inaction.t

package info (click to toggle)
libdbix-class-perl 0.082844-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,320 kB
  • sloc: perl: 27,215; sql: 322; sh: 29; makefile: 16
file content (102 lines) | stat: -rw-r--r-- 2,481 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use strict;
use warnings;

use lib 't/lib';
use DBICTest::RunMode;
BEGIN {
  if( DBICTest::RunMode->is_plain ) {
    print "1..0 # SKIP not running dangerous segfault-prone test on plain install\n";
    exit 0;
  }
}

use File::Temp ();
use DBIx::Class::_Util 'scope_guard';
use DBIx::Class::Schema;

# Do not use T::B - the test is hard enough not to segfault as it is
my $test_count = 0;

# start with one failure, and decrement it at the end
my $failed = 1;

sub ok {
  printf STDOUT ("%s %u - %s\n",
    ( $_[0] ? 'ok' : 'not ok' ),
    ++$test_count,
    $_[1] || '',
  );

  unless( $_[0] ) {
    $failed++;
    printf STDERR ("# Failed test #%d at %s line %d\n",
      $test_count,
      (caller(0))[1,2]
    );
  }

  return !!$_[0];
}

# yes, make it even dirtier
my $schema = 'DBIx::Class::Schema';

$schema->connection('dbi:SQLite::memory:');

# this is incredibly horrible...
# demonstrate utter breakage of the reconnection/retry logic
#
open(my $stderr_copy, '>&', *STDERR) or die "Unable to dup STDERR: $!";
my $tf = File::Temp->new( UNLINK => 1 );

my $output;

ESCAPE:
{
  my $guard = scope_guard {
    close STDERR;
    open(STDERR, '>&', $stderr_copy);
    $output = do { local (@ARGV, $/) = $tf; <> };
    close $tf;
    unlink $tf;
    undef $tf;
    close $stderr_copy;
  };

  close STDERR;
  open(STDERR, '>&', $tf) or die "Unable to reopen STDERR: $!";

  $schema->storage->ensure_connected;
  $schema->storage->_dbh->disconnect;

  local $SIG{__WARN__} = sub {};

  $schema->exception_action(sub {
    ok(1, 'exception_action invoked');
    # essentially what Dancer2's redirect() does after https://github.com/PerlDancer/Dancer2/pull/485
    # which "nicely" combines with: https://metacpan.org/source/MARKOV/Log-Report-1.12/lib/Dancer2/Plugin/LogReport.pm#L143
    # as encouraged by: https://metacpan.org/pod/release/MARKOV/Log-Report-1.12/lib/Dancer2/Plugin/LogReport.pod#Logging-DBIC-database-queries-and-errors
    last ESCAPE;
  });

  # this *DOES* throw, but the exception will *NEVER SHOW UP*
  $schema->storage->dbh_do(sub { $_[1]->selectall_arrayref("SELECT * FROM wfwqfdqefqef") } );

  # NEITHER will this
  ok(0, "Nope");
}

ok(1, "Post-escape reached");

ok(
  !!( $output =~ /DBIx::Class INTERNAL PANIC.+FIX YOUR ERROR HANDLING/s ),
  'Proper warning emitted on STDERR'
) or print STDERR "Instead found:\n\n$output\n";

print "1..$test_count\n";

# this is our "done_testing"
$failed--;

# avoid tasty segfaults on 5.8.x
exit( $failed );