Skip to content

Commit a7d77cf

Browse files
committed
Generators: add tests covering handling of invalid docs
This adds another set of dedicated tests to safeguard how XML docs which don't follow the specification are handled. This initial set of tests for this documents the current behaviour [*]. This behaviour may not always be the desired behaviour, in which case, this will be fixed in follow-up commits. To get these tests up and running, the following fatal errors needed to be fixed: * Fatal error when a code comparison only contains a single code element: ``` Fatal error: Uncaught Error: Call to a member function getAttribute() on null in path/to/PHP_CodeSniffer/src/Generators/Markdown.php:253 Stack trace: #0 path/to/PHP_CodeSniffer/src/Generators/Markdown.php(139): PHP_CodeSniffer\Generators\Markdown->getFormattedCodeComparisonBlock(Object(DOMElement)) #1 path/to/PHP_CodeSniffer/src/Generators/Markdown.php(39): PHP_CodeSniffer\Generators\Markdown->processSniff(Object(DOMElement)) #2 path/to/PHP_CodeSniffer/src/Runner.php(99): PHP_CodeSniffer\Generators\Markdown->generate() #3 path/to/PHP_CodeSniffer/bin/phpcs(14): PHP_CodeSniffer\Runner->runPHPCS() #4 {main} thrown in path/to/PHP_CodeSniffer/src/Generators/Markdown.php on line 253 ``` * Fatal error when a code element contains no textual content: ``` Fatal error: Uncaught Error: Call to a member function getAttribute() on null in path/to/PHP_CodeSniffer/src/Generators/Markdown.php:246 Stack trace: #0 path/to/PHP_CodeSniffer/src/Generators/Markdown.php(139): PHP_CodeSniffer\Generators\Markdown->getFormattedCodeComparisonBlock(Object(DOMElement)) #1 path/to/PHP_CodeSniffer/src/Generators/Markdown.php(39): PHP_CodeSniffer\Generators\Markdown->processSniff(Object(DOMElement)) #2 path/to/PHP_CodeSniffer/src/Runner.php(99): PHP_CodeSniffer\Generators\Markdown->generate() #3 path/to/PHP_CodeSniffer/bin/phpcs(14): PHP_CodeSniffer\Runner->runPHPCS() #4 {main} thrown in path/to/PHP_CodeSniffer/src/Generators/Markdown.php on line 246 ``` Both of these fatals are fixed by adding defensive coding validating that there are (at least) two code blocks to the `getFormattedCodeComparisonBlock()` methods for all three generator classes.
1 parent d11ed56 commit a7d77cf

File tree

61 files changed

+1836
-63
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1836
-63
lines changed

src/Generators/HTML.php

+12-5
Original file line numberDiff line numberDiff line change
@@ -383,20 +383,27 @@ protected function printCodeComparisonBlock(DOMNode $node)
383383
*/
384384
protected function getFormattedCodeComparisonBlock(DOMNode $node)
385385
{
386-
$codeBlocks = $node->getElementsByTagName('code');
386+
$codeBlocks = $node->getElementsByTagName('code');
387+
$firstCodeElm = $codeBlocks->item(0);
388+
$secondCodeElm = $codeBlocks->item(1);
387389

388-
$firstTitle = trim($codeBlocks->item(0)->getAttribute('title'));
390+
if (isset($firstCodeElm, $secondCodeElm) === false) {
391+
// Missing at least one code block.
392+
return '';
393+
}
394+
395+
$firstTitle = trim($firstCodeElm->getAttribute('title'));
389396
$firstTitle = str_replace(' ', '  ', $firstTitle);
390-
$first = trim($codeBlocks->item(0)->nodeValue);
397+
$first = trim($firstCodeElm->nodeValue);
391398
$first = str_replace('<?php', '&lt;?php', $first);
392399
$first = str_replace("\n", '</br>', $first);
393400
$first = str_replace(' ', '&nbsp;', $first);
394401
$first = str_replace('<em>', '<span class="code-comparison-highlight">', $first);
395402
$first = str_replace('</em>', '</span>', $first);
396403

397-
$secondTitle = trim($codeBlocks->item(1)->getAttribute('title'));
404+
$secondTitle = trim($secondCodeElm->getAttribute('title'));
398405
$secondTitle = str_replace(' ', '&nbsp;&nbsp;', $secondTitle);
399-
$second = trim($codeBlocks->item(1)->nodeValue);
406+
$second = trim($secondCodeElm->nodeValue);
400407
$second = str_replace('<?php', '&lt;?php', $second);
401408
$second = str_replace("\n", '</br>', $second);
402409
$second = str_replace(' ', '&nbsp;', $second);

src/Generators/Markdown.php

+12-5
Original file line numberDiff line numberDiff line change
@@ -241,18 +241,25 @@ protected function printCodeComparisonBlock(DOMNode $node)
241241
*/
242242
protected function getFormattedCodeComparisonBlock(DOMNode $node)
243243
{
244-
$codeBlocks = $node->getElementsByTagName('code');
244+
$codeBlocks = $node->getElementsByTagName('code');
245+
$firstCodeElm = $codeBlocks->item(0);
246+
$secondCodeElm = $codeBlocks->item(1);
245247

246-
$firstTitle = trim($codeBlocks->item(0)->getAttribute('title'));
248+
if (isset($firstCodeElm, $secondCodeElm) === false) {
249+
// Missing at least one code block.
250+
return '';
251+
}
252+
253+
$firstTitle = trim($firstCodeElm->getAttribute('title'));
247254
$firstTitle = str_replace(' ', '&nbsp;&nbsp;', $firstTitle);
248-
$first = trim($codeBlocks->item(0)->nodeValue);
255+
$first = trim($firstCodeElm->nodeValue);
249256
$first = str_replace("\n", PHP_EOL.' ', $first);
250257
$first = str_replace('<em>', '', $first);
251258
$first = str_replace('</em>', '', $first);
252259

253-
$secondTitle = trim($codeBlocks->item(1)->getAttribute('title'));
260+
$secondTitle = trim($secondCodeElm->getAttribute('title'));
254261
$secondTitle = str_replace(' ', '&nbsp;&nbsp;', $secondTitle);
255-
$second = trim($codeBlocks->item(1)->nodeValue);
262+
$second = trim($secondCodeElm->nodeValue);
256263
$second = str_replace("\n", PHP_EOL.' ', $second);
257264
$second = str_replace('<em>', '', $second);
258265
$second = str_replace('</em>', '', $second);

src/Generators/Text.php

+13-5
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,17 @@ protected function printCodeComparisonBlock(DOMNode $node)
198198
*/
199199
protected function getFormattedCodeComparisonBlock(DOMNode $node)
200200
{
201-
$codeBlocks = $node->getElementsByTagName('code');
202-
$first = trim($codeBlocks->item(0)->nodeValue);
203-
$firstTitle = trim($codeBlocks->item(0)->getAttribute('title'));
201+
$codeBlocks = $node->getElementsByTagName('code');
202+
$firstCodeElm = $codeBlocks->item(0);
203+
$secondCodeElm = $codeBlocks->item(1);
204+
205+
if (isset($firstCodeElm, $secondCodeElm) === false) {
206+
// Missing at least one code block.
207+
return '';
208+
}
209+
210+
$first = trim($firstCodeElm->nodeValue);
211+
$firstTitle = trim($firstCodeElm->getAttribute('title'));
204212

205213
$firstTitleLines = [];
206214
$tempTitle = '';
@@ -234,8 +242,8 @@ protected function getFormattedCodeComparisonBlock(DOMNode $node)
234242
$first = str_replace('</em>', '', $first);
235243
$firstLines = explode("\n", $first);
236244

237-
$second = trim($codeBlocks->item(1)->nodeValue);
238-
$secondTitle = trim($codeBlocks->item(1)->getAttribute('title'));
245+
$second = trim($secondCodeElm->nodeValue);
246+
$secondTitle = trim($secondCodeElm->getAttribute('title'));
239247

240248
$secondTitleLines = [];
241249
$tempTitle = '';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<html>
2+
<head>
3+
<title>GeneratorTest Coding Standards</title>
4+
<style>
5+
body {
6+
background-color: #FFFFFF;
7+
font-size: 14px;
8+
font-family: Arial, Helvetica, sans-serif;
9+
color: #000000;
10+
}
11+
12+
h1 {
13+
color: #666666;
14+
font-size: 20px;
15+
font-weight: bold;
16+
margin-top: 0px;
17+
background-color: #E6E7E8;
18+
padding: 20px;
19+
border: 1px solid #BBBBBB;
20+
}
21+
22+
h2 {
23+
color: #00A5E3;
24+
font-size: 16px;
25+
font-weight: normal;
26+
margin-top: 50px;
27+
}
28+
29+
.code-comparison {
30+
width: 100%;
31+
}
32+
33+
.code-comparison td {
34+
border: 1px solid #CCCCCC;
35+
}
36+
37+
.code-comparison-title, .code-comparison-code {
38+
font-family: Arial, Helvetica, sans-serif;
39+
font-size: 12px;
40+
color: #000000;
41+
vertical-align: top;
42+
padding: 4px;
43+
width: 50%;
44+
background-color: #F1F1F1;
45+
line-height: 15px;
46+
}
47+
48+
.code-comparison-code {
49+
font-family: Courier;
50+
background-color: #F9F9F9;
51+
}
52+
53+
.code-comparison-highlight {
54+
background-color: #DDF1F7;
55+
border: 1px solid #00A5E3;
56+
line-height: 15px;
57+
}
58+
59+
.tag-line {
60+
text-align: center;
61+
width: 100%;
62+
margin-top: 30px;
63+
font-size: 12px;
64+
}
65+
66+
.tag-line a {
67+
color: #000000;
68+
}
69+
</style>
70+
</head>
71+
<body>
72+
<h1>GeneratorTest Coding Standards</h1>
73+
<a name="Code-Comparison,-mismatched-code-blocks" />
74+
<h2>Code Comparison, mismatched code blocks</h2>
75+
<p class="text">This doc has two code elements, one only has a title, one has actual code. Unbalanced</p>
76+
<table class="code-comparison">
77+
<tr>
78+
<td class="code-comparison-title">Code title</td>
79+
<td class="code-comparison-title"></td>
80+
</tr>
81+
<tr>
82+
<td class="code-comparison-code"></td>
83+
<td class="code-comparison-code">$a&nbsp;=&nbsp;'Example&nbsp;code';</td>
84+
</tr>
85+
</table>
86+
<div class="tag-line">Documentation generated on #REDACTED# by <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer">PHP_CodeSniffer #VERSION#</a></div>
87+
</body>
88+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# GeneratorTest Coding Standard
2+
3+
## Code Comparison, mismatched code blocks
4+
5+
This doc has two code elements, one only has a title, one has actual code. Unbalanced
6+
<table>
7+
<tr>
8+
<th>Code title</th>
9+
<th></th>
10+
</tr>
11+
<tr>
12+
<td>
13+
14+
15+
16+
</td>
17+
<td>
18+
19+
$a = 'Example code';
20+
21+
</td>
22+
</tr>
23+
</table>
24+
25+
Documentation generated on *REDACTED* by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
--------------------------------------------------------------------------
3+
| GENERATORTEST CODING STANDARD: CODE COMPARISON, MISMATCHED CODE BLOCKS |
4+
--------------------------------------------------------------------------
5+
6+
This doc has two code elements, one only has a title, one has actual code. Unbalanced
7+
8+
----------------------------------------- CODE COMPARISON ------------------------------------------
9+
| Code title | |
10+
----------------------------------------------------------------------------------------------------
11+
| | $a = 'Example code'; |
12+
----------------------------------------------------------------------------------------------------
13+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<html>
2+
<head>
3+
<title>GeneratorTest Coding Standards</title>
4+
<style>
5+
body {
6+
background-color: #FFFFFF;
7+
font-size: 14px;
8+
font-family: Arial, Helvetica, sans-serif;
9+
color: #000000;
10+
}
11+
12+
h1 {
13+
color: #666666;
14+
font-size: 20px;
15+
font-weight: bold;
16+
margin-top: 0px;
17+
background-color: #E6E7E8;
18+
padding: 20px;
19+
border: 1px solid #BBBBBB;
20+
}
21+
22+
h2 {
23+
color: #00A5E3;
24+
font-size: 16px;
25+
font-weight: normal;
26+
margin-top: 50px;
27+
}
28+
29+
.code-comparison {
30+
width: 100%;
31+
}
32+
33+
.code-comparison td {
34+
border: 1px solid #CCCCCC;
35+
}
36+
37+
.code-comparison-title, .code-comparison-code {
38+
font-family: Arial, Helvetica, sans-serif;
39+
font-size: 12px;
40+
color: #000000;
41+
vertical-align: top;
42+
padding: 4px;
43+
width: 50%;
44+
background-color: #F1F1F1;
45+
line-height: 15px;
46+
}
47+
48+
.code-comparison-code {
49+
font-family: Courier;
50+
background-color: #F9F9F9;
51+
}
52+
53+
.code-comparison-highlight {
54+
background-color: #DDF1F7;
55+
border: 1px solid #00A5E3;
56+
line-height: 15px;
57+
}
58+
59+
.tag-line {
60+
text-align: center;
61+
width: 100%;
62+
margin-top: 30px;
63+
font-size: 12px;
64+
}
65+
66+
.tag-line a {
67+
color: #000000;
68+
}
69+
</style>
70+
</head>
71+
<body>
72+
<h1>GeneratorTest Coding Standards</h1>
73+
<a name="Code-Comparison,-missing-code-element" />
74+
<h2>Code Comparison, missing code element</h2>
75+
<p class="text">This is a standard block.</p>
76+
<div class="tag-line">Documentation generated on #REDACTED# by <a href="https://github.com/PHPCSStandards/PHP_CodeSniffer">PHP_CodeSniffer #VERSION#</a></div>
77+
</body>
78+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# GeneratorTest Coding Standard
2+
3+
## Code Comparison, missing code element
4+
5+
This is a standard block.
6+
7+
Documentation generated on *REDACTED* by [PHP_CodeSniffer *VERSION*](https://github.com/PHPCSStandards/PHP_CodeSniffer)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
------------------------------------------------------------------------
3+
| GENERATORTEST CODING STANDARD: CODE COMPARISON, MISSING CODE ELEMENT |
4+
------------------------------------------------------------------------
5+
6+
This is a standard block.
7+

0 commit comments

Comments
 (0)