Completed
Push — nomi/archive-docs ( 959cb6...8e5004 )
by
unknown
15:52 queued 05:59
created

PDOStatementTest::testColumnCountSameColumnTwice()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
rs 9.4285
cc 1
eloc 6
nc 1
nop 0
1
<?php
2
/**
3
 * Licensed to CRATE Technology GmbH("Crate") under one or more contributor
4
 * license agreements.  See the NOTICE file distributed with this work for
5
 * additional information regarding copyright ownership.  Crate licenses
6
 * this file to you under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.  You may
8
 * obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
15
 * License for the specific language governing permissions and limitations
16
 * under the License.
17
 *
18
 * However, if you have executed another commercial license agreement
19
 * with Crate these terms will supersede the license and you may use the
20
 * software solely pursuant to the terms of the relevant commercial agreement.
21
 */
22
23
namespace CrateTest\PDO;
24
25
use Crate\PDO\PDO;
26
use Crate\PDO\PDOStatement;
27
use Crate\Stdlib\Collection;
28
use Crate\Stdlib\CollectionInterface;
29
use Crate\Stdlib\CrateConst;
30
use PHPUnit_Framework_MockObject_MockObject;
31
use PHPUnit_Framework_TestCase;
32
use ReflectionClass;
33
use ReflectionMethod;
34
use ReflectionProperty;
35
36
/**
37
 * Tests for {@see \Crate\PDO\PDOStatement}
38
 *
39
 * @coversDefaultClass \Crate\PDO\PDOStatement
40
 * @covers ::<!public>
41
 *
42
 * @group unit
43
 * @group statement
44
 */
45
class PDOStatementTest extends PHPUnit_Framework_TestCase
46
{
47
    const SQL = 'SELECT * FROM table_name';
48
49
    /**
50
     * @var PDO|PHPUnit_Framework_MockObject_MockObject
51
     */
52
    protected $pdo;
53
54
    /**
55
     * @var PDOStatement
56
     */
57
    protected $statement;
58
59
    /**
60
     * @var mixed
61
     */
62
    protected $callbackReturnValue;
63
64
    /**
65
     * @var array
66
     */
67
    protected $callbackCallParams;
68
69
    protected function setUp()
70
    {
71
        $this->pdo = $this->getMock('Crate\PDO\PDOInterface');
72
73
74
        $callback = function() {
75
76
            $args = func_get_args();
77
78
            if ($this->callbackCallParams !== null) {
79
                $this->assertEquals($args, $this->callbackCallParams);
80
            }
81
82
            return $this->callbackReturnValue;
83
        };
84
85
        $this->statement = new PDOStatement($this->pdo, $callback, static::SQL, []);
86
    }
87
88
    /**
89
     * @return CollectionInterface
90
     */
91
    private function getPopulatedCollection()
92
    {
93
        $data = [
94
            [1, 'foo', false],
95
            [2, 'bar', true],
96
        ];
97
98
        $columns = ['id', 'name', 'active'];
99
100
        return new Collection($data, $columns, 0, count($data));
101
    }
102
103
    /**
104
     * @covers ::__construct
105
     */
106
    public function testInstantiation()
107
    {
108
        $this->assertInstanceOf('Crate\PDO\PDOStatement', $this->statement);
109
        $this->assertInstanceOf('PDOStatement', $this->statement);
110
    }
111
112
    /**
113
     * @covers ::execute
114
     */
115
    public function testExecuteWithErrorResponse()
116
    {
117
        $this->callbackReturnValue = ['code' => 1337, 'message' => 'failed'];
118
119
        $this->assertFalse($this->statement->execute());
120
121
        list ($ansiErrorCode, $driverCode, $message) = $this->statement->errorInfo();
0 ignored issues
show
Unused Code introduced by
The assignment to $ansiErrorCode is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
122
123
        $this->assertEquals(1337, $driverCode);
124
        $this->assertEquals('failed', $message);
125
    }
126
127
    /**
128
     * @covers ::execute
129
     */
130
    public function testExecute()
131
    {
132
        $parameters = ['bar'];
133
134
        $this->callbackCallParams  = [$this->statement, static::SQL, $parameters];
135
        $this->callbackReturnValue = $this->getPopulatedCollection();
136
137
        $this->assertTrue($this->statement->execute($parameters));
138
    }
139
140
    /**
141
     * @covers ::bindParam
142
     */
143
    public function testBindParam()
144
    {
145
        $initial  = 'foo';
146
        $expected = 'bar';
147
148
        $this->callbackCallParams  = [$this->statement, static::SQL, [0 => $expected]];
149
        $this->callbackReturnValue = $this->getPopulatedCollection();
150
151
        $this->statement->bindParam(1, $initial);
152
153
        // Update bar prior to calling execute
154
        $initial = $expected;
0 ignored issues
show
Unused Code introduced by
$initial is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
155
156
        $this->statement->execute();
157
    }
158
159
    /**
160
     * @covers ::bindParam
161
     */
162
    public function testBindParamInvalidPosition()
163
    {
164
        $initial  = 'foo';
165
        $expected = 'bar';
166
167
        $this->callbackCallParams  = [$this->statement, static::SQL, [0 => $expected]];
168
        $this->callbackReturnValue = $this->getPopulatedCollection();
169
170
        $this->setExpectedException('Crate\PDO\Exception\UnsupportedException');
171
        $this->statement->bindParam(0, $initial);
172
    }
173
174
    /**
175
     * @covers ::bindColumn
176
     */
177
    public function testBindColumn()
178
    {
179
        $column     = 'column';
180
        $value      = 'value1';
181
        $type       = PDO::PARAM_STR;
182
        $maxlen     = 1000;
183
        $driverData = null;
184
185
        $this->statement->bindColumn($column, $value, $type, $maxlen, $driverData);
186
187
        $reflection = new ReflectionClass('Crate\PDO\PDOStatement');
188
189
        $property = $reflection->getProperty('columnBinding');
190
        $property->setAccessible(true);
191
192
        $columnBinding = $property->getValue($this->statement);
193
194
        $this->assertArrayHasKey($column, $columnBinding);
195
        $this->assertEquals($value, $columnBinding[$column]['ref']);
196
197
        $value = 'value2';
198
199
        $this->assertEquals($value, $columnBinding[$column]['ref']);
200
    }
201
202
    public function bindValueParameterProvider()
203
    {
204
        return [
205
            [PDO::PARAM_INT, '1', 1],
206
            [PDO::PARAM_NULL, '1', null],
207
            [PDO::PARAM_BOOL, '1', true],
208
            [PDO::PARAM_STR, '1', '1']
209
        ];
210
    }
211
212
    /**
213
     * @dataProvider bindValueParameterProvider
214
     * @covers ::bindValue
215
     *
216
     * @param int    $type
217
     * @param string $value
218
     * @param mixed  $expectedValue
219
     */
220
    public function testBindValue($type, $value, $expectedValue)
221
    {
222
        $this->statement->bindValue(1, $value, $type);
223
224
        $reflection = new ReflectionClass('Crate\PDO\PDOStatement');
225
226
        $property = $reflection->getProperty('parameters');
227
        $property->setAccessible(true);
228
229
        $castedValue = $property->getValue($this->statement);
230
231
        $this->assertSame($expectedValue, $castedValue[0]);
232
    }
233
234
    /**
235
     * @covers ::fetch
236
     */
237
    public function testFetchWithUnsuccessfulExecution()
238
    {
239
        $this->callbackReturnValue = ['code' => 1337, 'message' => 'expected failure'];
240
241
        $this->assertFalse($this->statement->fetch());
242
    }
243
244
    /**
245
     * @covers ::fetch
246
     */
247
    public function testFetchWithEmptyResult()
248
    {
249
        $collection = $this->getMock('Crate\Stdlib\CollectionInterface');
250
        $collection
251
            ->expects($this->once())
252
            ->method('valid')
253
            ->will($this->returnValue(false));
254
255
        $this->callbackReturnValue = $collection;
256
257
        $this->assertFalse($this->statement->fetch(PDO::FETCH_NUM));
258
    }
259
260
    /**
261
     * @covers ::fetch
262
     */
263
    public function testFetchWithBoundStyle()
264
    {
265
        $id     = null;
266
        $name   = null;
267
        $active = null;
268
269
        $this->statement->bindColumn('id', $id, PDO::PARAM_INT);
270
        $this->statement->bindColumn('name', $name, PDO::PARAM_STR);
271
        $this->statement->bindColumn('active', $active, PDO::PARAM_BOOL);
272
273
        $this->assertNull($id);
274
        $this->assertNull($name);
275
        $this->assertNull($active);
276
277
        $this->callbackReturnValue = $this->getPopulatedCollection();
278
279
        $this->statement->fetch(PDO::FETCH_BOUND);
280
281
        $this->assertSame(1, $id);
282
        $this->assertSame('foo', $name);
283
        $this->assertFalse($active);
284
285
        $this->statement->fetch(PDO::FETCH_BOUND);
286
287
        $this->assertSame(2, $id);
288
        $this->assertSame('bar', $name);
289
        $this->assertTrue($active);
290
    }
291
292
    public function fetchStyleProvider()
293
    {
294
        return [
295
            [PDO::FETCH_NAMED, ['id' => 1, 'name' => 'foo', 'active' => false]],
296
            [PDO::FETCH_ASSOC, ['id' => 1, 'name' => 'foo', 'active' => false]],
297
            [PDO::FETCH_BOTH, [0 => 1, 1 => 'foo', 2 => false, 'id' => 1, 'name' => 'foo', 'active' => false]],
298
            [PDO::FETCH_NUM, [0 => 1, 1 => 'foo', 2 => false]]
299
        ];
300
    }
301
302
    /**
303
     * @dataProvider fetchStyleProvider
304
     * @covers ::fetch
305
     *
306
     * @param int   $fetchStyle
307
     * @param array $expected
308
     */
309
    public function testFetch($fetchStyle, array $expected)
310
    {
311
        $this->callbackReturnValue = $this->getPopulatedCollection();
312
313
        $result = $this->statement->fetch($fetchStyle);
314
315
        $this->assertEquals($expected, $result);
316
    }
317
318
    /**
319
     * @covers ::fetch
320
     */
321
    public function testFetchWithUnsupportedFetchStyle()
322
    {
323
        $this->setExpectedException('Crate\PDO\Exception\UnsupportedException');
324
325
        $this->callbackReturnValue = $this->getPopulatedCollection();
326
327
        $this->statement->fetch(PDO::FETCH_INTO);
328
    }
329
330
    /**
331
     * @covers ::rowCount
332
     */
333
    public function testRowCountWithFailedExecution()
334
    {
335
        $this->callbackReturnValue = ['code' => 1337, 'message' => 'expected failure'];
336
337
        $this->assertEquals(0, $this->statement->rowCount());
338
    }
339
340
    /**
341
     * @covers ::rowCount
342
     */
343
    public function testRowCount()
344
    {
345
        $this->callbackReturnValue = $this->getPopulatedCollection();
346
        $this->assertEquals(2, $this->statement->rowCount());
347
    }
348
349
    /**
350
     * @covers ::fetchColumn
351
     */
352
    public function testFetchColumnWithInvalidColumnNumberType()
353
    {
354
        $this->setExpectedException('Crate\PDO\Exception\InvalidArgumentException');
355
        $this->statement->fetchColumn('test');
356
    }
357
358
    /**
359
     * @covers ::fetchColumn
360
     */
361
    public function testFetchColumnWithFailedExecution()
362
    {
363
        $this->callbackReturnValue = ['code' => 1337, 'message' => 'expected failure'];
364
        $this->assertFalse($this->statement->fetchColumn());
365
    }
366
367
    /**
368
     * @covers ::fetchColumn
369
     */
370
    public function testFetchColumnWithWithEmptyCollection()
371
    {
372
        $collection = $this->getMock('Crate\Stdlib\CollectionInterface');
373
        $collection
374
            ->expects($this->once())
375
            ->method('valid')
376
            ->will($this->returnValue(false));
377
378
        $this->callbackReturnValue = $collection;
379
        $this->assertFalse($this->statement->fetchColumn());
380
    }
381
382
    /**
383
     * @covers ::fetchColumn
384
     */
385
    public function testFetchColumnWithInvalidColumnIndex()
386
    {
387
        $this->setExpectedException('Crate\PDO\Exception\OutOfBoundsException');
388
389
        $this->callbackReturnValue = $this->getPopulatedCollection();
390
        $this->statement->fetchColumn(10);
391
    }
392
393
    /**
394
     * @covers ::fetchColumn
395
     */
396
    public function testFetchColumn()
397
    {
398
        $this->callbackReturnValue = $this->getPopulatedCollection();
399
400
        $this->assertEquals(1, $this->statement->fetchColumn());
401
        $this->assertEquals(2, $this->statement->fetchColumn());
402
        $this->assertFalse($this->statement->fetchColumn());
403
    }
404
405
    /**
406
     * @covers ::fetchAll
407
     */
408
    public function testFetchAllWithFailedExecution()
409
    {
410
        $this->callbackReturnValue = ['code' => 1337, 'message' => 'expected failure'];
411
412
        $this->assertFalse($this->statement->fetchAll());
413
    }
414
415
    /**
416
     * @covers ::fetchAll
417
     */
418
    public function testFetchAllWithInvalidFetchStyle()
419
    {
420
        $this->setExpectedException('Crate\PDO\Exception\UnsupportedException');
421
        $this->callbackReturnValue = $this->getPopulatedCollection();
422
423
        $this->statement->fetchAll(PDO::FETCH_INTO);
424
    }
425
426
    /**
427
     * @return array
428
     */
429
    public function fetchAllStyleProvider()
430
    {
431
        return [
432
            [
433
                // Null mean it will use the default which is PDO::FETCH_BOTH
434
                null,
435
                [
436
                    [
437
                        0        => 1,
438
                        1        => 'foo',
439
                        2        => false,
440
                        'id'     => 1,
441
                        'name'   => 'foo',
442
                        'active' => false
443
                    ],
444
                    [
445
                        0        => 2,
446
                        1        => 'bar',
447
                        2        => true,
448
                        'id'     => 2,
449
                        'name'   => 'bar',
450
                        'active' => true
451
                    ]
452
                ]
453
            ],
454
            [
455
                PDO::FETCH_BOTH,
456
                [
457
                    [
458
                        0        => 1,
459
                        1        => 'foo',
460
                        2        => false,
461
                        'id'     => 1,
462
                        'name'   => 'foo',
463
                        'active' => false
464
                    ],
465
                    [
466
                        0        => 2,
467
                        1        => 'bar',
468
                        2        => true,
469
                        'id'     => 2,
470
                        'name'   => 'bar',
471
                        'active' => true
472
                    ]
473
                ]
474
            ],
475
            [
476
                PDO::FETCH_ASSOC,
477
                [
478
                    [
479
                        'id'     => 1,
480
                        'name'   => 'foo',
481
                        'active' => false
482
                    ],
483
                    [
484
                        'id'     => 2,
485
                        'name'   => 'bar',
486
                        'active' => true
487
                    ]
488
                ]
489
            ],
490
            [
491
                PDO::FETCH_NAMED,
492
                [
493
                    [
494
                        'id'     => 1,
495
                        'name'   => 'foo',
496
                        'active' => false
497
                    ],
498
                    [
499
                        'id'     => 2,
500
                        'name'   => 'bar',
501
                        'active' => true
502
                    ]
503
                ]
504
            ],
505
            [
506
                PDO::FETCH_NUM,
507
                [
508
                    [
509
                        0        => 1,
510
                        1        => 'foo',
511
                        2        => false,
512
                    ],
513
                    [
514
                        0        => 2,
515
                        1        => 'bar',
516
                        2        => true,
517
                    ]
518
                ]
519
            ],
520
            [
521
                PDO::FETCH_COLUMN,
522
                [
523
                    1,
524
                    2
525
                ]
526
            ],
527
528
        ];
529
    }
530
531
    /**
532
     * @dataProvider fetchAllStyleProvider
533
     * @covers ::fetchAll
534
     *
535
     * @param string $fetchStyle
536
     * @param array  $expected
537
     */
538
    public function testFetchAll($fetchStyle, array $expected)
539
    {
540
        $this->callbackReturnValue = $this->getPopulatedCollection();
541
542
        $this->pdo
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Crate\PDO\PDO.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
543
            ->expects($this->any())
544
            ->method('getAttribute')
545
            ->with(PDO::ATTR_DEFAULT_FETCH_MODE)
546
            ->will($this->returnValue(PDO::FETCH_BOTH));
547
548
549
        $result = $this->statement->fetchAll($fetchStyle);
550
551
        $this->assertEquals($expected, $result);
552
    }
553
554
    /**
555
     * @covers ::fetchAll
556
     */
557
    public function testFetchAllWithFetchStyleFuncAndInvalidCallback()
558
    {
559
        $this->setExpectedException('Crate\PDO\Exception\InvalidArgumentException');
560
        $this->callbackReturnValue = $this->getPopulatedCollection();
561
562
        $this->statement->fetchAll(PDO::FETCH_FUNC, 'void');
563
    }
564
565
    /**
566
     * @covers ::fetchAll
567
     */
568
    public function testFetchAllBothSameColumnTwice() 
569
    {
570
        $columns = ['id', 'id', 'name'];
571
        $this->callbackReturnValue = new Collection([[1, 1, 'foo']], $columns, 0, 1);
572
        $result = $this->statement->fetchAll(PDO::FETCH_BOTH);
573
574
        $expected = [[0 => 1, 1 => 1, 2 => 'foo', 'id' => 1, 'id' => 1, 'name' => 'foo']];
575
        $this->assertEquals($expected, $result);
576
    }
577
578
579
    /**
580
     * @covers ::fetchAll
581
     */
582
    public function testFetchAllWithFetchStyleFunc()
583
    {
584
        $this->callbackReturnValue = $this->getPopulatedCollection();
585
586
        $result = $this->statement->fetchAll(PDO::FETCH_FUNC, function($id, $name, $active) {
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $active is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
587
            return $id;
588
        });
589
590
        $this->assertEquals([1, 2], $result);
591
    }
592
593
    /**
594
     * @covers ::fetchAll
595
     */
596
    public function testFetchAllWithFetchStyleColumnAndInvalidColumnIndexType()
597
    {
598
        $this->setExpectedException('Crate\PDO\Exception\InvalidArgumentException');
599
        $this->callbackReturnValue = $this->getPopulatedCollection();
600
601
        $this->statement->fetchAll(PDO::FETCH_COLUMN, 'test');
602
    }
603
604
    /**
605
     * @covers ::fetchAll
606
     */
607
    public function testFetchAllWithFetchStyleColumnAndInvalidColumnIndex()
608
    {
609
        $this->setExpectedException('Crate\PDO\Exception\OutOfBoundsException');
610
        $this->callbackReturnValue = $this->getPopulatedCollection();
611
612
        $this->statement->fetchAll(PDO::FETCH_COLUMN, 100);
613
    }
614
615
    /**
616
     * @covers ::fetchObject
617
     */
618
    public function testFetchObject()
619
    {
620
        $this->setExpectedException('Crate\PDO\Exception\UnsupportedException');
621
        $this->statement->fetchObject();
622
    }
623
624
    /**
625
     * @covers ::errorCode
626
     */
627
    public function testErrorCode()
628
    {
629
        $this->assertNull($this->statement->errorCode());
630
631
        $reflection = new ReflectionClass('Crate\PDO\PDOStatement');
632
633
        $property = $reflection->getProperty('errorCode');
634
        $property->setAccessible(true);
635
        $property->setValue($this->statement, 1337);
636
637
        $this->assertEquals(1337, $this->statement->errorCode());
638
    }
639
640
    /**
641
     * @return array
642
     */
643
    public function errorInfoAnsiCodeProvider()
644
    {
645
        return [
646
            [42000, CrateConst::ERR_INVALID_SQL, 'le error message'],
647
            ['Not available', 1337, 'le error message']
648
        ];
649
    }
650
651
    /**
652
     * @covers ::errorInfo
653
     * @dataProvider errorInfoAnsiCodeProvider
654
     *
655
     * @param mixed  $ansiCode
656
     * @param int    $errorCode
657
     * @param string $errorMessage
658
     */
659
    public function testErrorInfo($ansiCode, $errorCode, $errorMessage)
660
    {
661
        $this->assertNull($this->statement->errorInfo());
662
663
        $reflection = new ReflectionClass('Crate\PDO\PDOStatement');
664
665
        $errorCodeProp = $reflection->getProperty('errorCode');
666
        $errorCodeProp->setAccessible(true);
667
        $errorCodeProp->setValue($this->statement, $errorCode);
668
669
        $errorMessageProp = $reflection->getProperty('errorMessage');
670
        $errorMessageProp->setAccessible(true);
671
        $errorMessageProp->setValue($this->statement, $errorMessage);
672
673
        $this->assertEquals([$ansiCode, $errorCode, $errorMessage], $this->statement->errorInfo());
674
    }
675
676
    /**
677
     * @covers ::getAttribute
678
     */
679
    public function testGetAttribute()
680
    {
681
        $this->setExpectedException('Crate\PDO\Exception\UnsupportedException');
682
        $this->statement->getAttribute(null, null);
0 ignored issues
show
Unused Code introduced by
The call to PDOStatement::getAttribute() has too many arguments starting with null.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
683
    }
684
685
    /**
686
     * @covers ::setAttribute
687
     */
688
    public function testSetAttribute()
689
    {
690
        $this->setExpectedException('Crate\PDO\Exception\UnsupportedException');
691
        $this->statement->setAttribute(null, null);
692
    }
693
694
    /**
695
     * @covers ::columnCount
696
     */
697
    public function testColumnCount()
698
    {
699
        $this->callbackReturnValue = $this->getPopulatedCollection();
700
        $this->assertEquals(3, $this->statement->columnCount());
701
    }
702
703
    /**
704
     * @covers ::columnCount
705
     */
706
    public function testColumnCountSameColumnTwice()
707
    {
708
        $data = [
709
            [1, 1],
710
            [2, 2],
711
        ];
712
713
        $this->callbackReturnValue = new Collection($data, ['id', 'id'], 0, 2);
714
        $this->assertEquals(2, $this->statement->columnCount());
715
    }
716
717
    /**
718
     * @covers ::getColumnMeta
719
     */
720
    public function testGetColumnMeta()
721
    {
722
        $this->setExpectedException('Crate\PDO\Exception\UnsupportedException');
723
        $this->statement->getColumnMeta(null);
724
    }
725
726
    /**
727
     * @covers ::setFetchMode
728
     */
729
    public function testSetFetchModeWithColumnAndMissingColNo()
730
    {
731
        $this->setExpectedException(
732
            'Crate\PDO\Exception\InvalidArgumentException',
733
            'fetch mode requires the colno argument'
734
        );
735
736
        $this->statement->setFetchMode(PDO::FETCH_COLUMN);
737
    }
738
739
    /**
740
     * @covers ::setFetchMode
741
     */
742
    public function testSetFetchModeWithColumnAndInvalidColNo()
743
    {
744
        $this->setExpectedException(
745
            'Crate\PDO\Exception\InvalidArgumentException',
746
            'colno must be an integer'
747
        );
748
749
        $this->statement->setFetchMode(PDO::FETCH_COLUMN, 'test');
750
    }
751
752
    /**
753
     * @covers ::setFetchMode
754
     */
755
    public function testSetFetchModeWithColumn()
756
    {
757
        $this->statement->setFetchMode(PDO::FETCH_COLUMN, 1);
758
759
        $reflection = new ReflectionClass('Crate\PDO\PDOStatement');
760
761
        $property = $reflection->getProperty('options');
762
        $property->setAccessible(true);;
763
764
        $options = $property->getValue($this->statement);
765
766
        $this->assertEquals(PDO::FETCH_COLUMN, $options['fetchMode']);
767
        $this->assertEquals(1, $options['fetchColumn']);
768
    }
769
770
    public function fetchModeStyleProvider()
771
    {
772
        return [
773
            [PDO::FETCH_ASSOC],
774
            [PDO::FETCH_NUM],
775
            [PDO::FETCH_BOTH],
776
            [PDO::FETCH_BOUND],
777
            [PDO::FETCH_NAMED]
778
        ];
779
    }
780
781
    /**
782
     * @covers ::setFetchMode
783
     * @dataProvider fetchModeStyleProvider
784
     *
785
     * @param int $fetchStyle
786
     */
787
    public function testSetFetchMode($fetchStyle)
788
    {
789
        $this->statement->setFetchMode($fetchStyle);
790
791
        $reflection = new ReflectionClass('Crate\PDO\PDOStatement');
792
793
        $property = $reflection->getProperty('options');
794
        $property->setAccessible(true);
795
796
        $options = $property->getValue($this->statement);
797
798
        $this->assertEquals($fetchStyle, $options['fetchMode']);
799
    }
800
801
    /**
802
     * @covers ::setFetchMode
803
     */
804
    public function testSetFetchModeWithInvalidFetchStyle()
805
    {
806
        $this->setExpectedException('Crate\PDO\Exception\UnsupportedException');
807
        $this->statement->setFetchMode(PDO::FETCH_INTO);
808
    }
809
810
    /**
811
     * @covers ::setFetchMode
812
     * @dataProvider fetchModeStyleProvider
813
     *
814
     * @param int $fetchStyle
815
     */
816
    public function testSetFetchModeWithInvalidExtraParam($fetchStyle)
817
    {
818
        $this->setExpectedException('Crate\PDO\Exception\InvalidArgumentException');
819
        $this->statement->setFetchMode($fetchStyle, 'fooBar');
820
    }
821
822
    /**
823
     * @covers ::nextRowset
824
     */
825
    public function testNextRowsetWithFailedExecution()
826
    {
827
        $this->callbackReturnValue = ['code' => 1337, 'message' => 'expected failure'];
828
        $this->assertFalse($this->statement->nextRowset());
829
    }
830
831
    /**
832
     * @covers ::nextRowset
833
     */
834
    public function testNextRowset()
835
    {
836
        $this->callbackReturnValue = $this->getPopulatedCollection();
837
838
        $this->assertTrue($this->statement->nextRowset());
839
        $this->assertFalse($this->statement->nextRowset());
840
    }
841
842
    /**
843
     * @covers ::debugDumpParams
844
     */
845
    public function testDumpDebugParams()
846
    {
847
        $this->setExpectedException('Crate\PDO\Exception\PDOException');
848
        $this->statement->debugDumpParams();
849
    }
850
851
    /**
852
     * @covers ::getIterator
853
     */
854
    public function testGetIterator()
855
    {
856
        $this->callbackReturnValue = $this->getPopulatedCollection();
857
        $this->statement->setFetchMode(PDO::FETCH_COLUMN, 0);
858
859
        $counter = 0;
860
861
        foreach ($this->statement->getIterator() as $id) {
862
            $this->assertEquals(++$counter, $id);
863
        }
864
865
        $this->assertEquals(2, $counter);
866
    }
867
868
    /**
869
     * @covers ::closeCursor
870
     */
871
    public function testCloseCursorReturnsTrue()
872
    {
873
        $this->assertTrue($this->statement->closeCursor());
874
    }
875
876
    /**
877
     * @covers ::typedValue
878
     */
879
    public function testTypedValue()
880
    {
881
        $method = new ReflectionMethod('Crate\PDO\PDOStatement', 'typedValue');
882
        $method->setAccessible(true);
883
884
        $this->assertEquals(1.23, $method->invoke($this->statement, 1.23, PDO::PARAM_FLOAT));
885
        $this->assertEquals(1.23, $method->invoke($this->statement, 1.23, PDO::PARAM_DOUBLE));
886
887
        $this->assertEquals(1, $method->invoke($this->statement, 1, PDO::PARAM_INT));
888
        $this->assertEquals(1, $method->invoke($this->statement, 1, PDO::PARAM_LONG));
889
890
        $this->assertEquals(null, $method->invoke($this->statement, 1, PDO::PARAM_NULL));
891
892
        $this->assertEquals("hello", $method->invoke($this->statement, "hello", PDO::PARAM_STR));
893
        $this->assertEquals("1234", $method->invoke($this->statement, 1234, PDO::PARAM_STR));
894
        $this->assertEquals("127.0.0.1", $method->invoke($this->statement, "127.0.0.1", PDO::PARAM_IP));
895
896
        $this->assertEquals([1, 2], $method->invoke($this->statement, [1, 2], PDO::PARAM_ARRAY));
897
        $this->assertEquals(["foo" =>  "bar"], $method->invoke($this->statement, ["foo" =>  "bar"], PDO::PARAM_ARRAY));
898
899
        $this->assertEquals(12345, $method->invoke($this->statement, 12345, PDO::PARAM_TIMESTAMP));
900
        $this->assertEquals(12345, $method->invoke($this->statement, "12345", PDO::PARAM_TIMESTAMP));
901
        $this->assertEquals("2014-03-04T18:45:20", $method->invoke($this->statement, "2014-03-04T18:45:20", PDO::PARAM_TIMESTAMP));
902
903
    }
904
905
    /**
906
     * @covers ::typedValue
907
     */
908
    public function testTypedValueInvalid()
909
    {
910
        $method = new ReflectionMethod('Crate\PDO\PDOStatement', 'typedValue');
911
        $method->setAccessible(true);
912
913
        $this->setExpectedException('Crate\PDO\Exception\PDOException');
914
        $method->invoke($this->statement, 1, PDO::PARAM_LOB);
915
    }
916
917
    /**
918
     * @covers ::replaceNamedParametersWithPositionals
919
     */
920
    public function testReplaceNamedParametersWithPositionals()
921
    {
922
        $method = new ReflectionMethod('Crate\PDO\PDOStatement', 'replaceNamedParametersWithPositionals');
923
        $method->setAccessible(true);
924
        $property = new ReflectionProperty('Crate\PDO\PDOStatement', 'namedToPositionalMap');
925
        $property->setAccessible(true);
926
927
        $sql = "select * from test_table where name = :name and hoschi = 'sld''fn:sdfsf' and id = :id";
928
        $sql_converted = $method->invoke($this->statement, $sql);
929
        $this->assertEquals("select * from test_table where name = ? and hoschi = 'sld''fn:sdfsf' and id = ?", $sql_converted);
930
        $nameToPositionalMap = $property->getValue($this->statement);
931
        $this->assertEquals("name", $nameToPositionalMap[1]);
932
        $this->assertEquals("id", $nameToPositionalMap[2]);
933
    }
934
    
935
    public function testReplaceNamedParametersWithPositionalsMultiple()
936
    {
937
        $method = new ReflectionMethod('Crate\PDO\PDOStatement', 'replaceNamedParametersWithPositionals');
938
        $method->setAccessible(true);
939
        $property = new ReflectionProperty('Crate\PDO\PDOStatement', 'namedToPositionalMap');
940
        $property->setAccessible(true);
941
942
        $sql = "update test_table set name = concat(name, :name) where id = :id and name != :name";
943
        $sql_converted = $method->invoke($this->statement, $sql);
944
        $this->assertEquals("update test_table set name = concat(name, ?) where id = ? and name != ?", $sql_converted);
945
        $nameToPositionalMap = $property->getValue($this->statement);
946
        $this->assertEquals("name", $nameToPositionalMap[1]);
947
        $this->assertEquals("id", $nameToPositionalMap[2]);
948
        $this->assertEquals("name", $nameToPositionalMap[3]);
949
    }
950
    
951
}
952
953