Changeset View
Changeset View
Standalone View
Standalone View
src/lint/linter/__tests__/ArcanistLinterTestCase.php
| Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | if (count($contents) < 2) { | ||||
| "Expected '%s' separating test case and results.", | "Expected '%s' separating test case and results.", | ||||
| '~~~~~~~~~~')); | '~~~~~~~~~~')); | ||||
| } | } | ||||
| list($data, $expect, $xform, $config) = array_merge( | list($data, $expect, $xform, $config) = array_merge( | ||||
| $contents, | $contents, | ||||
| array(null, null)); | array(null, null)); | ||||
| $basename = basename($file); | |||||
| if ($config) { | if ($config) { | ||||
| $config = phutil_json_decode($config); | $config = phutil_json_decode($config); | ||||
| } else { | } else { | ||||
| $config = array(); | $config = array(); | ||||
| } | } | ||||
| PhutilTypeSpec::checkMap( | PhutilTypeSpec::checkMap( | ||||
| $config, | $config, | ||||
| array( | array( | ||||
| 'config' => 'optional map<string, wild>', | 'config' => 'optional map<string, wild>', | ||||
| 'mode' => 'optional string', | 'mode' => 'optional string', | ||||
| 'path' => 'optional string', | 'path' => 'optional string', | ||||
| 'stopped' => 'optional bool', | 'stopped' => 'optional bool', | ||||
| )); | )); | ||||
| $exception = null; | $exception = null; | ||||
| $after_lint = null; | $after_lint = null; | ||||
| $messages = null; | $messages = null; | ||||
| $exception_message = false; | $exception_message = false; | ||||
| $caught_exception = false; | $caught_exception = false; | ||||
| try { | try { | ||||
| $path_name = idx($config, 'path'); | |||||
| if ($path_name !== null) { | |||||
| $basename = basename($path_name); | |||||
| } else { | |||||
| $basename = basename($file); | |||||
| } | |||||
| $tmp = new TempFile($basename); | $tmp = new TempFile($basename); | ||||
| Filesystem::writeFile($tmp, $data); | Filesystem::writeFile($tmp, $data); | ||||
| $full_path = (string)$tmp; | $full_path = (string)$tmp; | ||||
| $mode = idx($config, 'mode'); | $mode = idx($config, 'mode'); | ||||
| if ($mode) { | if ($mode) { | ||||
| Filesystem::changePermissions($tmp, octdec($mode)); | Filesystem::changePermissions($tmp, octdec($mode)); | ||||
| } | } | ||||
| $dir = dirname($full_path); | $dir = dirname($full_path); | ||||
| $path = basename($full_path); | |||||
| $working_copy = ArcanistWorkingCopyIdentity::newFromRootAndConfigFile( | $working_copy = ArcanistWorkingCopyIdentity::newFromRootAndConfigFile( | ||||
| $dir, | $dir, | ||||
| null, | null, | ||||
| pht('Unit Test')); | pht('Unit Test')); | ||||
| $configuration_manager = new ArcanistConfigurationManager(); | $configuration_manager = new ArcanistConfigurationManager(); | ||||
| $configuration_manager->setWorkingCopyIdentity($working_copy); | $configuration_manager->setWorkingCopyIdentity($working_copy); | ||||
| $engine = new ArcanistUnitTestableLintEngine(); | $engine = new ArcanistUnitTestableLintEngine(); | ||||
| $engine->setWorkingCopy($working_copy); | $engine->setWorkingCopy($working_copy); | ||||
| $engine->setConfigurationManager($configuration_manager); | $engine->setConfigurationManager($configuration_manager); | ||||
| $path_name = idx($config, 'path', $path); | $engine->setPaths(array($basename)); | ||||
| $engine->setPaths(array($path_name)); | |||||
| $linter->setEngine($engine); | $linter->setEngine($engine); | ||||
| $linter->addPath($path_name); | $linter->addPath($basename); | ||||
| $linter->addData($path_name, $data); | $linter->addData($basename, $data); | ||||
| foreach (idx($config, 'config', array()) as $key => $value) { | foreach (idx($config, 'config', array()) as $key => $value) { | ||||
| $linter->setLinterConfigurationValue($key, $value); | $linter->setLinterConfigurationValue($key, $value); | ||||
| } | } | ||||
| $engine->addLinter($linter); | $engine->addLinter($linter); | ||||
| $engine->addFileData($path_name, $data); | $engine->addFileData($basename, $data); | ||||
| $results = $engine->run(); | $results = $engine->run(); | ||||
| $this->assertEqual( | $this->assertEqual( | ||||
| 1, | 1, | ||||
| count($results), | count($results), | ||||
| pht('Expect one result returned by linter.')); | pht('Expect one result returned by linter.')); | ||||
| $assert_stopped = idx($config, 'stopped'); | $assert_stopped = idx($config, 'stopped'); | ||||
| if ($assert_stopped !== null) { | if ($assert_stopped !== null) { | ||||
| $this->assertEqual( | $this->assertEqual( | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | private function compareLint($file, $expect, ArcanistLintResult $results) { | ||||
| } | } | ||||
| foreach ($expect as $result) { | foreach ($expect as $result) { | ||||
| $parts = explode(':', $result); | $parts = explode(':', $result); | ||||
| $message = new ArcanistLintMessage(); | $message = new ArcanistLintMessage(); | ||||
| $severity = idx($parts, 0); | $severity = idx($parts, 0); | ||||
| $line = idx($parts, 1); | $line = idx($parts, 1); | ||||
| if ($line === '') { | |||||
| $line = null; | |||||
| } | |||||
| $char = idx($parts, 2); | $char = idx($parts, 2); | ||||
| if ($char === '') { | |||||
| $char = null; | |||||
| } | |||||
| $code = idx($parts, 3); | $code = idx($parts, 3); | ||||
| if ($code === '') { | |||||
| $code = null; | |||||
| } | |||||
| if ($severity !== null) { | if ($severity !== null) { | ||||
| $message->setSeverity($severity); | $message->setSeverity($severity); | ||||
| } | } | ||||
| if ($line !== null) { | if ($line !== null) { | ||||
| $message->setLine($line); | $message->setLine($line); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | foreach ($expected_results->getMessages() as $expected_message) { | ||||
| } | } | ||||
| if (!$found) { | if (!$found) { | ||||
| $missing[] = $expected_message; | $missing[] = $expected_message; | ||||
| } | } | ||||
| } | } | ||||
| if ($missing || $surprising) { | if ($missing || $surprising) { | ||||
| $expected = pht('EXPECTED MESSAGES'); | |||||
| if ($missing) { | |||||
| foreach ($missing as $message) { | |||||
| $expected .= sprintf( | |||||
| "\n %s: %s %s", | |||||
| pht( | |||||
| '%s at line %d, char %d', | |||||
| $message->getSeverity(), | |||||
| $message->getLine(), | |||||
| $message->getChar()), | |||||
| $message->getCode(), | |||||
| $message->getName()); | |||||
| } | |||||
| } else { | |||||
| $expected .= "\n ".pht('No messages'); | |||||
| } | |||||
| $actual = pht('UNEXPECTED MESSAGES'); | |||||
| if ($surprising) { | |||||
| foreach ($surprising as $message) { | |||||
| $actual .= sprintf( | |||||
| "\n %s: %s %s", | |||||
| pht( | |||||
| '%s at line %d, char %d', | |||||
| $message->getSeverity(), | |||||
| $message->getLine(), | |||||
| $message->getChar()), | |||||
| $message->getCode(), | |||||
| $message->getName()); | |||||
| } | |||||
| } else { | |||||
| $actual .= "\n ".pht('No messages'); | |||||
| } | |||||
| $this->assertFailure( | $this->assertFailure( | ||||
| sprintf( | sprintf( | ||||
| "%s\n\n%s\n\n%s", | "%s\n%s%s", | ||||
| pht("Lint failed for '%s'.", $file), | pht( | ||||
| $expected, | 'Lint emitted an unexpected set of messages for file "%s".', | ||||
| $actual)); | $file), | ||||
| $this->renderMessages(pht('MISSING MESSAGES'), $missing), | |||||
| $this->renderMessages(pht('SURPLUS MESSAGES'), $surprising))); | |||||
| } | } | ||||
| } | } | ||||
| private function compareTransform($expected, $actual) { | private function compareTransform($expected, $actual) { | ||||
| if (!strlen($expected)) { | if (!strlen($expected)) { | ||||
| return; | return; | ||||
| } | } | ||||
| $this->assertEqual( | $this->assertEqual( | ||||
| $expected, | $expected, | ||||
| $actual, | $actual, | ||||
| pht('File as patched by lint did not match the expected patched file.')); | pht('File as patched by lint did not match the expected patched file.')); | ||||
| } | } | ||||
| /** | /** | ||||
| * Compare properties of @{class:ArcanistLintMessage} instances. | * Compare properties of @{class:ArcanistLintMessage} instances. | ||||
| * | * | ||||
| * The expectation is that if one (or both) of the properties is null, then | |||||
| * we don't care about its value. | |||||
| * | |||||
| * @param wild | * @param wild | ||||
| * @param wild | * @param wild | ||||
| * @return bool | * @return bool | ||||
| */ | */ | ||||
| private static function compareLintMessageProperty($x, $y) { | private static function compareLintMessageProperty($x, $y) { | ||||
| return $x === null || $y === null || $x === $y; | if ($x === null) { | ||||
| return true; | |||||
| } | |||||
| return ($x === $y); | |||||
| } | |||||
| private function renderMessages($header, array $messages) { | |||||
| if (!$messages) { | |||||
| $display = tsprintf( | |||||
| "%s\n", | |||||
| pht('(No messages.)')); | |||||
| } else { | |||||
| $lines = array(); | |||||
| foreach ($messages as $message) { | |||||
| $line = $message->getLine(); | |||||
| if ($line === null) { | |||||
| $display_line = pht('<null>'); | |||||
| } else { | |||||
| $display_line = $line; | |||||
| } | |||||
| $char = $message->getChar(); | |||||
| if ($char === null) { | |||||
| $display_char = pht('<null>'); | |||||
| } else { | |||||
| $display_char = $char; | |||||
| } | |||||
| $code = $message->getCode(); | |||||
| $name = $message->getName(); | |||||
| if ($code !== null && $name !== null) { | |||||
| $display_code = pht('%s: %s', $code, $name); | |||||
| } else if ($code !== null) { | |||||
| $display_code = pht('%s', $code); | |||||
| } else { | |||||
| $display_code = null; | |||||
| } | |||||
| $severity = $message->getSeverity(); | |||||
| if ($display_code === null) { | |||||
| $display_message = pht( | |||||
| 'Message with severity "%s" at "%s:%s"', | |||||
| $severity, | |||||
| $display_line, | |||||
| $display_char); | |||||
| } else { | |||||
| $display_message = pht( | |||||
| 'Message with severity "%s" at "%s:%s" (%s)', | |||||
| $severity, | |||||
| $display_line, | |||||
| $display_char, | |||||
| $display_code); | |||||
| } | |||||
| $lines[] = tsprintf( | |||||
| " %s\n", | |||||
| $display_message); | |||||
| } | |||||
| $display = implode('', $lines); | |||||
| } | |||||
| return tsprintf( | |||||
| "%s\n%B\n", | |||||
| $header, | |||||
| $display); | |||||
| } | } | ||||
| } | } | ||||