File: run.t

package info (click to toggle)
libdbix-connector-perl 0.60-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 284 kB
  • sloc: perl: 582; makefile: 2
file content (144 lines) | stat: -rw-r--r-- 4,667 bytes parent folder | download
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use strict; use warnings;

use Test::More tests => 58;
use lib 't/lib';
use Hook::Guard;
use DBIx::Connector;

my $CLASS = 'DBIx::Connector';

ok my $conn = $CLASS->new( 'dbi:ExampleP:dummy', '', '' ),
    'Get a connection';

# Test with no existing dbh.
my $connect_meth = Hook::Guard->new( \*DBIx::Connector::_connect )->prepend(sub {
    pass '_connect should be called';
});

ok $conn->run(sub {
    ok shift->{AutoCommit}, 'Inside, we should not be in a transaction';
    ok !$conn->in_txn, 'in_txn() should know it, too';
    ok $conn->{_in_run}, '_in_run should be true';
}), 'Do something with no existing handle';

# Test with instantiated dbh.
$connect_meth->restore;
ok my $dbh = $conn->dbh, 'Fetch the dbh';

# Set up a DBI mocker.
my $ping = 0;
my $dbh_ping_meth = Hook::Guard->new( \*DBI::db::ping )->replace( sub { ++$ping } );

is $conn->{_dbh}, $dbh, 'The dbh should be the stored';
is $ping, 0, 'No pings yet';
ok $conn->connected, 'We should be connected';
is $ping, 1, 'Ping should have been called';
ok $conn->run(sub {
    is $ping, 1, 'Ping should not have been called before the run';
    is shift, $dbh, 'The database handle should have been passed';
    is $_, $dbh, 'Should have dbh in $_';
    is $conn->dbh, $dbh, 'Should get same dbh from dbh()';
    is $ping, 1, 'ping should not have been called again';
    $dbh->{Active} = 0;
    isnt $conn->dbh, $dbh, 'Should get different dbh if after disconnect';
}), 'Do something with handle';

# Test the return value.
$dbh = $conn->dbh;
ok my $foo = $conn->run(sub {
    return (2, 3, 5);
}), 'Do in scalar context';
is $foo, 5, 'The return value should be the last value';

ok $foo = $conn->run(sub {
    return wantarray ?  (2, 3, 5) : 'scalar';
}), 'Do in scalar context';
is $foo, 'scalar', 'Callback should know when its context is scalar';

ok my @foo = $conn->run(sub {
    return (2, 3, 5);
}), 'Do in array context';
is_deeply \@foo, [2, 3, 5], 'The return value should be the list';

ok @foo = $conn->run(sub {
    return wantarray ?  (2, 3, 5) : 'scalar';
}), 'Do in array context';
is_deeply \@foo, [2, 3, 5], 'Callback should know when its context is list';

# Test an exception.
eval {  $conn->run(sub { die 'WTF?' }) };
like $@, qr/WTF/, 'We should have died';

# Make sure nesting works okay.
ok !$conn->{_in_run}, '_in_run should be false';
$conn->run(sub {
    my $dbh = shift;
    ok $conn->{_in_run}, '_in_run should be set inside run()';
    local $dbh->{Active} = 0;
    $conn->run(sub {
        my $dbha = shift;
        isnt $dbha, $dbh, 'Nested should get the same when inactive';
        is $_, $dbha, 'Should have dbh in $_';
        is $conn->dbh, $dbha, 'Should get same dbh from dbh()';
        ok $conn->{_in_run}, '_in_run should be set inside nested run()';
    });
});
ok !$conn->{_in_run}, '_in_run should be false again';

# Make sure a nested txn call works, too.
ok ++$conn->{_depth}, 'Increase the transacation depth';
ok !($conn->{_dbh}{Active} = 0), 'Disconnect the handle';
$conn->run(sub {
    is shift, $conn->{_dbh},
        'The txn nested call to run() should get the deactivated handle';
    is $_, $conn->{_dbh}, 'Its should also be in $_';
});

# Make sure nesting works when ping returns false.
$conn->run(sub {
    my $dbh = shift;
    ok $conn->{_in_run}, '_in_run should be set inside run()';
    $dbh_ping_meth->replace( sub { 0 } );
    $conn->run(sub {
        is shift, $dbh, 'Nested get the same dbh even if ping is false';
        is $_, $dbh, 'Should have dbh in $_';
        is $conn->dbh, $dbh, 'Should get same dbh from dbh()';
        ok $conn->{_in_run}, '_in_run should be set inside nested run()';
    });
});

# Test mode.
$conn->run(sub {
    is $conn->mode, 'no_ping', 'Default mode should be no_ping';
});

$conn->run(ping => sub {
    is $conn->mode, 'ping', 'Mode should be "ping" inside ping run'
});
is $conn->mode, 'no_ping', 'Back outside, should be "no_ping" again';

$conn->run(fixup => sub {
    is $conn->mode, 'fixup', 'Mode should be "fixup" inside fixup run'
});
is $conn->mode, 'no_ping', 'Back outside, should be "no_ping" again';

ok $conn->mode('ping'), 'Set mode to "ping"';
$conn->run(sub {
    is $conn->mode, 'ping', 'Mode should implicitly be "ping"'
});

ok $conn->mode('fixup'), 'Set mode to "fixup"';
$conn->run(sub {
    is $conn->mode, 'fixup', 'Mode should implicitly be "fixup"'
});

NOEXIT: {
    no warnings;

    # Make sure we don't exit the app via `next` or `last`.
    for my $mode (qw(ping no_ping fixup)) {
        $conn->mode($mode);
        ok !$conn->run(sub { next }), "Return via next should fail";
        ok !$conn->run(sub { last }), "Return via last should fail";
    }
}