forked from crystal-lang/crystal-db
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtransaction_spec.cr
233 lines (199 loc) · 5.41 KB
/
transaction_spec.cr
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
require "./spec_helper"
private class FooException < Exception
end
describe DB::Transaction do
it "begin/commit transaction from connection" do
with_dummy_connection do |cnn|
tx = cnn.begin_transaction
tx.commit
end
end
it "begin/rollback transaction from connection" do
with_dummy_connection do |cnn|
tx = cnn.begin_transaction
tx.rollback
end
end
it "raise if begin over existing transaction" do
with_dummy_connection do |cnn|
cnn.begin_transaction
expect_raises(DB::Error, "There is an existing transaction in this connection") do
cnn.begin_transaction
end
end
end
it "allow sequential transactions" do
with_dummy_connection do |cnn|
tx = cnn.begin_transaction
tx.rollback
tx = cnn.begin_transaction
tx.commit
end
end
it "transaction with block from connection should be committed" do
t = uninitialized DummyDriver::DummyTransaction
with_witness do |w|
with_dummy_connection do |cnn|
cnn.transaction do |tx|
if tx.is_a?(DummyDriver::DummyTransaction)
t = tx
w.check
end
end
end
end
t.committed.should be_true
t.rolledback.should be_false
end
it "transaction with block from connection should be rolledback if raise DB::Rollback" do
t = uninitialized DummyDriver::DummyTransaction
with_witness do |w|
with_dummy_connection do |cnn|
cnn.transaction do |tx|
if tx.is_a?(DummyDriver::DummyTransaction)
t = tx
w.check
end
raise DB::Rollback.new
end
end
end
t.rolledback.should be_true
t.committed.should be_false
end
it "transaction with block from connection should be rolledback if raise" do
t = uninitialized DummyDriver::DummyTransaction
with_witness do |w|
with_dummy_connection do |cnn|
expect_raises(FooException) do
cnn.transaction do |tx|
if tx.is_a?(DummyDriver::DummyTransaction)
t = tx
w.check
end
raise FooException.new
end
end
end
end
t.rolledback.should be_true
t.committed.should be_false
end
it "transaction with block from connection should be committed if `return` is called" do
t = uninitialized DummyDriver::DummyTransaction
with_witness do |w|
with_dummy_connection do |cnn|
t = return_from_txn(cnn).as(DummyDriver::DummyTransaction)
w.check
end
end
t.rolledback.should be_false
t.committed.should be_true
end
it "transaction can be committed within block" do
with_dummy_connection do |cnn|
cnn.transaction do |tx|
tx.commit
end
end
end
it "transaction can be rolledback within block" do
with_dummy_connection do |cnn|
cnn.transaction do |tx|
tx.rollback
end
end
end
it "transaction can be rolledback within block and later raise" do
with_dummy_connection do |cnn|
expect_raises(FooException) do
cnn.transaction do |tx|
tx.rollback
raise FooException.new
end
end
end
end
it "transaction can be rolledback within block and later raise DB::Rollback without forwarding it" do
with_dummy_connection do |cnn|
cnn.transaction do |tx|
tx.rollback
raise DB::Rollback.new
end
end
end
it "transaction can't be committed twice" do
with_dummy_connection do |cnn|
cnn.transaction do |tx|
tx.commit
expect_raises(DB::Error, "Transaction already closed") do
tx.commit
end
end
end
end
it "transaction can't be rolledback twice" do
with_dummy_connection do |cnn|
cnn.transaction do |tx|
tx.rollback
expect_raises(DB::Error, "Transaction already closed") do
tx.rollback
end
end
end
end
it "return connection to pool after transaction block in db" do
DummyDriver::DummyConnection.clear_connections
with_dummy do |db|
db.transaction do |tx|
db.pool.is_available?(DummyDriver::DummyConnection.connections.first).should be_false
end
db.pool.is_available?(DummyDriver::DummyConnection.connections.first).should be_true
end
end
it "releasing result_set from within transaction should not return connection to pool" do
cnn = uninitialized DB::Connection
with_dummy do |db|
db.transaction do |tx|
cnn = tx.connection
cnn.scalar "1"
db.pool.is_available?(cnn).should be_false
end
db.pool.is_available?(cnn).should be_true
end
end
it "returns block value when sucess" do
with_dummy_connection do |cnn|
res = cnn.transaction do |tx|
42
end
res.should eq(42)
typeof(res).should eq(Int32 | Nil)
end
end
it "returns value on rollback via method" do
with_dummy_connection do |cnn|
res = cnn.transaction do |tx|
tx.rollback
42
end
res.should eq(42)
typeof(res).should eq(Int32 | Nil)
end
end
it "returns nil on rollback via exception" do
with_dummy_connection do |cnn|
res = cnn.transaction do |tx|
raise DB::Rollback.new
42
end
res.should be_nil
typeof(res).should eq(Int32 | Nil)
end
end
end
private def return_from_txn(cnn)
cnn.transaction do |tx|
return tx
end
end