Issues (99)

test/Db/Driver/MySQLTest.php (1 issue)

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