1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-25 08:12:40 +01:00

Make lint tests handle paths better and distinguish between "0" and "null" more carefully

Summary:
Ref T13543. Currently, the `cpplint` tests do not function because `cpplint` is passed a path which does not end in a suffix it recognizes.

Change the tempfile / path code to pass `linter path/to/example.c`-style linters a path they expect.

Then, correct some older code which was playing it fast-and-loose with "null" vs "0".

Test Plan: Ran `arc unit --everything`, got a clean bill of health on all the linters I have installed. (This is probably not all tests, since I have only a subset of linters installed locally that we have code for.)

Maniphest Tasks: T13543

Differential Revision: https://secure.phabricator.com/D21291
This commit is contained in:
epriestley 2020-05-27 12:07:49 -07:00
parent e69aa32603
commit fce72b9c89
10 changed files with 122 additions and 66 deletions

View file

@ -261,8 +261,7 @@ final class ArcanistTextLinter extends ArcanistLinter {
self::LINT_TRAILING_WHITESPACE, self::LINT_TRAILING_WHITESPACE,
pht( pht(
'This line contains trailing whitespace. Consider setting '. 'This line contains trailing whitespace. Consider setting '.
'up your editor to automatically remove trailing whitespace, '. 'up your editor to automatically remove trailing whitespace.'),
'you will save time.'),
$string, $string,
''); '');
} }

View file

@ -64,8 +64,6 @@ abstract class ArcanistLinterTestCase extends PhutilTestCase {
$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 {
@ -87,6 +85,14 @@ abstract class ArcanistLinterTestCase extends PhutilTestCase {
$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;
@ -97,7 +103,6 @@ abstract class ArcanistLinterTestCase extends PhutilTestCase {
} }
$dir = dirname($full_path); $dir = dirname($full_path);
$path = basename($full_path);
$working_copy = ArcanistWorkingCopyIdentity::newFromRootAndConfigFile( $working_copy = ArcanistWorkingCopyIdentity::newFromRootAndConfigFile(
$dir, $dir,
@ -106,26 +111,25 @@ abstract class ArcanistLinterTestCase extends PhutilTestCase {
$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),
@ -188,8 +192,19 @@ abstract class ArcanistLinterTestCase extends PhutilTestCase {
$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);
@ -256,46 +271,14 @@ abstract class ArcanistLinterTestCase extends PhutilTestCase {
} }
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)));
} }
} }
@ -312,15 +295,78 @@ abstract class ArcanistLinterTestCase extends PhutilTestCase {
/** /**
* 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);
} }
} }

View file

@ -1,5 +1,5 @@
~~~~~~~~~~ ~~~~~~~~~~
warning:0:0:CHMOD1:Invalid Executable warning:::CHMOD1:Invalid Executable
~~~~~~~~~~ ~~~~~~~~~~
~~~~~~~~~~ ~~~~~~~~~~
{"mode": "0755"} {"mode": "0755"}

View file

@ -1,10 +1,21 @@
#include "library.cpp" #include "library.cpp"
#include <stdio> #include <stdio>
void main()
{
}
~~~~~~~~~
warning
warning:2
warning:5
~~~~~~~~~~
#include "library.cpp"
#include <stdio>
void main() void main()
{ {
} }
~~~~~~~~~~ ~~~~~~~~~~
warning:0: {
warning:2: "path": "example.cpp"
warning:5: }

View file

@ -1,5 +1,5 @@
~~~~~~~~~~ ~~~~~~~~~~
error:0:0:NAME1:Bad Filename error:::NAME1:Bad Filename
~~~~~~~~~~ ~~~~~~~~~~
~~~~~~~~~~ ~~~~~~~~~~
{"path": "bad@filename"} {"path": "bad@filename"}

View file

@ -4,4 +4,4 @@ function f() {
$this = "cannot be re-assigned"; $this = "cannot be re-assigned";
} }
~~~~~~~~~ ~~~~~~~~~
error:4:0:PHP2:Fatal Error error:4::PHP2:Fatal Error

View file

@ -4,4 +4,4 @@ function f() {
this is bad syntax; this is bad syntax;
} }
~~~~~~~~~ ~~~~~~~~~
error:4:0:PHP1:Parse Error error:4::PHP1:Parse Error

View file

@ -1,4 +1,4 @@
def hello() def hello()
puts "hello world" puts "hello world"
~~~~~~~~~~ ~~~~~~~~~~
error:2:0:RUBY:Syntax Error error:2::RUBY:Syntax Error

View file

@ -1,4 +1,4 @@
~~~~~~~~~~ ~~~~~~~~~~
error:0:0:TXT10:Empty File error:::TXT10:Empty File

View file

@ -1,4 +1,4 @@
<?php <?php
~~~~~~~~~~ ~~~~~~~~~~
warning:0:0:XHP82:Empty File warning:::XHP82:Empty File