Completed
Push — master ( b97768...587712 )
by Bartko
31:36
created

testHandleBrokenNestedTransaction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.584
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace StefanoTreeTest\Integration\Adapter;
6
7
use StefanoTree\NestedSet\Adapter\AdapterInterface;
8
use StefanoTree\NestedSet\Adapter\NestedTransactionDecorator;
9
use StefanoTree\NestedSet\Adapter\Pdo;
10
use StefanoTree\NestedSet\Options;
11
use StefanoTreeTest\TestUtil;
12
use StefanoTreeTest\UnitTestCase;
13
use Zend_Db_Adapter_Abstract as ZendDbAdapter;
14
15
class NestedTransactionDecoratorTest extends UnitTestCase
16
{
17
    /**
18
     * @var AdapterInterface
19
     */
20
    protected $adapterNestedDoNotSupport;
21
22
    /**
23
     * @var ZendDbAdapter
24
     */
25
    protected $dbAdapter;
26
27
    protected function setUp()
28
    {
29
        $this->dbAdapter = TestUtil::getPDOConnection();
0 ignored issues
show
Documentation Bug introduced by
It seems like \StefanoTreeTest\TestUtil::getPDOConnection() of type object<PDO> is incompatible with the declared type object<Zend_Db_Adapter_Abstract> of property $dbAdapter.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
30
31
        $options = new Options(array(
32
                                   'tableName' => 'tree_traversal',
33
                                   'idColumnName' => 'tree_traversal_id',
34
                               ));
35
36
        $this->adapterNestedDoNotSupport = new Pdo($options, $this->dbAdapter);
37
38
        parent::setUp();
39
    }
40
41
    protected function tearDown()
42
    {
43
        $this->adapterNestedDoNotSupport = null;
44
        parent::tearDown();
45
    }
46
47
    public function testCanHandleNestedTransaction()
48
    {
49
        $adapterStub = \Mockery::mock(AdapterInterface::class);
50
51
        $adapter = new NestedTransactionDecorator($adapterStub);
52
        $this->assertTrue($adapter->canHandleNestedTransaction());
53
    }
54
55
    public function testWrappedAdapterCanHandleHandleNestedTransaction()
56
    {
57
        $adapterMock = \Mockery::mock(AdapterInterface::class);
58
        $adapterMock->shouldReceive('canHandleNestedTransaction')
59
                    ->andReturnTrue();
60
61
        $adapterMock->shouldReceive('beginTransaction')
62
                    ->times(3);
63
64
        $adapterMock->shouldReceive('commitTransaction')
65
                    ->times(2);
66
67
        $adapterMock->shouldReceive('rollbackTransaction')
68
                    ->times(1);
69
70
        $adapterMock->shouldReceive('isInTransaction')
71
                    ->andReturnFalse();
72
73
        $adapter = new NestedTransactionDecorator($adapterMock);
74
        $adapter->beginTransaction();
75
        $adapter->beginTransaction();
76
        $adapter->beginTransaction();
77
        $adapter->commitTransaction();
78
        $adapter->commitTransaction();
79
        $adapter->rollbackTransaction();
80
    }
81
82
    public function testHandleTransaction()
83
    {
84
        $adapterMock = \Mockery::mock(AdapterInterface::class);
85
        $adapterMock->shouldReceive('canHandleNestedTransaction')
86
                    ->andReturnFalse();
87
88
        $adapterMock->shouldReceive('beginTransaction')
89
                    ->times(1);
90
91
        $adapterMock->shouldReceive('commitTransaction')
92
                    ->times(1);
93
94
        $adapterMock->shouldReceive('isInTransaction')
95
                    ->andReturnFalse();
96
97
        $adapter = new NestedTransactionDecorator($adapterMock);
98
        $adapter->beginTransaction();
99
        $adapter->commitTransaction();
100
    }
101
102
    public function testHandleBrokenTransaction()
103
    {
104
        $adapterMock = \Mockery::mock(AdapterInterface::class);
105
        $adapterMock->shouldReceive('canHandleNestedTransaction')
106
                    ->andReturnFalse();
107
108
        $adapterMock->shouldReceive('beginTransaction')
109
                    ->times(1);
110
111
        $adapterMock->shouldReceive('rollbackTransaction')
112
                    ->times(1);
113
114
        $adapterMock->shouldReceive('isInTransaction')
115
                    ->andReturnFalse();
116
117
        $adapter = new NestedTransactionDecorator($adapterMock);
118
        $adapter->beginTransaction();
119
        $adapter->rollbackTransaction();
120
    }
121
122
    public function testRollbackOnlyMarkIsSetToFalseAfterRollbackSuccess()
123
    {
124
        $adapterMock = \Mockery::mock(AdapterInterface::class);
125
        $adapterMock->shouldReceive('canHandleNestedTransaction')
126
                    ->andReturnFalse();
127
128
        $adapterMock->shouldReceive('beginTransaction')
129
                    ->times(3);
130
131
        $adapterMock->shouldReceive('commitTransaction')
132
                    ->times(2);
133
134
        $adapterMock->shouldReceive('rollbackTransaction')
135
                    ->times(1);
136
137
        $adapterMock->shouldReceive('isInTransaction')
138
                    ->andReturnFalse();
139
140
        $adapter = new NestedTransactionDecorator($adapterMock);
141
        $adapter->beginTransaction();
142
        $adapter->beginTransaction();
143
        $adapter->rollbackTransaction();
144
        $adapter->rollbackTransaction();
145
146
        $adapter->beginTransaction();
147
        $adapter->commitTransaction();
148
149
        $adapter->beginTransaction();
150
        $adapter->beginTransaction();
151
        $adapter->commitTransaction();
152
        $adapter->commitTransaction();
153
    }
154
155
    public function testHandleNestedTransaction()
156
    {
157
        $adapterMock = \Mockery::mock(AdapterInterface::class);
158
        $adapterMock->shouldReceive('canHandleNestedTransaction')
159
                    ->andReturnFalse();
160
161
        $adapterMock->shouldReceive('beginTransaction')
162
                    ->times(1);
163
164
        $adapterMock->shouldReceive('commitTransaction')
165
                    ->times(1);
166
167
        $adapterMock->shouldReceive('isInTransaction')
168
                    ->andReturnFalse();
169
170
        $adapter = new NestedTransactionDecorator($adapterMock);
171
        $adapter->beginTransaction();
172
        $adapter->beginTransaction();
173
        $adapter->commitTransaction();
174
        $adapter->commitTransaction();
175
    }
176
177
    public function testHandleBrokenNestedTransaction()
178
    {
179
        $adapterMock = \Mockery::mock(AdapterInterface::class);
180
        $adapterMock->shouldReceive('canHandleNestedTransaction')
181
                    ->andReturnFalse();
182
183
        $adapterMock->shouldReceive('beginTransaction')
184
                    ->times(1);
185
186
        $adapterMock->shouldReceive('rollbackTransaction')
187
                    ->times(1);
188
189
        $adapterMock->shouldReceive('isInTransaction')
190
                    ->andReturnFalse();
191
192
        $adapter = new NestedTransactionDecorator($adapterMock);
193
        $adapter->beginTransaction();
194
        $adapter->beginTransaction();
195
        $adapter->rollbackTransaction();
196
        $adapter->rollbackTransaction();
197
    }
198
199
    public function testBrokenTransactionIsRollbackOnly()
200
    {
201
        $this->expectException(\Exception::class);
202
        $this->expectExceptionMessage('Cannot commit Transaction was marked as rollback only');
203
204
        $adapterMock = \Mockery::mock(AdapterInterface::class);
205
        $adapterMock->shouldReceive('canHandleNestedTransaction')
206
                    ->andReturnFalse();
207
208
        $adapterMock->shouldReceive('beginTransaction')
209
                    ->times(1);
210
211
        $adapterMock->shouldReceive('commitTransaction')
212
                    ->times(0);
213
214
        $adapterMock->shouldReceive('rollbackTransaction');
215
216
        $adapterMock->shouldReceive('isInTransaction')
217
                    ->andReturnFalse();
218
219
        $adapter = new NestedTransactionDecorator($adapterMock);
220
        $adapter->beginTransaction();
221
        $adapter->beginTransaction();
222
        $adapter->rollbackTransaction();
223
        $adapter->commitTransaction();
224
        $adapter->rollbackTransaction();
225
    }
226
227
    public function testTransactionWasOpenOutside()
228
    {
229
        $dbAdapter = $this->dbAdapter;
230
231
        $adapterMock = \Mockery::mock($this->adapterNestedDoNotSupport);
232
        $adapterMock->shouldReceive('canHandleNestedTransaction')
233
                    ->andReturnFalse();
234
235
        $adapterMock->shouldReceive('beginTransaction')
236
                    ->times(2);
237
238
        $adapterMock->shouldReceive('commitTransaction')
239
                    ->times(1);
240
241
        $adapterMock->shouldReceive('rollbackTransaction')
242
                    ->times(1);
243
244
        $adapter = new NestedTransactionDecorator($adapterMock);
245
246
        $dbAdapter->beginTransaction(); // start transaction outside
247
248
        $adapter->beginTransaction();
249
        $adapter->commitTransaction();
250
251
        $dbAdapter->rollBack(); // close transaction outside
252
253
        $adapter->beginTransaction();
254
        $adapter->rollbackTransaction();
255
256
        $adapter->beginTransaction();
257
        $adapter->commitTransaction();
258
259
        $dbAdapter->beginTransaction(); // start transaction outside
260
261
        $adapter->beginTransaction();
262
        $adapter->rollbackTransaction();
263
264
        $dbAdapter->rollBack(); // close transaction outside
265
    }
266
}
267