| 1 |
<?php
|
| 2 |
// $Id: CoderTestFile.php,v 1.1.2.4 2008/01/21 03:40:33 sun Exp $
|
| 3 |
|
| 4 |
|
| 5 |
/**
|
| 6 |
* Represents coder test file for full coder_format_string_all() tests.
|
| 7 |
*/
|
| 8 |
class CoderTestFile extends SimpleExpectation {
|
| 9 |
/* Filename of test */
|
| 10 |
var $filename;
|
| 11 |
|
| 12 |
/* Test name */
|
| 13 |
var $test;
|
| 14 |
|
| 15 |
/* PHP to be parsed */
|
| 16 |
var $input = array();
|
| 17 |
|
| 18 |
/* Expected output */
|
| 19 |
var $expect = array();
|
| 20 |
|
| 21 |
/* Actual result */
|
| 22 |
var $actual = array();
|
| 23 |
|
| 24 |
/* Whether or not <?php and CVS Id should be added */
|
| 25 |
var $full = 0;
|
| 26 |
|
| 27 |
/* Whether or not a specific test should be the only one tested */
|
| 28 |
var $only = array();
|
| 29 |
|
| 30 |
/**
|
| 31 |
* Loads this class from a file.
|
| 32 |
*
|
| 33 |
* @param string $filename
|
| 34 |
* A filename to load.
|
| 35 |
*/
|
| 36 |
function load($filename) {
|
| 37 |
$this->filename = $filename;
|
| 38 |
$fh = fopen($filename, 'r');
|
| 39 |
$state = '';
|
| 40 |
$unit = 0;
|
| 41 |
|
| 42 |
while (($line = fgets($fh)) !== false) {
|
| 43 |
// Normalize newlines.
|
| 44 |
$line = rtrim($line, "\n\r");
|
| 45 |
// Detect INPUT and EXPECT sections.
|
| 46 |
if (substr($line, 0, 2) == '--') {
|
| 47 |
$state = trim($line, ' -');
|
| 48 |
|
| 49 |
// If a new INPUT section begins, start a new unit.
|
| 50 |
if ($state == 'INPUT') {
|
| 51 |
// If previous section has been marked with the keyword 'ONLY', break
|
| 52 |
// immediately to process only the marked section.
|
| 53 |
if ($this->only[$unit]) {
|
| 54 |
break;
|
| 55 |
}
|
| 56 |
$unit++;
|
| 57 |
}
|
| 58 |
continue;
|
| 59 |
}
|
| 60 |
// Process other keywords only outside of INPUT and EXPECT sections.
|
| 61 |
if (!$state) {
|
| 62 |
list($keyword, $line) = explode(': ', $line, 2);
|
| 63 |
}
|
| 64 |
// Assign previous keyword, if there is no new one.
|
| 65 |
else {
|
| 66 |
$keyword = $state;
|
| 67 |
}
|
| 68 |
switch ($keyword) {
|
| 69 |
case 'TEST':
|
| 70 |
$this->test = $line;
|
| 71 |
break;
|
| 72 |
|
| 73 |
case 'FULL':
|
| 74 |
$this->full = (bool)$line;
|
| 75 |
break;
|
| 76 |
|
| 77 |
case 'INPUT':
|
| 78 |
$this->input[$unit] .= $line ."\n";
|
| 79 |
break;
|
| 80 |
|
| 81 |
case 'EXPECT':
|
| 82 |
$this->expect[$unit] .= $line ."\n";
|
| 83 |
break;
|
| 84 |
|
| 85 |
case 'ONLY':
|
| 86 |
$this->only[$unit] = TRUE;
|
| 87 |
break;
|
| 88 |
}
|
| 89 |
}
|
| 90 |
fclose($fh);
|
| 91 |
foreach (range(1, $unit) as $unit) {
|
| 92 |
// If no EXPECTed code was defined, INPUT is expected.
|
| 93 |
if (!isset($this->expect[$unit])) {
|
| 94 |
$this->expect[$unit] = $this->input[$unit];
|
| 95 |
}
|
| 96 |
// If FULL was *not* defined, add a PHP header to contents.
|
| 97 |
if (!$this->full) {
|
| 98 |
$prepend = "<?php\n// $". "Id$\n\n";
|
| 99 |
$this->input[$unit] = $prepend . rtrim($this->input[$unit], "\n") ."\n\n";
|
| 100 |
$this->expect[$unit] = $prepend . rtrim($this->expect[$unit], "\n") ."\n\n";
|
| 101 |
}
|
| 102 |
}
|
| 103 |
if (!empty($this->only[$unit])) {
|
| 104 |
$this->input = array($this->input[$unit]);
|
| 105 |
$this->expect = array($this->expect[$unit]);
|
| 106 |
}
|
| 107 |
}
|
| 108 |
|
| 109 |
/**
|
| 110 |
* Implements SimpleExpectation::test().
|
| 111 |
*
|
| 112 |
* @param $filename Filename of test file to test.
|
| 113 |
*/
|
| 114 |
function test($filename = false) {
|
| 115 |
if ($filename) {
|
| 116 |
$this->load($filename);
|
| 117 |
}
|
| 118 |
|
| 119 |
// Perform test.
|
| 120 |
// Test passes until proven invalid.
|
| 121 |
$valid = TRUE;
|
| 122 |
foreach ($this->input as $unit => $content) {
|
| 123 |
// Parse input and store results.
|
| 124 |
$this->actual[$unit] = coder_format_string_all($this->input[$unit]);
|
| 125 |
|
| 126 |
// Let this test fail, if a unit fails.
|
| 127 |
if ($this->expect[$unit] !== $this->actual[$unit]) {
|
| 128 |
$valid = FALSE;
|
| 129 |
}
|
| 130 |
}
|
| 131 |
|
| 132 |
return $valid;
|
| 133 |
}
|
| 134 |
|
| 135 |
/**
|
| 136 |
* Implements SimpleExpectation::testMessage().
|
| 137 |
*/
|
| 138 |
function testMessage() {
|
| 139 |
$message = $this->test .' test in '. htmlspecialchars(basename($this->filename));
|
| 140 |
return $message;
|
| 141 |
}
|
| 142 |
|
| 143 |
/**
|
| 144 |
* Renders the test with an HTML diff table.
|
| 145 |
*/
|
| 146 |
function render() {
|
| 147 |
drupal_add_css(drupal_get_path('module', 'coder') .'/scripts/coder_format/tests/coder-diff.css', 'module', 'all', false);
|
| 148 |
|
| 149 |
foreach ($this->input as $unit => $content) {
|
| 150 |
// Do not output passed units.
|
| 151 |
if ($this->expect[$unit] === $this->actual[$unit]) {
|
| 152 |
continue;
|
| 153 |
}
|
| 154 |
|
| 155 |
$diff = new Text_Diff('auto', array(explode("\n", $this->expect[$unit]), explode("\n", $this->actual[$unit])));
|
| 156 |
$renderer = new Text_Diff_Renderer_parallel($this->test .' test in '. htmlspecialchars(basename($this->filename)));
|
| 157 |
|
| 158 |
$message .= $renderer->render($diff);
|
| 159 |
}
|
| 160 |
|
| 161 |
return $message;
|
| 162 |
}
|
| 163 |
}
|
| 164 |
|
| 165 |
/**
|
| 166 |
* Parallel diff renderer for HTML tables with original text on left,
|
| 167 |
* new text on right, and changed text highlighted with appropriate classes.
|
| 168 |
*/
|
| 169 |
class Text_Diff_Renderer_parallel extends Text_Diff_Renderer {
|
| 170 |
/* String header for left column */
|
| 171 |
var $original = 'Expected';
|
| 172 |
|
| 173 |
/* String header for right column */
|
| 174 |
var $final = 'Actual';
|
| 175 |
|
| 176 |
// These are big to ensure entire string is output.
|
| 177 |
var $_leading_context_lines = 10000;
|
| 178 |
var $_trailing_context_lines = 10000;
|
| 179 |
var $title;
|
| 180 |
|
| 181 |
function Text_Diff_Renderer_parallel($title) {
|
| 182 |
$this->title = $title;
|
| 183 |
}
|
| 184 |
|
| 185 |
function _blockHeader() {}
|
| 186 |
|
| 187 |
function _startDiff() {
|
| 188 |
return '<table class="diff"><thead><tr><th colspan="2">'. $this->title .'</th></tr><tr><th>'. $this->original .'</th><th>'. $this->final .'</th></tr></thead><tbody>';
|
| 189 |
}
|
| 190 |
|
| 191 |
function _endDiff() {
|
| 192 |
return '</tbody></table>';
|
| 193 |
}
|
| 194 |
|
| 195 |
function _context($lines) {
|
| 196 |
return '<tr><td><pre>'. $this->_renderLines($lines) .'</pre></td>
|
| 197 |
<td><pre>'. $this->_renderLines($lines) .'</pre></td></tr>';
|
| 198 |
}
|
| 199 |
|
| 200 |
function _added($lines) {
|
| 201 |
return '<tr><td> </td><td class="added"><pre>'. $this->_renderLines($lines) .'</pre></td></tr>';
|
| 202 |
}
|
| 203 |
|
| 204 |
function _deleted($lines) {
|
| 205 |
return '<tr><td class="deleted"><pre>'. $this->_renderLines($lines) .'</pre></td><td> </td></tr>';
|
| 206 |
}
|
| 207 |
|
| 208 |
function _changed($orig, $final) {
|
| 209 |
return '<tr class="changed"><td><pre>'. $this->_renderLines($orig) .'</pre></td>
|
| 210 |
<td><pre>'. $this->_renderLines($final) .'</pre></td></tr>';
|
| 211 |
}
|
| 212 |
|
| 213 |
function _renderLines($lines) {
|
| 214 |
return str_replace("\n", "<strong>¶</strong>\n", htmlspecialchars(implode("\n", $lines)."\n"));
|
| 215 |
}
|
| 216 |
|
| 217 |
}
|
| 218 |
|