Passed
Push — master ( 9b30b3...3078fb )
by Darío
01:46
created

MySQLTest::testTransactionConfirmationShortcut()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 39
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 20
nc 1
nop 0
dl 0
loc 39
rs 9.6
c 0
b 0
f 0
1
<?php
2
/**
3
 * DronePHP (http://www.dronephp.com)
4
 *
5
 * @link      http://github.com/Pleets/DronePHP
6
 * @copyright Copyright (c) 2016-2018 Pleets. (http://www.pleets.org)
7
 * @license   http://www.dronephp.com/license
8
 * @author    Darío Rivera <[email protected]>
9
 */
10
11
namespace DroneTest\Util;
12
13
use Drone\Db\Driver\MySQL;
14
use Drone\Db\Driver\Exception\ConnectionException;
15
use Drone\Db\Driver\Exception\InvalidQueryException;
16
use PHPUnit\Framework\TestCase;
17
18
class MySQLTest extends TestCase
19
{
20
    /**
21
     * Database parameters
22
     */
23
    private $options = [
24
        "dbhost"       => "localhost",
25
        "dbuser"       => "root",
26
        "dbpass"       => "",
27
        "dbname"       => "test",
28
        "dbchar"       => "utf8",
29
        "dbport"       => "3306",
30
        "auto_connect" => false
31
    ];
32
33
    /*
34
    |--------------------------------------------------------------------------
35
    | Stablishing connections
36
    |--------------------------------------------------------------------------
37
    |
38
    | The following tests are related to the connection methods and its
39
    | exceptions and returned values.
40
    |
41
    */
42
43
    /**
44
     * Tests if we can connect to the database server
45
     *
46
     * @return null
47
     */
48
    public function testCanStablishConnection()
49
    {
50
        $conn = new MySQL($this->options);
51
52
        $mysqliObject = $conn->connect();
53
54
        $this->assertInstanceOf('\mysqli', $mysqliObject);
55
        $this->assertTrue($conn->isConnected());
56
    }
57
58
    /**
59
     * Tests if we can disconnect from the database server
60
     *
61
     * @return null
62
     */
63
    public function testCanDownConnection()
64
    {
65
        $conn = new MySQL($this->options);
66
67
        $conn->connect();
68
        $result = $conn->disconnect();
69
70
        $this->assertNotTrue($conn->isConnected());
71
        $this->assertTrue($result);
72
    }
73
74
    /**
75
     * Tests if we can disconnect from server when there is not a connection stablished
76
     *
77
     * @return null
78
     */
79
    public function testCannotDisconectWhenNotConnected()
80
    {
81
        $conn = new MySQL($this->options);
82
83
        $errorObject = null;
84
85
        try {
86
            $conn->disconnect();
87
        }
88
        catch (\Exception $e)
89
        {
90
            $errorObject = ($e instanceof \LogicException);
91
        }
92
        finally
93
        {
94
            $this->assertNotTrue($conn->isConnected());
95
            $this->assertTrue($errorObject, $e->getMessage());
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $e does not seem to be defined for all execution paths leading up to this point.
Loading history...
96
        }
97
    }
98
99
    /**
100
     * Tests if we can reconnect to the database server
101
     *
102
     * @return null
103
     */
104
    public function testCanStablishConnectionAgain()
105
    {
106
        $conn = new MySQL($this->options);
107
108
        $conn->connect();
109
        $mysqliObject = $conn->reconnect();
110
111
        $this->assertInstanceOf('\mysqli', $mysqliObject);
112
        $this->assertTrue($conn->isConnected());
113
    }
114
115
    /**
116
     * Tests if we can reconnect to the database server when there is not a connection stablished
117
     *
118
     * @return null
119
     */
120
    public function testCannotStablishReconnection()
121
    {
122
        $conn = new MySQL($this->options);
123
124
        $errorObject = null;
125
126
        try {
127
            $conn->reconnect();
128
        }
129
        catch (\Exception $e)
130
        {
131
            $errorObject = ($e instanceof \LogicException);
132
        }
133
        finally
134
        {
135
            $this->assertTrue($errorObject, $e->getMessage());
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $e does not seem to be defined for all execution paths leading up to this point.
Loading history...
136
            $this->assertNotTrue($conn->isConnected());
137
        }
138
    }
139
140
    /**
141
     * Tests if a failed connection throws a ConnectionException
142
     *
143
     * @return null
144
     */
145
    public function testCannotStablishConnection()
146
    {
147
        $options = $this->options;
148
        $options["dbhost"] = 'myserver';   // this server does not exists
149
150
        $conn = new MySQL($options);
151
152
        $mysqliObject = $errorObject = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $mysqliObject is dead and can be removed.
Loading history...
153
154
        $message = "No exception";
155
156
        try {
157
            $mysqliObject = $conn->connect();
158
        }
159
        catch (\Exception $e)
160
        {
161
            $errorObject = ($e instanceof ConnectionException);
162
            $message = $e->getMessage();
163
        }
164
        finally
165
        {
166
            $this->assertTrue($errorObject, $message);
167
            $this->assertNotTrue($conn->isConnected());
168
        }
169
    }
170
171
    /*
172
    |--------------------------------------------------------------------------
173
    | Quering and Transactions
174
    |--------------------------------------------------------------------------
175
    |
176
    | The following tests are related to query and transaction operations and its
177
    | exceptions and returned values.
178
    |
179
    */
180
181
    /**
182
     * Tests if we can execute DDL statements
183
     *
184
     * @return null
185
     */
186
    public function testCanExecuteDLLStatement()
187
    {
188
        $options = $this->options;
189
        $options["auto_connect"] = true;
190
191
        $conn = new MySQL($options);
192
        $sql = "CREATE TABLE MYTABLE (ID INTEGER(11) NOT NULL PRIMARY KEY AUTO_INCREMENT, DESCRIPTION VARCHAR(100))";
193
        $result = $conn->execute($sql);
194
195
        $this->assertTrue(is_object($result));
196
197
        # properties modified by execute() method
198
        $this->assertEquals(0, $conn->getNumRows());
199
        $this->assertEquals(0, $conn->getNumFields());
200
        $this->assertEquals(0, $conn->getRowsAffected());
201
    }
202
203
    /**
204
     * Tests if we can execute DML statements
205
     *
206
     * @return null
207
     */
208
    public function testCanExecuteDMLStatement()
209
    {
210
        $options = $this->options;
211
        $options["auto_connect"] = true;
212
213
        $conn = new MySQL($options);
214
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('Hello world!')";
215
        $result = $conn->execute($sql);
216
217
        $this->assertTrue(is_object($result));
218
219
        # properties modified by execute() method
220
        $this->assertEquals(0, $conn->getNumRows());
221
        $this->assertEquals(0, $conn->getNumFields());
222
        $this->assertEquals(1, $conn->getRowsAffected());
223
    }
224
225
    /**
226
     * Tests if a wrong query execution throws an InvalidQueryException
227
     *
228
     * @return null
229
     */
230
    public function testGettingInvalidQueryException()
231
    {
232
        $options = $this->options;
233
        $options["auto_connect"] = true;
234
235
        $conn = new MySQL($options);
236
237
        $errorObject = null;
238
        $message = "No exception";
239
240
        try
241
        {
242
            $sql = "INSERT INTO MYTABLE (DESCRIPTION, WRONG) VALUES ('Hello world!')";
243
	        $result = $conn->execute($sql);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
244
        }
245
        catch (\Exception $e)
246
        {
247
            $errorObject = ($e instanceof InvalidQueryException);
248
            $message = $e->getMessage();
249
        }
250
        finally
251
        {
252
            $this->assertTrue($errorObject, $message);
253
        }
254
    }
255
256
    /**
257
     * Tests getting results
258
     *
259
     * @return null
260
     */
261
    public function testGettingResults()
262
    {
263
        $options = $this->options;
264
        $options["auto_connect"] = true;
265
266
        $conn = new MySQL($options);
267
        $sql = "SELECT * FROM MYTABLE LIMIT 2";
268
        $result = $conn->execute($sql);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
269
270
        # properties modified by execute() method
271
        $this->assertEquals(1, $conn->getNumRows());
272
        $this->assertEquals(2, $conn->getNumFields());
273
        $this->assertEquals(0, $conn->getRowsAffected());
274
275
        $rowset = $conn->getArrayResult();    # array with results
276
        $row = array_shift($rowset);
277
278
        $this->assertArrayHasKey("ID", $row);
279
        $this->assertArrayHasKey("DESCRIPTION", $row);
280
    }
281
282
    /**
283
     * Tests if we can commit transactions
284
     *
285
     * @return null
286
     */
287
    public function testCommitBehavior()
288
    {
289
        $options = $this->options;
290
        $options["auto_connect"] = true;
291
292
        $conn = new MySQL($options);
293
        $conn->autocommit(false);
294
295
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('COMMIT_ROW_1')";
296
        $result = $conn->execute($sql);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
297
298
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION = 'COMMIT_ROW_1'";
299
        $result = $conn->execute($sql);
300
        $rowcount = count($conn->getArrayResult());
301
302
        $this->assertTrue(($rowcount === 1));    # the row is available for now
303
304
        # properties modified by execute() method
305
        $this->assertEquals(1, $conn->getNumRows());
306
        $this->assertEquals(2, $conn->getNumFields());
307
        $this->assertEquals(0, $conn->getRowsAffected());    # nothing affected (autocommit = false)
308
309
        $this->assertTrue($conn->commit());
310
311
        # now let's to verify if the record exists after commit
312
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION = 'COMMIT_ROW_1'";
313
        $result = $conn->execute($sql);
314
        $rowcount = count($conn->getArrayResult());
315
316
        $this->assertTrue(($rowcount === 1));    # the row is available
317
    }
318
319
    /**
320
     * Tests if we can rollback transactions
321
     *
322
     * @return null
323
     */
324
    public function testRollbackBehavior()
325
    {
326
        $options = $this->options;
327
        $options["auto_connect"] = true;
328
329
        $conn = new MySQL($options);
330
        $conn->autocommit(false);
331
332
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('ROLLBACK_ROW_1')";
333
        $result = $conn->execute($sql);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
334
335
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION = 'ROLLBACK_ROW_1'";
336
        $result = $conn->execute($sql);
337
        $rowcount = count($conn->getArrayResult());
338
339
        $this->assertTrue(($rowcount === 1));    # the row is available for now
340
341
        # properties modified by execute() method
342
        $this->assertEquals(1, $conn->getNumRows());
343
        $this->assertEquals(2, $conn->getNumFields());
344
        $this->assertEquals(0, $conn->getRowsAffected());    # nothing affected (autocommit = false)
345
346
        $this->assertTrue($conn->rollback());
347
348
        # now let's to verify if the record exists after commit
349
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION = 'ROLLBACK_ROW_1'";
350
        $result = $conn->execute($sql);
351
        $rowcount = count($conn->getArrayResult());
352
353
        $this->assertNotTrue(($rowcount === 1));    # the row is not available
354
    }
355
356
    /**
357
     * Tests if we can do a transaction with commiting changes
358
     *
359
     * @return null
360
     */
361
    public function testTransactionConfirmation()
362
    {
363
        $options = $this->options;
364
        $options["auto_connect"] = true;
365
366
        $conn = new MySQL($options);
367
        $conn->autocommit(false);
368
369
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('COMMIT_ROW_TRANSACTION_1')";
370
        $result = $conn->execute($sql);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
371
372
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('COMMIT_ROW_TRANSACTION_2')";
373
        $result = $conn->execute($sql);
374
375
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('COMMIT_ROW_TRANSACTION_3')";
376
        $result = $conn->execute($sql);
377
378
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('COMMIT_ROW_TRANSACTION_4')";
379
        $result = $conn->execute($sql);
380
381
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION LIKE 'COMMIT_ROW_TRANSACTION_%'";
382
        $result = $conn->execute($sql);
383
        $rowcount = count($conn->getArrayResult());
384
385
        $this->assertTrue(($rowcount === 4));    # the rows are available for now
386
387
        # properties modified by execute() method
388
        $this->assertEquals(4, $conn->getNumRows());
389
        $this->assertEquals(2, $conn->getNumFields());
390
        $this->assertEquals(0, $conn->getRowsAffected());    # nothing affected (autocommit = false)
391
392
        $this->assertTrue($conn->commit());
393
394
        # now let's to verify if the record exists after commit
395
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION LIKE 'COMMIT_ROW_TRANSACTION_%'";
396
        $result = $conn->execute($sql);
397
        $rowcount = count($conn->getArrayResult());
398
399
        $this->assertTrue(($rowcount === 4));    # the row is available
400
    }
401
402
    /**
403
     * Tests if we can do a transaction with reverting changes
404
     *
405
     * @return null
406
     */
407
    public function testTransactionReversion()
408
    {
409
        $options = $this->options;
410
        $options["auto_connect"] = true;
411
412
        $conn = new MySQL($options);
413
        $conn->autocommit(false);
414
415
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('ROLLBACK_ROW_TRANSACTION_1')";
416
        $result = $conn->execute($sql);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
417
418
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('ROLLBACK_ROW_TRANSACTION_2')";
419
        $result = $conn->execute($sql);
420
421
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('ROLLBACK_ROW_TRANSACTION_3')";
422
        $result = $conn->execute($sql);
423
424
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('ROLLBACK_ROW_TRANSACTION_4')";
425
        $result = $conn->execute($sql);
426
427
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION LIKE 'ROLLBACK_ROW_TRANSACTION_%'";
428
        $result = $conn->execute($sql);
429
        $rowcount = count($conn->getArrayResult());
430
431
        $this->assertTrue(($rowcount === 4));    # the rows are available for now
432
433
        # properties modified by execute() method
434
        $this->assertEquals(4, $conn->getNumRows());
435
        $this->assertEquals(2, $conn->getNumFields());
436
        $this->assertEquals(0, $conn->getRowsAffected());    # nothing affected (autocommit = false)
437
438
        $this->assertTrue($conn->rollback());
439
440
        # now let's to verify if the record exists after commit
441
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION LIKE 'ROLLBACK_ROW_TRANSACTION_%'";
442
        $result = $conn->execute($sql);
443
        $rowcount = count($conn->getArrayResult());
444
445
        $this->assertNotTrue(($rowcount === 4));    # the row is available
446
    }
447
448
    /**
449
     * Tests if we can do a transaction with the shortcut method
450
     *
451
     * @return null
452
     */
453
    public function testTransactionConfirmationShortcut()
454
    {
455
        $options = $this->options;
456
        $options["auto_connect"] = true;
457
458
        $conn = new MySQL($options);
459
460
        # not necessary!
461
        # $conn->autocommit(false);
462
463
        # starts the transaction
464
        $conn->beginTransaction();
465
466
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('TRANSACTION_SHORTCUT_1')";
467
        $result = $conn->execute($sql);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
468
469
        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('TRANSACTION_SHORTCUT_1')";
470
        $result = $conn->execute($sql);
471
472
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION LIKE 'TRANSACTION_SHORTCUT_%'";
473
        $result = $conn->execute($sql);
474
        $rowcount = count($conn->getArrayResult());
475
476
        $this->assertTrue(($rowcount === 2));    # the rows are available for now
477
478
        # properties modified by execute() method
479
        $this->assertEquals(2, $conn->getNumRows());
480
        $this->assertEquals(2, $conn->getNumFields());
481
        $this->assertEquals(0, $conn->getRowsAffected());    # nothing affected (autocommit = false)
482
483
        # ends the transaction
484
        $conn->endTransaction();
485
486
        # now let's to verify if the record exists after endTransaction()
487
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION LIKE 'TRANSACTION_SHORTCUT_%'";
488
        $result = $conn->execute($sql);
489
        $rowcount = count($conn->getArrayResult());
490
491
        $this->assertTrue(($rowcount === 2));    # the row is available
492
    }
493
494
    /**
495
     * Tests if we can do a transaction with reverting changes
496
     *
497
     * @return null
498
     */
499
    public function testTransactionReversionShortcut()
500
    {
501
        $options = $this->options;
502
        $options["auto_connect"] = true;
503
504
        $conn = new MySQL($options);
505
506
        # not necessary!
507
        # $conn->autocommit(false);
508
509
        # starts the transaction
510
        $conn->beginTransaction();
511
512
        try
513
        {
514
	        $sql = "INSERT INTO MYTABLE (DESCRIPTION) VALUES ('TRANS_SHORTCUT_1')";
515
	        $result = $conn->execute($sql);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
516
517
	        $sql = "INSERT INTO MYTABLE (DESCRIPTION, WRONG) VALUES ('TRANS_SHORTCUT_2')";
518
	        $result = $conn->execute($sql);
519
        }
520
        catch (InvalidQueryException $e)
521
        {
522
            $message = $e->getMessage();
0 ignored issues
show
Unused Code introduced by
The assignment to $message is dead and can be removed.
Loading history...
523
            #·not necessary!
524
            # $this->assertTrue($conn->rollback());
525
        }
526
527
        # starts the transaction
528
        $conn->endTransaction();
529
530
        # now let's to verify if the record exists after endTransaction()
531
        $sql = "SELECT * FROM MYTABLE WHERE DESCRIPTION LIKE 'TRANS_SHORTCUT_%'";
532
        $result = $conn->execute($sql);
533
        $rowcount = count($conn->getArrayResult());
534
535
        $this->assertNotTrue(($rowcount === 0));    # the rows are not available
536
    }
537
}