1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Base sniff test class file |
4
|
|
|
* |
5
|
|
|
* @package PHPCompatibility |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* BaseSniffTest |
10
|
|
|
* |
11
|
|
|
* Adds PHPCS sniffing logic and custom assertions for PHPCS errors and |
12
|
|
|
* warnings |
13
|
|
|
* |
14
|
|
|
* @uses PHPUnit_Framework_TestCase |
15
|
|
|
* @package PHPCompatibility |
16
|
|
|
* @author Jansen Price <[email protected]> |
17
|
|
|
*/ |
18
|
|
|
class BaseSniffTest extends PHPUnit_Framework_TestCase |
19
|
|
|
{ |
20
|
|
|
/** |
21
|
|
|
* The PHP_CodeSniffer object used for testing. |
22
|
|
|
* |
23
|
|
|
* @var PHP_CodeSniffer |
24
|
|
|
*/ |
25
|
|
|
protected static $phpcs = null; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Sets up this unit test. |
29
|
|
|
* |
30
|
|
|
* @return void |
31
|
|
|
*/ |
32
|
|
|
protected function setUp() |
33
|
|
|
{ |
34
|
|
|
if (self::$phpcs === null) { |
35
|
|
|
self::$phpcs = new PHP_CodeSniffer(); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
PHP_CodeSniffer::setConfigData('testVersion', null, true); |
39
|
|
|
if (method_exists('PHP_CodeSniffer_CLI', 'setCommandLineValues')) { // For PHPCS 2.x |
40
|
|
|
self::$phpcs->cli->setCommandLineValues(array('-p', '--colors')); |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
self::$phpcs->process(array(), __DIR__ . '/../'); |
44
|
|
|
self::$phpcs->setIgnorePatterns(array()); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* Tear down after each test |
49
|
|
|
* |
50
|
|
|
* @return void |
51
|
|
|
*/ |
52
|
|
|
public function tearDown() |
53
|
|
|
{ |
54
|
|
|
// Reset any settingsStandard (targetPhpVersion) |
55
|
|
|
self::$phpcs->cli->settingsStandard = array(); |
|
|
|
|
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Sniff a file and return resulting file object |
60
|
|
|
* |
61
|
|
|
* @param string $filename Filename to sniff |
62
|
|
|
* @param string $targetPhpVersion Value of 'testVersion' to set on PHPCS object |
63
|
|
|
* @return PHP_CodeSniffer_File File object |
64
|
|
|
*/ |
65
|
|
|
public function sniffFile($filename, $targetPhpVersion = null) |
66
|
|
|
{ |
67
|
|
|
if (null !== $targetPhpVersion) { |
68
|
|
|
PHP_CodeSniffer::setConfigData('testVersion', $targetPhpVersion, true); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
$filename = realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR . $filename; |
72
|
|
|
try { |
73
|
|
|
$phpcsFile = self::$phpcs->processFile($filename); |
74
|
|
|
} catch (Exception $e) { |
75
|
|
|
$this->fail('An unexpected exception has been caught: ' . $e->getMessage()); |
76
|
|
|
return false; |
|
|
|
|
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
return $phpcsFile; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Assert a PHPCS error on a particular line number |
84
|
|
|
* |
85
|
|
|
* @param PHP_CodeSniffer_File $file Codesniffer file object |
86
|
|
|
* @param int $lineNumber Line number |
87
|
|
|
* @param string $expectedMessage Expected error message (assertContains) |
88
|
|
|
* @return bool |
89
|
|
|
*/ |
90
|
|
|
public function assertError(PHP_CodeSniffer_File $file, $lineNumber, $expectedMessage) |
91
|
|
|
{ |
92
|
|
|
$errors = $this->gatherErrors($file); |
93
|
|
|
|
94
|
|
|
return $this->assertForType($errors, 'error', $lineNumber, $expectedMessage); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Assert a PHPCS warning on a particular line number |
99
|
|
|
* |
100
|
|
|
* @param PHP_CodeSniffer_File $file Codesniffer file object |
101
|
|
|
* @param int $lineNumber Line number |
102
|
|
|
* @param string $expectedMessage Expected message (assertContains) |
103
|
|
|
* @return bool |
104
|
|
|
*/ |
105
|
|
|
public function assertWarning(PHP_CodeSniffer_File $file, $lineNumber, $expectedMessage) |
106
|
|
|
{ |
107
|
|
|
$warnings = $this->gatherWarnings($file); |
108
|
|
|
|
109
|
|
|
return $this->assertForType($warnings, 'warning', $lineNumber, $expectedMessage); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* Assert a PHPCS error or warning on a particular line number. |
114
|
|
|
* |
115
|
|
|
* @param array $issues Array of issues of a particular type. |
116
|
|
|
* @param string $type The type of issues, either 'error' or 'warning'. |
117
|
|
|
* @param int $lineNumber Line number. |
118
|
|
|
* @param string $expectedMessage Expected message (assertContains). |
119
|
|
|
* @return bool |
120
|
|
|
*/ |
121
|
|
|
private function assertForType($issues, $type, $lineNumber, $expectedMessage) |
122
|
|
|
{ |
123
|
|
|
if (!isset($issues[$lineNumber])) { |
124
|
|
|
throw new Exception("Expected $type '$expectedMessage' on line number $lineNumber, but none found."); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
$insteadFoundMessages = array(); |
128
|
|
|
|
129
|
|
|
// Concat any error messages so we can do an assertContains |
130
|
|
|
foreach ($issues[$lineNumber] as $issue) { |
131
|
|
|
$insteadFoundMessages[] = $issue['message']; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
$insteadMessagesString = implode(', ', $insteadFoundMessages); |
135
|
|
|
return $this->assertContains( |
136
|
|
|
$expectedMessage, $insteadMessagesString, |
137
|
|
|
"Expected $type message '$expectedMessage' on line $lineNumber not found. Instead found: $insteadMessagesString." |
138
|
|
|
); |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Assert no violation (warning or error) on a given line number |
143
|
|
|
* |
144
|
|
|
* @param PHP_CodeSniffer_File $file Codesniffer File object |
145
|
|
|
* @param mixed $lineNumber Line number |
146
|
|
|
* @return bool |
147
|
|
|
*/ |
148
|
|
|
public function assertNoViolation(PHP_CodeSniffer_File $file, $lineNumber = 0) |
149
|
|
|
{ |
150
|
|
|
$errors = $this->gatherErrors($file); |
151
|
|
|
$warnings = $this->gatherWarnings($file); |
152
|
|
|
|
153
|
|
|
if (!count($errors) && !count($warnings)) { |
154
|
|
|
return $this->assertTrue(true); |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
if ($lineNumber == 0) { |
158
|
|
|
$allMessages = $errors + $warnings; |
159
|
|
|
// TODO: Update the fail message to give the tester some |
160
|
|
|
// indication of what the errors or warnings were |
161
|
|
|
return $this->assertEmpty($allMessages, 'Failed asserting no violations in file'); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
$encounteredMessages = array(); |
165
|
|
|
if (isset($errors[$lineNumber])) { |
166
|
|
|
foreach ($errors[$lineNumber] as $error) { |
167
|
|
|
$encounteredMessages[] = 'ERROR: ' . $error['message']; |
168
|
|
|
} |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
if (isset($warnings[$lineNumber])) { |
172
|
|
|
foreach ($warnings[$lineNumber] as $warning) { |
173
|
|
|
$encounteredMessages[] = 'WARNING: ' . $warning['message']; |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
if (!count($encounteredMessages)) { |
178
|
|
|
return $this->assertTrue(true); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
$failMessage = "Failed asserting no standards violation on line $lineNumber: " |
182
|
|
|
. implode(', ', $encounteredMessages); |
183
|
|
|
|
184
|
|
|
$this->assertEmpty($encounteredMessages, $failMessage); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Show violations in file by line number |
189
|
|
|
* |
190
|
|
|
* This is useful for debugging sniffs on a file |
191
|
|
|
* |
192
|
|
|
* @param PHP_CodeSniffer_File $file Codesniffer file object |
193
|
|
|
* @return void |
194
|
|
|
*/ |
195
|
|
|
public function showViolations(PHP_CodeSniffer_File $file) |
196
|
|
|
{ |
197
|
|
|
$violations = array( |
198
|
|
|
'errors' => $this->gatherErrors($file), |
199
|
|
|
'warnings' => $this->gatherWarnings($file), |
200
|
|
|
); |
201
|
|
|
|
202
|
|
|
return $violations; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* Gather all error messages by line number from phpcs file result |
207
|
|
|
* |
208
|
|
|
* @param PHP_CodeSniffer_File $file Codesniffer File object |
209
|
|
|
* @return array |
210
|
|
|
*/ |
211
|
|
|
public function gatherErrors(PHP_CodeSniffer_File $file) |
212
|
|
|
{ |
213
|
|
|
$foundErrors = $file->getErrors(); |
214
|
|
|
|
215
|
|
|
return $this->gatherIssues($foundErrors); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Gather all warning messages by line number from phpcs file result |
220
|
|
|
* |
221
|
|
|
* @param PHP_CodeSniffer_File $file Codesniffer File object |
222
|
|
|
* @return array |
223
|
|
|
*/ |
224
|
|
|
public function gatherWarnings(PHP_CodeSniffer_File $file) |
225
|
|
|
{ |
226
|
|
|
$foundWarnings = $file->getWarnings(); |
227
|
|
|
|
228
|
|
|
return $this->gatherIssues($foundWarnings); |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Gather all messages or a particular type by line number. |
233
|
|
|
* |
234
|
|
|
* @param array $IssuesArray Array of a particular type of issues, |
|
|
|
|
235
|
|
|
* i.e. errors or warnings. |
236
|
|
|
* @return array |
237
|
|
|
*/ |
238
|
|
|
private function gatherIssues($issuesArray) |
239
|
|
|
{ |
240
|
|
|
$allIssues = array(); |
241
|
|
|
foreach ($issuesArray as $line => $lineIssues) { |
242
|
|
|
foreach ($lineIssues as $column => $issues) { |
243
|
|
|
foreach ($issues as $issue) { |
244
|
|
|
|
245
|
|
|
if (!isset($allIssues[$line])) { |
246
|
|
|
$allIssues[$line] = array(); |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
$allIssues[$line][] = $issue; |
250
|
|
|
} |
251
|
|
|
} |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
return $allIssues; |
255
|
|
|
} |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.