Completed
Push — master ( f7cf81...0d805c )
by Jacob
02:47
created

PhpQuickProfilerTest::testGatherQueryData()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 27
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 27
rs 8.8571
cc 3
eloc 21
nc 4
nop 0
1
<?php
2
3
namespace Particletree\Pqp;
4
5
use PDO;
6
use PHPUnit_Framework_Testcase;
7
use ReflectionClass;
8
use ReflectionMethod;
9
10
class PhpQuickProfilerTest extends PHPUnit_Framework_TestCase
11
{
12
13
    protected static $dbConnection;
14
15
    public static function setUpBeforeClass()
16
    {
17
        self::$dbConnection = new PDO('sqlite::memory:');
18
        $createTable = "
19
            CREATE TABLE IF NOT EXISTS `testing` (
20
                `id` integer PRIMARY KEY AUTOINCREMENT,
21
                `title` varchar(60) NOT NULL
22
            );";
23
        self::$dbConnection->exec($createTable);
24
25
        $hydrateTable = "
26
            INSERT INTO `testing`
27
                (`title`)
28
            VALUES
29
                ('alpha'),
30
                ('beta'),
31
                ('charlie'),
32
                ('delta');";
33
        self::$dbConnection->exec($hydrateTable);
34
    }
35
36
    public function testConstruct()
37
    {
38
        $startTime = microtime(true);
39
40
        $profiler = new PhpQuickProfiler();
41
        $this->assertAttributeEquals($startTime, 'startTime', $profiler);
42
43
        $profiler = new PhpQuickProfiler($startTime);
44
        $this->assertAttributeEquals($startTime, 'startTime', $profiler);
45
    }
46
47
    public function testSetConsole()
48
    {
49
        $console = new Console();
50
        $profiler = new PhpQuickProfiler();
51
        $profiler->setConsole($console);
52
53
        $this->assertAttributeSame($console, 'console', $profiler);
54
    }
55
56
    public function testSetDisplay()
57
    {
58
        $display = new Display();
59
        $profiler = new PhpQuickProfiler();
60
        $profiler->setDisplay($display);
61
62
        $this->assertAttributeSame($display, 'display', $profiler);
63
    }
64
65
    public function testGatherFileData()
66
    {
67
        $files = get_included_files();
68
        $profiler = new PhpQuickProfiler();
69
        $gatheredFileData = $profiler->gatherFileData();
70
71
        $this->assertInternalType('array', $gatheredFileData);
72
        $this->assertEquals(count($files), count($gatheredFileData));
73
        foreach ($gatheredFileData as $fileData) {
74
            $this->assertInternalType('array', $fileData);
75
            $this->assertArrayHasKey('name', $fileData);
76
            $this->assertContains($fileData['name'], $files);
77
            $this->assertArrayHasKey('size', $fileData);
78
            $this->assertEquals($fileData['size'], filesize($fileData['name']));
79
        }
80
    }
81
82
    public function testGatherMemoryData()
83
    {
84
        $memoryUsage = memory_get_peak_usage();
85
        $allowedLimit = ini_get('memory_limit');
86
        $profiler = new PhpQuickProfiler();
87
        $gatheredMemoryData = $profiler->gatherMemoryData();
88
89
        $this->assertInternalType('array', $gatheredMemoryData);
90
        $this->assertEquals(2, count($gatheredMemoryData));
91
        $this->assertArrayHasKey('used', $gatheredMemoryData);
92
        $this->assertEquals($memoryUsage, $gatheredMemoryData['used']);
93
        $this->assertArrayHasKey('allowed', $gatheredMemoryData);
94
        $this->assertEquals($allowedLimit, $gatheredMemoryData['allowed']);
95
    }
96
97
    public function testSetProfiledQueries()
98
    {
99
        $profiledQueries = $this->dataProfiledQueries();
100
        $profiler = new PhpQuickProfiler();
101
        $profiler->setProfiledQueries($profiledQueries);
102
103
        $this->assertAttributeEquals($profiledQueries, 'profiledQueries', $profiler);
104
    }
105
106
    public function testGatherQueryData()
107
    {
108
        $profiledQueries = $this->dataProfiledQueries();
109
        $profiledQueriesSql = array();
110
        $profiledQueriesTime = array();
111
        foreach ($profiledQueries as $queryData) {
112
            array_push($profiledQueriesSql, $queryData['sql']);
113
            array_push($profiledQueriesTime, $queryData['time']);
114
        }
115
116
        $profiler = new PhpQuickProfiler();
117
        $profiler->setProfiledQueries($profiledQueries);
118
        $gatheredQueryData = $profiler->gatherQueryData(self::$dbConnection);
0 ignored issues
show
Bug introduced by
It seems like self::$dbConnection can be null; however, gatherQueryData() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
119
120
        $this->assertInternalType('array', $gatheredQueryData);
121
        $this->assertEquals(count($profiledQueries), count($gatheredQueryData));
122
        foreach ($gatheredQueryData as $queryData) {
123
            $this->assertInternalType('array', $queryData);
124
            $this->assertArrayHasKey('sql', $queryData);
125
            $this->assertContains($queryData['sql'], $profiledQueriesSql);
126
            $this->assertArrayHasKey('explain', $queryData);
127
            $this->assertInternaltype('array', $queryData['explain']);
128
            $this->assertGreaterThan(0, count($queryData['explain']));
129
            $this->assertArrayHasKey('time', $queryData);
130
            $this->assertContains($queryData['time'], $profiledQueriesTime);
131
        }
132
    }
133
134
    /**
135
     * @dataProvider dataProfiledQueries
136
     */
137
    public function testExplainQuery($sql, $parameters)
138
    {
139
        $profiler = new PhpQuickProfiler();
140
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'explainQuery');
141
142
        $explainedQuery = $reflectedMethod->invokeArgs(
143
            $profiler,
144
            array(self::$dbConnection, $sql, $parameters)
145
        );
146
        $this->assertInternalType('array', $explainedQuery);
147
        $this->assertGreaterThan(0, count($explainedQuery));
148
    }
149
150
    /**
151
     * @expectedException Exception
152
     */
153
    public function testExplainQueryBadQueryException()
154
    {
155
        $invalidQuery = 'SELECT * FROM `fake_table`';
156
        $profiler = new PhpQuickProfiler();
157
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'explainQuery');
158
159
        $reflectedMethod->invokeArgs(
160
            $profiler,
161
            array(self::$dbConnection, $invalidQuery)
162
        );
163
    }
164
165
    /**
166
     * @expectedException Exception
167
     */
168 View Code Duplication
    public function testExplainQueryBadParametersException()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
    {
170
        $query = 'SELECT * FROM `testing` WHERE `title` = :title';
171
        $invalidParams = array('id' => 1);
172
        $profiler = new PhpQuickProfiler();
173
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'explainQuery');
174
175
        $reflectedMethod->invokeArgs(
176
            $profiler,
177
            array(self::$dbConnection, $query, $invalidParams)
178
        );
179
    }
180
181
    /**
182
     * @dataProvider dataConnectionDrivers
183
     */
184
    public function testGetExplainQuery($driver, $prefix)
185
    {
186
        $query = 'SELECT * FROM `testing`';
187
        $profiler = new PhpQuickProfiler();
188
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'getExplainQuery');
189
190
        $explainQuery = $reflectedMethod->invokeArgs(
191
            $profiler,
192
            array($query, $driver)
193
        );
194
195
        $explainPrefix = str_replace($query, '', $explainQuery);
196
        $explainPrefix = trim($explainPrefix);
197
        $this->assertEquals($prefix, $explainPrefix);
198
    }
199
200
    /**
201
     * @expectedException Exception
202
     */
203 View Code Duplication
    public function testGetExplainQueryUnsupportedDriver()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
204
    {
205
        $query = 'SELECT * FROM `testing`';
206
        $unsupportedDriver = 'zz';
207
        $profiler = new PhpQuickProfiler();
208
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'getExplainQuery');
209
210
        $reflectedMethod->invokeArgs(
211
            $profiler,
212
            array($query, $unsupportedDriver)
213
        );
214
    }
215
216
    public function testGatherSpeedData()
217
    {
218
        $elapsedTime = 1.234;
219
        $startTime = microtime(true) - $elapsedTime;
220
        $allowedTime = ini_get('max_execution_time');
221
        $profiler = new PhpQuickProfiler($startTime);
222
        $gatheredSpeedData = $profiler->gatherSpeedData();
223
224
        $this->assertInternalType('array', $gatheredSpeedData);
225
        $this->assertEquals(2, count($gatheredSpeedData));
226
        $this->assertArrayHasKey('elapsed', $gatheredSpeedData);
227
        $this->assertEquals($elapsedTime, $gatheredSpeedData['elapsed']);
228
        $this->assertArrayHasKey('allowed', $gatheredSpeedData);
229
        $this->assertEquals($allowedTime, $gatheredSpeedData['allowed']);
230
    }
231
232
    public function dataProfiledQueries()
233
    {
234
        return array(
235
            array(
236
              'sql' => "SELECT * FROM testing",
237
              'parameters' => array(),
238
              'time' => 25
239
            ),
240
            array(
241
              'sql' => "SELECT id FROM testing WHERE title = :title",
242
              'parameters' => array('title' => 'beta'),
243
              'time' => 5
244
            )
245
        );
246
    }
247
248
    public function dataConnectionDrivers()
249
    {
250
        return array(
251
            array(
252
                'driver' => 'mysql',
253
                'prefix' => 'EXPLAIN'
254
            ),
255
            array(
256
                'driver' => 'sqlite',
257
                'prefix' => 'EXPLAIN QUERY PLAN'
258
            )
259
        );
260
    }
261
262
    protected function getAccessibleMethod(PhpQuickProfiler $profiler, $methodName)
263
    {
264
        $reflectedConsole = new ReflectionClass(get_class($profiler));
265
        $reflectedMethod = $reflectedConsole->getMethod($methodName);
266
        $reflectedMethod->setAccessible(true);
267
        return $reflectedMethod;
268
    }
269
270
    public static function tearDownAfterClass()
271
    {
272
        self::$dbConnection = null;
273
    }
274
}
275