Completed
Push — master ( 0d805c...d019cb )
by Jacob
02:09
created

testGatherQueryDataInternalProfiler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 10
rs 9.4286
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
3
namespace Particletree\Pqp;
4
5
use PHPUnit_Framework_Testcase;
6
use ReflectionClass;
7
use ReflectionMethod;
8
9
class PhpQuickProfilerTest extends PHPUnit_Framework_TestCase
10
{
11
12
    protected static $dbConnection;
13
14
    public static function setUpBeforeClass()
15
    {
16
        self::$dbConnection = new LoggingPdo('sqlite::memory:');
17
        $createTable = "
18
            CREATE TABLE IF NOT EXISTS `testing` (
19
                `id` integer PRIMARY KEY AUTOINCREMENT,
20
                `title` varchar(60) NOT NULL
21
            );";
22
        self::$dbConnection->exec($createTable);
23
24
        $hydrateTable = "
25
            INSERT INTO `testing`
26
                (`title`)
27
            VALUES
28
                ('alpha'),
29
                ('beta'),
30
                ('charlie'),
31
                ('delta');";
32
        self::$dbConnection->exec($hydrateTable);
33
    }
34
35
    public function testConstruct()
36
    {
37
        $startTime = microtime(true);
38
39
        $profiler = new PhpQuickProfiler();
40
        $this->assertAttributeEquals($startTime, 'startTime', $profiler);
41
42
        $profiler = new PhpQuickProfiler($startTime);
43
        $this->assertAttributeEquals($startTime, 'startTime', $profiler);
44
    }
45
46
    public function testSetConsole()
47
    {
48
        $console = new Console();
49
        $profiler = new PhpQuickProfiler();
50
        $profiler->setConsole($console);
51
52
        $this->assertAttributeSame($console, 'console', $profiler);
53
    }
54
55
    public function testSetDisplay()
56
    {
57
        $display = new Display();
58
        $profiler = new PhpQuickProfiler();
59
        $profiler->setDisplay($display);
60
61
        $this->assertAttributeSame($display, 'display', $profiler);
62
    }
63
64
    public function testGatherFileData()
65
    {
66
        $files = get_included_files();
67
        $profiler = new PhpQuickProfiler();
68
        $gatheredFileData = $profiler->gatherFileData();
69
70
        $this->assertInternalType('array', $gatheredFileData);
71
        $this->assertEquals(count($files), count($gatheredFileData));
72
        foreach ($gatheredFileData as $fileData) {
73
            $this->assertInternalType('array', $fileData);
74
            $this->assertArrayHasKey('name', $fileData);
75
            $this->assertContains($fileData['name'], $files);
76
            $this->assertArrayHasKey('size', $fileData);
77
            $this->assertEquals($fileData['size'], filesize($fileData['name']));
78
        }
79
    }
80
81
    public function testGatherMemoryData()
82
    {
83
        $memoryUsage = memory_get_peak_usage();
84
        $allowedLimit = ini_get('memory_limit');
85
        $profiler = new PhpQuickProfiler();
86
        $gatheredMemoryData = $profiler->gatherMemoryData();
87
88
        $this->assertInternalType('array', $gatheredMemoryData);
89
        $this->assertEquals(2, count($gatheredMemoryData));
90
        $this->assertArrayHasKey('used', $gatheredMemoryData);
91
        $this->assertEquals($memoryUsage, $gatheredMemoryData['used']);
92
        $this->assertArrayHasKey('allowed', $gatheredMemoryData);
93
        $this->assertEquals($allowedLimit, $gatheredMemoryData['allowed']);
94
    }
95
96
    public function testSetProfiledQueries()
97
    {
98
        $profiledQueries = $this->dataProfiledQueries();
99
        $profiler = new PhpQuickProfiler();
100
        $profiler->setProfiledQueries($profiledQueries);
101
102
        $this->assertAttributeEquals($profiledQueries, 'profiledQueries', $profiler);
103
    }
104
105
    public function testGatherQueryData()
106
    {
107
        $profiledQueries = $this->dataProfiledQueries();
108
        $profiledQueriesSql = array();
109
        $profiledQueriesTime = array();
110
        foreach ($profiledQueries as $queryData) {
111
            array_push($profiledQueriesSql, $queryData['sql']);
112
            array_push($profiledQueriesTime, $queryData['time']);
113
        }
114
115
        $profiler = new PhpQuickProfiler();
116
        $profiler->setProfiledQueries($profiledQueries);
117
        $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...
118
119
        $this->assertInternalType('array', $gatheredQueryData);
120
        $this->assertEquals(count($profiledQueries), count($gatheredQueryData));
121
        foreach ($gatheredQueryData as $queryData) {
122
            $this->assertInternalType('array', $queryData);
123
            $this->assertArrayHasKey('sql', $queryData);
124
            $this->assertContains($queryData['sql'], $profiledQueriesSql);
125
            $this->assertArrayHasKey('explain', $queryData);
126
            $this->assertInternaltype('array', $queryData['explain']);
127
            $this->assertGreaterThan(0, count($queryData['explain']));
128
            $this->assertArrayHasKey('time', $queryData);
129
            $this->assertContains($queryData['time'], $profiledQueriesTime);
130
        }
131
    }
132
133
    public function testGatherQueryDataInternalProfiler()
134
    {
135
        $profiledQueries = $this->dataProfiledQueries();
136
        $dbConnection = self::$dbConnection;
137
        $dbConnection->queries = $profiledQueries;
138
        $profiler = new PhpQuickProfiler();
139
        $profiler->gatherQueryData($dbConnection);
140
141
        $this->assertAttributeSame($profiledQueries, 'profiledQueries', $profiler);
142
    }
143
144
    /**
145
     * @dataProvider dataProfiledQueries
146
     */
147
    public function testExplainQuery($sql, $parameters)
148
    {
149
        $profiler = new PhpQuickProfiler();
150
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'explainQuery');
151
152
        $explainedQuery = $reflectedMethod->invokeArgs(
153
            $profiler,
154
            array(self::$dbConnection, $sql, $parameters)
155
        );
156
        $this->assertInternalType('array', $explainedQuery);
157
        $this->assertGreaterThan(0, count($explainedQuery));
158
    }
159
160
    /**
161
     * @expectedException Exception
162
     */
163
    public function testExplainQueryBadQueryException()
164
    {
165
        $invalidQuery = 'SELECT * FROM `fake_table`';
166
        $profiler = new PhpQuickProfiler();
167
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'explainQuery');
168
169
        $reflectedMethod->invokeArgs(
170
            $profiler,
171
            array(self::$dbConnection, $invalidQuery)
172
        );
173
    }
174
175
    /**
176
     * @expectedException Exception
177
     */
178 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...
179
    {
180
        $query = 'SELECT * FROM `testing` WHERE `title` = :title';
181
        $invalidParams = array('id' => 1);
182
        $profiler = new PhpQuickProfiler();
183
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'explainQuery');
184
185
        $reflectedMethod->invokeArgs(
186
            $profiler,
187
            array(self::$dbConnection, $query, $invalidParams)
188
        );
189
    }
190
191
    /**
192
     * @dataProvider dataConnectionDrivers
193
     */
194
    public function testGetExplainQuery($driver, $prefix)
195
    {
196
        $query = 'SELECT * FROM `testing`';
197
        $profiler = new PhpQuickProfiler();
198
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'getExplainQuery');
199
200
        $explainQuery = $reflectedMethod->invokeArgs(
201
            $profiler,
202
            array($query, $driver)
203
        );
204
205
        $explainPrefix = str_replace($query, '', $explainQuery);
206
        $explainPrefix = trim($explainPrefix);
207
        $this->assertEquals($prefix, $explainPrefix);
208
    }
209
210
    /**
211
     * @expectedException Exception
212
     */
213 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...
214
    {
215
        $query = 'SELECT * FROM `testing`';
216
        $unsupportedDriver = 'zz';
217
        $profiler = new PhpQuickProfiler();
218
        $reflectedMethod = $this->getAccessibleMethod($profiler, 'getExplainQuery');
219
220
        $reflectedMethod->invokeArgs(
221
            $profiler,
222
            array($query, $unsupportedDriver)
223
        );
224
    }
225
226
    public function testGatherSpeedData()
227
    {
228
        $elapsedTime = 1.234;
229
        $startTime = microtime(true) - $elapsedTime;
230
        $allowedTime = ini_get('max_execution_time');
231
        $profiler = new PhpQuickProfiler($startTime);
232
        $gatheredSpeedData = $profiler->gatherSpeedData();
233
234
        $this->assertInternalType('array', $gatheredSpeedData);
235
        $this->assertEquals(2, count($gatheredSpeedData));
236
        $this->assertArrayHasKey('elapsed', $gatheredSpeedData);
237
        $this->assertEquals($elapsedTime, $gatheredSpeedData['elapsed']);
238
        $this->assertArrayHasKey('allowed', $gatheredSpeedData);
239
        $this->assertEquals($allowedTime, $gatheredSpeedData['allowed']);
240
    }
241
242
    public function dataProfiledQueries()
243
    {
244
        return array(
245
            array(
246
              'sql' => "SELECT * FROM testing",
247
              'parameters' => array(),
248
              'time' => 25
249
            ),
250
            array(
251
              'sql' => "SELECT id FROM testing WHERE title = :title",
252
              'parameters' => array('title' => 'beta'),
253
              'time' => 5
254
            )
255
        );
256
    }
257
258
    public function dataConnectionDrivers()
259
    {
260
        return array(
261
            array(
262
                'driver' => 'mysql',
263
                'prefix' => 'EXPLAIN'
264
            ),
265
            array(
266
                'driver' => 'sqlite',
267
                'prefix' => 'EXPLAIN QUERY PLAN'
268
            )
269
        );
270
    }
271
272
    protected function getAccessibleMethod(PhpQuickProfiler $profiler, $methodName)
273
    {
274
        $reflectedConsole = new ReflectionClass(get_class($profiler));
275
        $reflectedMethod = $reflectedConsole->getMethod($methodName);
276
        $reflectedMethod->setAccessible(true);
277
        return $reflectedMethod;
278
    }
279
280
    public static function tearDownAfterClass()
281
    {
282
        self::$dbConnection = null;
283
    }
284
}
285