1use strict;
2use warnings;
3use Test::More;
4use lib qw(t/lib);
5use MyApp::Schema;
6use Test::Fatal;
7
8sub gen_schema {
9    my $schema = MyApp::Schema->connect("dbi:SQLite::memory:", "", "", {
10        sqlite_use_immediate_transaction => 1,
11    });
12}
13
14subtest 'add_txn_end_hook should call in transaction' => sub {
15    my $schema = gen_schema();
16
17    like(
18        exception {
19            $schema->storage->add_txn_end_hook(sub {});
20        },
21        qr/only can call add_txn_end_hook in transaction/,
22        "die if called add_txn_end_hook method without transaction",
23    );
24};
25
26subtest 'DBIx::Schema->txn_do style' => sub {
27    my $schema = gen_schema();
28    my $call_count = 0;
29
30    $schema->txn_do(sub{
31            $schema->storage->add_txn_end_hook(sub {
32                    $call_count++;
33                });
34            is $call_count, 0, "not yet call";
35            is @{ $schema->storage->_hooks }, 1, "hooks count is 1";
36        });
37
38    is $call_count, 1, "add_txn_end_hook is called";
39    is @{ $schema->storage->_hooks }, 0, "all hooks is executed";
40};
41
42subtest 'DBIx::Schema->txn_begin and txn_commit style' => sub {
43    my $schema = gen_schema();
44    my $call_count = 0;
45
46    $schema->txn_begin;
47    $schema->storage->add_txn_end_hook(sub {
48        $call_count++;
49    });
50    is $call_count, 0, "not yet call";
51    is @{ $schema->storage->_hooks }, 1, "hooks count is 1";
52
53    $schema->txn_commit;
54
55    is $call_count, 1, "called";
56    is @{ $schema->storage->_hooks }, 0, "all hooks is executed";
57};
58
59subtest 'DBIx::Schema->storage->txn_begin and txn_commit style' => sub {
60    my $schema = gen_schema();
61    my $call_count = 0;
62
63    $schema->storage->txn_begin;
64    $schema->storage->add_txn_end_hook(sub {
65        $call_count++;
66    });
67    $schema->storage->add_txn_end_hook(sub {
68        $call_count++;
69    });
70    is $call_count, 0;
71    is @{ $schema->storage->_hooks }, 2;
72    $schema->storage->txn_commit;
73
74    is $call_count, 2;
75    is @{ $schema->storage->_hooks }, 0;
76};
77
78subtest 'DBIx::Schema->txn_scope_guard style' => sub {
79    my $schema = gen_schema();
80    my $call_count = 0;
81
82    my $guard = $schema->txn_scope_guard;
83    $schema->storage->add_txn_end_hook(sub {
84        $call_count++;
85    });
86    $schema->storage->add_txn_end_hook(sub {
87        $call_count++;
88    });
89    is $call_count, 0;
90    is @{ $schema->storage->_hooks }, 2;
91
92    $guard->commit;
93
94    is $call_count, 2;
95    is @{ $schema->storage->_hooks }, 0;
96};
97
98subtest 'die in end hook subroutine' => sub {
99    my $schema = gen_schema();
100    my $call_count = 0;
101
102    my $guard = $schema->txn_scope_guard;
103    $schema->storage->add_txn_end_hook(sub {
104        $call_count++;
105    });
106    $schema->storage->add_txn_end_hook(sub {
107        die "die!die!die!";
108        $call_count++;
109    });
110    $schema->storage->add_txn_end_hook(sub {
111        $call_count++;
112    });
113    is $call_count, 0;
114    is @{ $schema->storage->_hooks }, 3;
115
116    is(
117        exception {
118            $guard->commit;
119        },
120        undef,
121        "not died in commit",
122    );
123
124    is $call_count, 1;
125    is @{ $schema->storage->_hooks }, 0, "all hooks is executed";
126
127    is $guard->{inactivated}, 1, "guard should be inactivated";
128};
129
130subtest 'nest transaction' => sub {
131    my $schema = gen_schema();
132    my $call_count = 0;
133
134    my $guard1 = $schema->txn_scope_guard;
135    my $guard2 = $schema->txn_scope_guard;
136
137    $schema->storage->add_txn_end_hook(sub {
138        $call_count++;
139    });
140    $schema->storage->add_txn_end_hook(sub {
141        $call_count++;
142    });
143
144    $guard2->commit;
145
146    is $call_count, 0;
147    is @{ $schema->storage->_hooks }, 2, "not yet called";
148
149    $guard1->commit;
150
151    is $call_count, 2;
152    is @{ $schema->storage->_hooks }, 0;
153};
154
155subtest 'schema->add_txn_end_hook' => sub {
156    my $schema = gen_schema();
157    my $call_count = 0;
158
159    $schema->txn_begin;
160    $schema->add_txn_end_hook(sub {
161        $call_count++;
162    });
163    $schema->add_txn_end_hook(sub {
164        $call_count++;
165    });
166    is $call_count, 0;
167    is @{ $schema->storage->_hooks }, 2;
168    $schema->txn_commit;
169
170    is $call_count, 2;
171    is @{ $schema->storage->_hooks }, 0;
172};
173
174subtest 'clear hook on rollback' => sub {
175    my $schema = gen_schema();
176    my $call_count = 0;
177
178    {
179        my $guard = $schema->txn_scope_guard;
180        $schema->storage->add_txn_end_hook(sub {
181            $call_count++;
182        });
183        is @{ $schema->storage->_hooks }, 1, "not yet called";
184        # end of scope
185    }
186
187    is $call_count, 0;
188    is @{ $schema->storage->_hooks }, 0, "cleard hooks";
189};
190
191done_testing;
192