1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of PHP Mess Detector. |
4
|
|
|
* |
5
|
|
|
* Copyright (c) Manuel Pichler <[email protected]>. |
6
|
|
|
* All rights reserved. |
7
|
|
|
* |
8
|
|
|
* Licensed under BSD License |
9
|
|
|
* For full copyright and license information, please see the LICENSE file. |
10
|
|
|
* Redistributions of files must retain the above copyright notice. |
11
|
|
|
* |
12
|
|
|
* @author Manuel Pichler <[email protected]> |
13
|
|
|
* @copyright Manuel Pichler. All rights reserved. |
14
|
|
|
* @license https://opensource.org/licenses/bsd-license.php BSD License |
15
|
|
|
* @link http://phpmd.org/ |
16
|
|
|
*/ |
17
|
|
|
|
18
|
|
|
namespace PHPMD\TextUI; |
19
|
|
|
|
20
|
|
|
use PHPMD\AbstractTest; |
21
|
|
|
use PHPMD\Rule; |
22
|
|
|
use PHPMD\TextUI\StreamFilter; |
23
|
|
|
use PHPMD\Test\Renderer\NamespaceRenderer; |
24
|
|
|
use PHPMD\Renderer\TextRenderer; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* Test case for the {@link \PHPMD\TextUI\CommandLineOptions} class. |
28
|
|
|
* |
29
|
|
|
* @covers \PHPMD\TextUI\CommandLineOptions |
30
|
|
|
*/ |
31
|
|
|
class CommandLineOptionsTest extends AbstractTest |
32
|
|
|
{ |
33
|
|
|
/** |
34
|
|
|
* @var resource |
35
|
|
|
*/ |
36
|
|
|
private $stderrStreamFilter; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @return void |
40
|
|
|
*/ |
41
|
|
View Code Duplication |
protected function tearDown() |
|
|
|
|
42
|
|
|
{ |
43
|
|
|
if (is_resource($this->stderrStreamFilter)) { |
44
|
|
|
stream_filter_remove($this->stderrStreamFilter); |
45
|
|
|
} |
46
|
|
|
$this->stderrStreamFilter = null; |
47
|
|
|
|
48
|
|
|
parent::tearDown(); |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* testAssignsInputArgumentToInputProperty |
53
|
|
|
* |
54
|
|
|
* @return void |
55
|
|
|
* @since 1.1.0 |
56
|
|
|
*/ |
57
|
|
View Code Duplication |
public function testAssignsInputArgumentToInputProperty() |
|
|
|
|
58
|
|
|
{ |
59
|
|
|
$args = array('foo.php', __FILE__, 'text', 'design'); |
60
|
|
|
$opts = new CommandLineOptions($args); |
61
|
|
|
|
62
|
|
|
self::assertEquals(__FILE__, $opts->getInputPath()); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* testAssignsFormatArgumentToReportFormatProperty |
67
|
|
|
* |
68
|
|
|
* @return void |
69
|
|
|
* @since 1.1.0 |
70
|
|
|
*/ |
71
|
|
View Code Duplication |
public function testAssignsFormatArgumentToReportFormatProperty() |
|
|
|
|
72
|
|
|
{ |
73
|
|
|
$args = array('foo.php', __FILE__, 'text', 'design'); |
74
|
|
|
$opts = new CommandLineOptions($args); |
75
|
|
|
|
76
|
|
|
self::assertEquals('text', $opts->getReportFormat()); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* testAssignsRuleSetsArgumentToRuleSetProperty |
81
|
|
|
* |
82
|
|
|
* @return void |
83
|
|
|
* @since 1.1.0 |
84
|
|
|
*/ |
85
|
|
View Code Duplication |
public function testAssignsRuleSetsArgumentToRuleSetProperty() |
|
|
|
|
86
|
|
|
{ |
87
|
|
|
$args = array('foo.php', __FILE__, 'text', 'design'); |
88
|
|
|
$opts = new CommandLineOptions($args); |
89
|
|
|
|
90
|
|
|
self::assertEquals('design', $opts->getRuleSets()); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* testThrowsExpectedExceptionWhenRequiredArgumentsNotSet |
95
|
|
|
* |
96
|
|
|
* @return void |
97
|
|
|
* @since 1.1.0 |
98
|
|
|
* @expectedException \InvalidArgumentException |
99
|
|
|
*/ |
100
|
|
|
public function testThrowsExpectedExceptionWhenRequiredArgumentsNotSet() |
101
|
|
|
{ |
102
|
|
|
$args = array(__FILE__, 'text', 'design'); |
103
|
|
|
new CommandLineOptions($args); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* testAssignsInputFileOptionToInputPathProperty |
108
|
|
|
* |
109
|
|
|
* @return void |
110
|
|
|
* @since 1.1.0 |
111
|
|
|
*/ |
112
|
|
View Code Duplication |
public function testAssignsInputFileOptionToInputPathProperty() |
|
|
|
|
113
|
|
|
{ |
114
|
|
|
$uri = self::createResourceUriForTest('inputfile.txt'); |
115
|
|
|
|
116
|
|
|
$args = array('foo.php', 'text', 'design', '--inputfile', $uri); |
117
|
|
|
$opts = new CommandLineOptions($args); |
118
|
|
|
|
119
|
|
|
self::assertEquals('Dir1/Class1.php,Dir2/Class2.php', $opts->getInputPath()); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* testAssignsFormatArgumentCorrectWhenCalledWithInputFile |
124
|
|
|
* |
125
|
|
|
* @return void |
126
|
|
|
* @since 1.1.0 |
127
|
|
|
*/ |
128
|
|
View Code Duplication |
public function testAssignsFormatArgumentCorrectWhenCalledWithInputFile() |
|
|
|
|
129
|
|
|
{ |
130
|
|
|
$uri = self::createResourceUriForTest('inputfile.txt'); |
131
|
|
|
|
132
|
|
|
$args = array('foo.php', 'text', 'design', '--inputfile', $uri); |
133
|
|
|
$opts = new CommandLineOptions($args); |
134
|
|
|
|
135
|
|
|
self::assertEquals('text', $opts->getReportFormat()); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* testAssignsRuleSetsArgumentCorrectWhenCalledWithInputFile |
140
|
|
|
* |
141
|
|
|
* @return void |
142
|
|
|
* @since 1.1.0 |
143
|
|
|
*/ |
144
|
|
View Code Duplication |
public function testAssignsRuleSetsArgumentCorrectWhenCalledWithInputFile() |
|
|
|
|
145
|
|
|
{ |
146
|
|
|
$uri = self::createResourceUriForTest('inputfile.txt'); |
147
|
|
|
|
148
|
|
|
$args = array('foo.php', 'text', 'design', '--inputfile', $uri); |
149
|
|
|
$opts = new CommandLineOptions($args); |
150
|
|
|
|
151
|
|
|
self::assertEquals('design', $opts->getRuleSets()); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* testThrowsExpectedExceptionWhenInputFileNotExists |
156
|
|
|
* |
157
|
|
|
* @return void |
158
|
|
|
* @since 1.1.0 |
159
|
|
|
* @expectedException \InvalidArgumentException |
160
|
|
|
*/ |
161
|
|
|
public function testThrowsExpectedExceptionWhenInputFileNotExists() |
162
|
|
|
{ |
163
|
|
|
$args = array('foo.php', 'text', 'design', '--inputfile', 'inputfail.txt'); |
164
|
|
|
new CommandLineOptions($args); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* testHasVersionReturnsFalseByDefault |
169
|
|
|
* |
170
|
|
|
* @return void |
171
|
|
|
*/ |
172
|
|
|
public function testHasVersionReturnsFalseByDefault() |
173
|
|
|
{ |
174
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'unusedcode'); |
175
|
|
|
$opts = new CommandLineOptions($args); |
176
|
|
|
|
177
|
|
|
self::assertFalse($opts->hasVersion()); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* testCliOptionsAcceptsVersionArgument |
182
|
|
|
* |
183
|
|
|
* @return void |
184
|
|
|
*/ |
185
|
|
|
public function testCliOptionsAcceptsVersionArgument() |
186
|
|
|
{ |
187
|
|
|
$args = array(__FILE__, '--version'); |
188
|
|
|
$opts = new CommandLineOptions($args); |
189
|
|
|
|
190
|
|
|
self::assertTrue($opts->hasVersion()); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Tests if ignoreViolationsOnExit returns false by default |
195
|
|
|
* |
196
|
|
|
* @return void |
197
|
|
|
*/ |
198
|
|
|
public function testIgnoreViolationsOnExitReturnsFalseByDefault() |
199
|
|
|
{ |
200
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'unusedcode'); |
201
|
|
|
$opts = new CommandLineOptions($args); |
202
|
|
|
|
203
|
|
|
self::assertFalse($opts->ignoreViolationsOnExit()); |
204
|
|
|
} |
205
|
|
|
|
206
|
|
|
/** |
207
|
|
|
* Tests if CLI options accepts ignoreViolationsOnExit argument |
208
|
|
|
* |
209
|
|
|
* @return void |
210
|
|
|
*/ |
211
|
|
|
public function testCliOptionsAcceptsIgnoreViolationsOnExitArgument() |
212
|
|
|
{ |
213
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'unusedcode', '--ignore-violations-on-exit'); |
214
|
|
|
$opts = new CommandLineOptions($args); |
215
|
|
|
|
216
|
|
|
self::assertTrue($opts->ignoreViolationsOnExit()); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* Tests if CLI usage contains ignoreViolationsOnExit option |
221
|
|
|
* |
222
|
|
|
* @return void |
223
|
|
|
*/ |
224
|
|
View Code Duplication |
public function testCliUsageContainsIgnoreViolationsOnExitOption() |
|
|
|
|
225
|
|
|
{ |
226
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'codesize'); |
227
|
|
|
$opts = new CommandLineOptions($args); |
228
|
|
|
|
229
|
|
|
$this->assertContains('--ignore-violations-on-exit:', $opts->usage()); |
230
|
|
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* Tests if CLI usage contains the auto-discovered renderers |
234
|
|
|
* |
235
|
|
|
* @return void |
236
|
|
|
*/ |
237
|
|
View Code Duplication |
public function testCliUsageContainsAutoDiscoveredRenderers() |
|
|
|
|
238
|
|
|
{ |
239
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'codesize'); |
240
|
|
|
$opts = new CommandLineOptions($args); |
241
|
|
|
|
242
|
|
|
$this->assertContains('Available formats: html, json, text, xml.', $opts->usage()); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
/** |
246
|
|
|
* testCliUsageContainsStrictOption |
247
|
|
|
* |
248
|
|
|
* @return void |
249
|
|
|
*/ |
250
|
|
View Code Duplication |
public function testCliUsageContainsStrictOption() |
|
|
|
|
251
|
|
|
{ |
252
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'codesize'); |
253
|
|
|
$opts = new CommandLineOptions($args); |
254
|
|
|
|
255
|
|
|
$this->assertContains('--strict:', $opts->usage()); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* testCliOptionsIsStrictReturnsFalseByDefault |
260
|
|
|
* |
261
|
|
|
* @return void |
262
|
|
|
* @since 1.2.0 |
263
|
|
|
*/ |
264
|
|
|
public function testCliOptionsIsStrictReturnsFalseByDefault() |
265
|
|
|
{ |
266
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'codesize'); |
267
|
|
|
$opts = new CommandLineOptions($args); |
268
|
|
|
|
269
|
|
|
self::assertFalse($opts->hasStrict()); |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
/** |
273
|
|
|
* testCliOptionsAcceptsStrictArgument |
274
|
|
|
* |
275
|
|
|
* @return void |
276
|
|
|
* @since 1.2.0 |
277
|
|
|
*/ |
278
|
|
|
public function testCliOptionsAcceptsStrictArgument() |
279
|
|
|
{ |
280
|
|
|
$args = array(__FILE__, '--strict', __FILE__, 'text', 'codesize'); |
281
|
|
|
$opts = new CommandLineOptions($args); |
282
|
|
|
|
283
|
|
|
self::assertTrue($opts->hasStrict()); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* @return void |
288
|
|
|
*/ |
289
|
|
View Code Duplication |
public function testCliOptionsAcceptsMinimumpriorityArgument() |
|
|
|
|
290
|
|
|
{ |
291
|
|
|
$args = array(__FILE__, '--minimumpriority', 42, __FILE__, 'text', 'codesize'); |
292
|
|
|
$opts = new CommandLineOptions($args); |
293
|
|
|
|
294
|
|
|
$this->assertEquals(42, $opts->getMinimumPriority()); |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* @return void |
299
|
|
|
*/ |
300
|
|
View Code Duplication |
public function testCliOptionsAcceptsMaximumpriorityArgument() |
|
|
|
|
301
|
|
|
{ |
302
|
|
|
$args = array(__FILE__, '--maximumpriority', 42, __FILE__, 'text', 'codesize'); |
303
|
|
|
$opts = new CommandLineOptions($args); |
304
|
|
|
|
305
|
|
|
$this->assertEquals(42, $opts->getMaximumPriority()); |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
/** |
309
|
|
|
* @return void |
310
|
|
|
*/ |
311
|
|
View Code Duplication |
public function testGetMinimumPriorityReturnsLowestValueByDefault() |
|
|
|
|
312
|
|
|
{ |
313
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'codesize'); |
314
|
|
|
$opts = new CommandLineOptions($args); |
315
|
|
|
|
316
|
|
|
$this->assertEquals(Rule::LOWEST_PRIORITY, $opts->getMinimumPriority()); |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* @return void |
321
|
|
|
*/ |
322
|
|
|
public function testGetCoverageReportReturnsNullByDefault() |
323
|
|
|
{ |
324
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'codesize'); |
325
|
|
|
$opts = new CommandLineOptions($args); |
326
|
|
|
|
327
|
|
|
$this->assertNull($opts->getCoverageReport()); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* @return void |
332
|
|
|
*/ |
333
|
|
View Code Duplication |
public function testGetCoverageReportWithCliOption() |
|
|
|
|
334
|
|
|
{ |
335
|
|
|
$opts = new CommandLineOptions( |
336
|
|
|
array( |
337
|
|
|
__FILE__, |
338
|
|
|
__FILE__, |
339
|
|
|
'text', |
340
|
|
|
'codesize', |
341
|
|
|
'--coverage', |
342
|
|
|
__METHOD__ |
343
|
|
|
) |
344
|
|
|
); |
345
|
|
|
|
346
|
|
|
$this->assertEquals(__METHOD__, $opts->getCoverageReport()); |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
/** |
350
|
|
|
* @param string $reportFormat |
351
|
|
|
* @param string $expectedClass |
352
|
|
|
* @return void |
353
|
|
|
* @dataProvider dataProviderCreateRenderer |
354
|
|
|
*/ |
355
|
|
|
public function testCreateRenderer($reportFormat, $expectedClass) |
356
|
|
|
{ |
357
|
|
|
$args = array(__FILE__, __FILE__, $reportFormat, 'codesize'); |
358
|
|
|
$opts = new CommandLineOptions($args); |
359
|
|
|
|
360
|
|
|
$this->assertInstanceOf($expectedClass, $opts->createRenderer($reportFormat)); |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
/** |
364
|
|
|
* @return array |
365
|
|
|
*/ |
366
|
|
|
public function dataProviderCreateRenderer() |
367
|
|
|
{ |
368
|
|
|
return array( |
369
|
|
|
array('html', 'PHPMD\\Renderer\\HtmlRenderer'), |
370
|
|
|
array('text', TextRenderer::class), |
371
|
|
|
array('xml', 'PHPMD\\Renderer\\XmlRenderer'), |
372
|
|
|
array('PHPMD_Test_Renderer_PEARRenderer', 'PHPMD_Test_Renderer_PEARRenderer'), |
373
|
|
|
array(NamespaceRenderer::class, NamespaceRenderer::class), |
374
|
|
|
/* Test what happens when class already exists. */ |
375
|
|
|
array(NamespaceRenderer::class, NamespaceRenderer::class), |
376
|
|
|
); |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
/** |
380
|
|
|
* @param string $reportFormat |
381
|
|
|
* @return void |
382
|
|
|
* @expectedException \InvalidArgumentException |
383
|
|
|
* @expectedExceptionMessageRegExp (^Can\'t ) |
384
|
|
|
* @dataProvider dataProviderCreateRendererThrowsException |
385
|
|
|
*/ |
386
|
|
|
public function testCreateRendererThrowsException($reportFormat) |
387
|
|
|
{ |
388
|
|
|
$args = array(__FILE__, __FILE__, $reportFormat, 'codesize'); |
389
|
|
|
$opts = new CommandLineOptions($args); |
390
|
|
|
$opts->createRenderer(); |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
/** |
394
|
|
|
* @return array |
395
|
|
|
*/ |
396
|
|
|
public function dataProviderCreateRendererThrowsException() |
397
|
|
|
{ |
398
|
|
|
return array( |
399
|
|
|
array(''), |
400
|
|
|
array('PHPMD\\Test\\Renderer\\NotExistsRenderer') |
401
|
|
|
); |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* @param string $deprecatedName |
406
|
|
|
* @param string $newName |
407
|
|
|
* @dataProvider dataProviderDeprecatedCliOptions |
408
|
|
|
*/ |
409
|
|
|
public function testDeprecatedCliOptions($deprecatedName, $newName) |
410
|
|
|
{ |
411
|
|
|
stream_filter_register('stderr_stream', StreamFilter::class); |
412
|
|
|
|
413
|
|
|
$this->stderrStreamFilter = stream_filter_prepend(STDERR, 'stderr_stream'); |
414
|
|
|
|
415
|
|
|
$args = array(__FILE__, __FILE__, 'text', 'codesize', sprintf('--%s', $deprecatedName), 42); |
416
|
|
|
new CommandLineOptions($args); |
417
|
|
|
|
418
|
|
|
$this->assertContains( |
419
|
|
|
sprintf( |
420
|
|
|
'The --%s option is deprecated, please use --%s instead.', |
421
|
|
|
$deprecatedName, |
422
|
|
|
$newName |
423
|
|
|
), |
424
|
|
|
StreamFilter::$streamHandle |
425
|
|
|
); |
426
|
|
|
} |
427
|
|
|
|
428
|
|
|
/** |
429
|
|
|
* @return array |
430
|
|
|
*/ |
431
|
|
|
public function dataProviderDeprecatedCliOptions() |
432
|
|
|
{ |
433
|
|
|
return array( |
434
|
|
|
array('extensions', 'suffixes'), |
435
|
|
|
array('ignore', 'exclude') |
436
|
|
|
); |
437
|
|
|
} |
438
|
|
|
|
439
|
|
|
/** |
440
|
|
|
* @param array $options |
441
|
|
|
* @param array $expected |
442
|
|
|
* @return void |
443
|
|
|
* @dataProvider dataProviderGetReportFiles |
444
|
|
|
*/ |
445
|
|
View Code Duplication |
public function testGetReportFiles(array $options, array $expected) |
|
|
|
|
446
|
|
|
{ |
447
|
|
|
$args = array_merge(array(__FILE__, __FILE__, 'text', 'codesize'), $options); |
448
|
|
|
$opts = new CommandLineOptions($args); |
449
|
|
|
|
450
|
|
|
$this->assertEquals($expected, $opts->getReportFiles()); |
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
public function dataProviderGetReportFiles() |
454
|
|
|
{ |
455
|
|
|
return array( |
456
|
|
|
array( |
457
|
|
|
array('--reportfile-xml', __FILE__), |
458
|
|
|
array('xml' => __FILE__) |
459
|
|
|
), |
460
|
|
|
array( |
461
|
|
|
array('--reportfile-html', __FILE__), |
462
|
|
|
array('html' => __FILE__) |
463
|
|
|
), |
464
|
|
|
array( |
465
|
|
|
array('--reportfile-text', __FILE__), |
466
|
|
|
array('text' => __FILE__) |
467
|
|
|
), |
468
|
|
|
array( |
469
|
|
|
array( |
470
|
|
|
'--reportfile-text', |
471
|
|
|
__FILE__, |
472
|
|
|
'--reportfile-xml', |
473
|
|
|
__FILE__, |
474
|
|
|
'--reportfile-html', |
475
|
|
|
__FILE__, |
476
|
|
|
), |
477
|
|
|
array('text' => __FILE__, 'xml' => __FILE__, 'html' => __FILE__) |
478
|
|
|
), |
479
|
|
|
); |
480
|
|
|
} |
481
|
|
|
} |
482
|
|
|
|
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.