testBrokenTransactionIsRollbackOnly()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 18
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 26
rs 9.6666
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
/**
16
 * @internal
17
 */
18
class NestedTransactionDecoratorTest extends UnitTestCase
19
{
20
    /**
21
     * @var AdapterInterface
22
     */
23
    protected $adapterNestedDoNotSupport;
24
25
    /**
26
     * @var ZendDbAdapter
27
     */
28
    protected $dbAdapter;
29
30
    protected function setUp(): void
31
    {
32
        $this->dbAdapter = TestUtil::getPDOConnection();
0 ignored issues
show
Documentation Bug introduced by
It seems like StefanoTreeTest\TestUtil::getPDOConnection() of type PDO is incompatible with the declared type 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...
33
34
        $options = new Options(array(
35
            'tableName' => 'tree_traversal',
36
            'idColumnName' => 'tree_traversal_id',
37
        ));
38
39
        $this->adapterNestedDoNotSupport = new Pdo($options, $this->dbAdapter);
40
41
        parent::setUp();
42
    }
43
44
    protected function tearDown(): void
45
    {
46
        $this->adapterNestedDoNotSupport = null;
47
        parent::tearDown();
48
    }
49
50
    public function testCanHandleNestedTransaction()
51
    {
52
        $adapterStub = \Mockery::mock(AdapterInterface::class);
53
54
        $adapter = new NestedTransactionDecorator($adapterStub);
0 ignored issues
show
Bug introduced by
$adapterStub of type Mockery\LegacyMockInterface|Mockery\MockInterface is incompatible with the type StefanoTree\NestedSet\Adapter\AdapterInterface expected by parameter $adapter of StefanoTree\NestedSet\Ad...ecorator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

54
        $adapter = new NestedTransactionDecorator(/** @scrutinizer ignore-type */ $adapterStub);
Loading history...
55
        $this->assertTrue($adapter->canHandleNestedTransaction());
56
    }
57
58
    public function testWrappedAdapterCanHandleHandleNestedTransaction()
59
    {
60
        $adapterMock = \Mockery::mock(AdapterInterface::class);
61
        $adapterMock->shouldReceive('canHandleNestedTransaction')
62
            ->andReturnTrue();
0 ignored issues
show
Bug introduced by
The method andReturnTrue() does not exist on Mockery\ExpectationInterface. Did you maybe mean andReturn()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

62
            ->/** @scrutinizer ignore-call */ andReturnTrue();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
63
64
        $adapterMock->shouldReceive('beginTransaction')
65
            ->times(3);
66
67
        $adapterMock->shouldReceive('commitTransaction')
68
            ->times(2);
69
70
        $adapterMock->shouldReceive('rollbackTransaction')
71
            ->times(1);
72
73
        $adapterMock->shouldReceive('isInTransaction')
74
            ->andReturnFalse();
0 ignored issues
show
Bug introduced by
The method andReturnFalse() does not exist on Mockery\ExpectationInterface. Did you maybe mean andReturn()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

74
            ->/** @scrutinizer ignore-call */ andReturnFalse();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
75
76
        $adapter = new NestedTransactionDecorator($adapterMock);
0 ignored issues
show
Bug introduced by
$adapterMock of type Mockery\LegacyMockInterface|Mockery\MockInterface is incompatible with the type StefanoTree\NestedSet\Adapter\AdapterInterface expected by parameter $adapter of StefanoTree\NestedSet\Ad...ecorator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

76
        $adapter = new NestedTransactionDecorator(/** @scrutinizer ignore-type */ $adapterMock);
Loading history...
77
        $adapter->beginTransaction();
78
        $adapter->beginTransaction();
79
        $adapter->beginTransaction();
80
        $adapter->commitTransaction();
81
        $adapter->commitTransaction();
82
        $adapter->rollbackTransaction();
83
    }
84
85
    public function testHandleTransaction()
86
    {
87
        $adapterMock = \Mockery::mock(AdapterInterface::class);
88
        $adapterMock->shouldReceive('canHandleNestedTransaction')
89
            ->andReturnFalse();
90
91
        $adapterMock->shouldReceive('beginTransaction')
92
            ->times(1);
93
94
        $adapterMock->shouldReceive('commitTransaction')
95
            ->times(1);
96
97
        $adapterMock->shouldReceive('isInTransaction')
98
            ->andReturnFalse();
99
100
        $adapter = new NestedTransactionDecorator($adapterMock);
0 ignored issues
show
Bug introduced by
$adapterMock of type Mockery\LegacyMockInterface|Mockery\MockInterface is incompatible with the type StefanoTree\NestedSet\Adapter\AdapterInterface expected by parameter $adapter of StefanoTree\NestedSet\Ad...ecorator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

100
        $adapter = new NestedTransactionDecorator(/** @scrutinizer ignore-type */ $adapterMock);
Loading history...
101
        $adapter->beginTransaction();
102
        $adapter->commitTransaction();
103
    }
104
105
    public function testHandleBrokenTransaction()
106
    {
107
        $adapterMock = \Mockery::mock(AdapterInterface::class);
108
        $adapterMock->shouldReceive('canHandleNestedTransaction')
109
            ->andReturnFalse();
110
111
        $adapterMock->shouldReceive('beginTransaction')
112
            ->times(1);
113
114
        $adapterMock->shouldReceive('rollbackTransaction')
115
            ->times(1);
116
117
        $adapterMock->shouldReceive('isInTransaction')
118
            ->andReturnFalse();
119
120
        $adapter = new NestedTransactionDecorator($adapterMock);
0 ignored issues
show
Bug introduced by
$adapterMock of type Mockery\LegacyMockInterface|Mockery\MockInterface is incompatible with the type StefanoTree\NestedSet\Adapter\AdapterInterface expected by parameter $adapter of StefanoTree\NestedSet\Ad...ecorator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

120
        $adapter = new NestedTransactionDecorator(/** @scrutinizer ignore-type */ $adapterMock);
Loading history...
121
        $adapter->beginTransaction();
122
        $adapter->rollbackTransaction();
123
    }
124
125
    public function testRollbackOnlyMarkIsSetToFalseAfterRollbackSuccess()
126
    {
127
        $adapterMock = \Mockery::mock(AdapterInterface::class);
128
        $adapterMock->shouldReceive('canHandleNestedTransaction')
129
            ->andReturnFalse();
130
131
        $adapterMock->shouldReceive('beginTransaction')
132
            ->times(3);
133
134
        $adapterMock->shouldReceive('commitTransaction')
135
            ->times(2);
136
137
        $adapterMock->shouldReceive('rollbackTransaction')
138
            ->times(1);
139
140
        $adapterMock->shouldReceive('isInTransaction')
141
            ->andReturnFalse();
142
143
        $adapter = new NestedTransactionDecorator($adapterMock);
0 ignored issues
show
Bug introduced by
$adapterMock of type Mockery\LegacyMockInterface|Mockery\MockInterface is incompatible with the type StefanoTree\NestedSet\Adapter\AdapterInterface expected by parameter $adapter of StefanoTree\NestedSet\Ad...ecorator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
        $adapter = new NestedTransactionDecorator(/** @scrutinizer ignore-type */ $adapterMock);
Loading history...
144
        $adapter->beginTransaction();
145
        $adapter->beginTransaction();
146
        $adapter->rollbackTransaction();
147
        $adapter->rollbackTransaction();
148
149
        $adapter->beginTransaction();
150
        $adapter->commitTransaction();
151
152
        $adapter->beginTransaction();
153
        $adapter->beginTransaction();
154
        $adapter->commitTransaction();
155
        $adapter->commitTransaction();
156
    }
157
158
    public function testHandleNestedTransaction()
159
    {
160
        $adapterMock = \Mockery::mock(AdapterInterface::class);
161
        $adapterMock->shouldReceive('canHandleNestedTransaction')
162
            ->andReturnFalse();
163
164
        $adapterMock->shouldReceive('beginTransaction')
165
            ->times(1);
166
167
        $adapterMock->shouldReceive('commitTransaction')
168
            ->times(1);
169
170
        $adapterMock->shouldReceive('isInTransaction')
171
            ->andReturnFalse();
172
173
        $adapter = new NestedTransactionDecorator($adapterMock);
0 ignored issues
show
Bug introduced by
$adapterMock of type Mockery\LegacyMockInterface|Mockery\MockInterface is incompatible with the type StefanoTree\NestedSet\Adapter\AdapterInterface expected by parameter $adapter of StefanoTree\NestedSet\Ad...ecorator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

173
        $adapter = new NestedTransactionDecorator(/** @scrutinizer ignore-type */ $adapterMock);
Loading history...
174
        $adapter->beginTransaction();
175
        $adapter->beginTransaction();
176
        $adapter->commitTransaction();
177
        $adapter->commitTransaction();
178
    }
179
180
    public function testHandleBrokenNestedTransaction()
181
    {
182
        $adapterMock = \Mockery::mock(AdapterInterface::class);
183
        $adapterMock->shouldReceive('canHandleNestedTransaction')
184
            ->andReturnFalse();
185
186
        $adapterMock->shouldReceive('beginTransaction')
187
            ->times(1);
188
189
        $adapterMock->shouldReceive('rollbackTransaction')
190
            ->times(1);
191
192
        $adapterMock->shouldReceive('isInTransaction')
193
            ->andReturnFalse();
194
195
        $adapter = new NestedTransactionDecorator($adapterMock);
0 ignored issues
show
Bug introduced by
$adapterMock of type Mockery\LegacyMockInterface|Mockery\MockInterface is incompatible with the type StefanoTree\NestedSet\Adapter\AdapterInterface expected by parameter $adapter of StefanoTree\NestedSet\Ad...ecorator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

195
        $adapter = new NestedTransactionDecorator(/** @scrutinizer ignore-type */ $adapterMock);
Loading history...
196
        $adapter->beginTransaction();
197
        $adapter->beginTransaction();
198
        $adapter->rollbackTransaction();
199
        $adapter->rollbackTransaction();
200
    }
201
202
    public function testBrokenTransactionIsRollbackOnly()
203
    {
204
        $this->expectException(\Exception::class);
205
        $this->expectExceptionMessage('Cannot commit Transaction was marked as rollback only');
206
207
        $adapterMock = \Mockery::mock(AdapterInterface::class);
208
        $adapterMock->shouldReceive('canHandleNestedTransaction')
209
            ->andReturnFalse();
210
211
        $adapterMock->shouldReceive('beginTransaction')
212
            ->times(1);
213
214
        $adapterMock->shouldReceive('commitTransaction')
215
            ->times(0);
216
217
        $adapterMock->shouldReceive('rollbackTransaction');
218
219
        $adapterMock->shouldReceive('isInTransaction')
220
            ->andReturnFalse();
221
222
        $adapter = new NestedTransactionDecorator($adapterMock);
0 ignored issues
show
Bug introduced by
$adapterMock of type Mockery\LegacyMockInterface|Mockery\MockInterface is incompatible with the type StefanoTree\NestedSet\Adapter\AdapterInterface expected by parameter $adapter of StefanoTree\NestedSet\Ad...ecorator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

222
        $adapter = new NestedTransactionDecorator(/** @scrutinizer ignore-type */ $adapterMock);
Loading history...
223
        $adapter->beginTransaction();
224
        $adapter->beginTransaction();
225
        $adapter->rollbackTransaction();
226
        $adapter->commitTransaction();
227
        $adapter->rollbackTransaction();
228
    }
229
230
    public function testTransactionWasOpenOutside()
231
    {
232
        $dbAdapter = $this->dbAdapter;
233
234
        $adapterMock = \Mockery::mock($this->adapterNestedDoNotSupport);
235
        $adapterMock->shouldReceive('canHandleNestedTransaction')
236
            ->andReturnFalse();
237
238
        $adapterMock->shouldReceive('beginTransaction')
239
            ->times(2);
240
241
        $adapterMock->shouldReceive('commitTransaction')
242
            ->times(1);
243
244
        $adapterMock->shouldReceive('rollbackTransaction')
245
            ->times(1);
246
247
        $adapter = new NestedTransactionDecorator($adapterMock);
0 ignored issues
show
Bug introduced by
$adapterMock of type Mockery\LegacyMockInterface|Mockery\MockInterface is incompatible with the type StefanoTree\NestedSet\Adapter\AdapterInterface expected by parameter $adapter of StefanoTree\NestedSet\Ad...ecorator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

247
        $adapter = new NestedTransactionDecorator(/** @scrutinizer ignore-type */ $adapterMock);
Loading history...
248
249
        $dbAdapter->beginTransaction(); // start transaction outside
250
251
        $adapter->beginTransaction();
252
        $adapter->commitTransaction();
253
254
        $dbAdapter->rollBack(); // close transaction outside
255
256
        $adapter->beginTransaction();
257
        $adapter->rollbackTransaction();
258
259
        $adapter->beginTransaction();
260
        $adapter->commitTransaction();
261
262
        $dbAdapter->beginTransaction(); // start transaction outside
263
264
        $adapter->beginTransaction();
265
        $adapter->rollbackTransaction();
266
267
        $dbAdapter->rollBack(); // close transaction outside
268
    }
269
}
270