Mercurial > hg > isophonics-drupal-site
diff vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php @ 17:129ea1e6d783
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:21:36 +0000 |
parents | |
children | af1871eacc83 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/squizlabs/php_codesniffer/tests/Standards/AbstractSniffUnitTest.php Thu Feb 28 13:21:36 2019 +0000 @@ -0,0 +1,450 @@ +<?php +/** + * An abstract class that all sniff unit tests must extend. + * + * A sniff unit test checks a .inc file for expected violations of a single + * coding standard. Expected errors and warnings that are not found, or + * warnings and errors that are not expected, are considered test failures. + * + * @author Greg Sherwood <gsherwood@squiz.net> + * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Tests\Standards; + +use PHP_CodeSniffer\Config; +use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Files\LocalFile; +use PHP_CodeSniffer\Util\Common; +use PHPUnit\Framework\TestCase; + +abstract class AbstractSniffUnitTest extends TestCase +{ + + /** + * Enable or disable the backup and restoration of the $GLOBALS array. + * Overwrite this attribute in a child class of TestCase. + * Setting this attribute in setUp() has no effect! + * + * @var boolean + */ + protected $backupGlobals = false; + + /** + * The path to the standard's main directory. + * + * @var string + */ + public $standardsDir = null; + + /** + * The path to the standard's test directory. + * + * @var string + */ + public $testsDir = null; + + + /** + * Sets up this unit test. + * + * @return void + */ + protected function setUp() + { + $class = get_class($this); + $this->standardsDir = $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$class]; + $this->testsDir = $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$class]; + + }//end setUp() + + + /** + * Get a list of all test files to check. + * + * These will have the same base as the sniff name but different extensions. + * We ignore the .php file as it is the class. + * + * @param string $testFileBase The base path that the unit tests files will have. + * + * @return string[] + */ + protected function getTestFiles($testFileBase) + { + $testFiles = []; + + $dir = substr($testFileBase, 0, strrpos($testFileBase, DIRECTORY_SEPARATOR)); + $di = new \DirectoryIterator($dir); + + foreach ($di as $file) { + $path = $file->getPathname(); + if (substr($path, 0, strlen($testFileBase)) === $testFileBase) { + if ($path !== $testFileBase.'php' && substr($path, -5) !== 'fixed' && substr($path, -4) !== '.bak') { + $testFiles[] = $path; + } + } + } + + // Put them in order. + sort($testFiles); + + return $testFiles; + + }//end getTestFiles() + + + /** + * Should this test be skipped for some reason. + * + * @return boolean + */ + protected function shouldSkipTest() + { + return false; + + }//end shouldSkipTest() + + + /** + * Tests the extending classes Sniff class. + * + * @return void + * @throws \PHPUnit\Framework\Exception + */ + final public function testSniff() + { + // Skip this test if we can't run in this environment. + if ($this->shouldSkipTest() === true) { + $this->markTestSkipped(); + } + + $sniffCode = Common::getSniffCode(get_class($this)); + list($standardName, $categoryName, $sniffName) = explode('.', $sniffCode); + + $testFileBase = $this->testsDir.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'UnitTest.'; + + // Get a list of all test files to check. + $testFiles = $this->getTestFiles($testFileBase); + $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'][] = $testFiles; + + if (isset($GLOBALS['PHP_CODESNIFFER_CONFIG']) === true) { + $config = $GLOBALS['PHP_CODESNIFFER_CONFIG']; + } else { + $config = new Config(); + $config->cache = false; + $GLOBALS['PHP_CODESNIFFER_CONFIG'] = $config; + } + + $config->standards = [$standardName]; + $config->sniffs = [$sniffCode]; + $config->ignored = []; + + if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS']) === false) { + $GLOBALS['PHP_CODESNIFFER_RULESETS'] = []; + } + + if (isset($GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]) === false) { + $ruleset = new Ruleset($config); + $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName] = $ruleset; + } + + $ruleset = $GLOBALS['PHP_CODESNIFFER_RULESETS'][$standardName]; + + $sniffFile = $this->standardsDir.DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR.$categoryName.DIRECTORY_SEPARATOR.$sniffName.'Sniff.php'; + + $sniffClassName = substr(get_class($this), 0, -8).'Sniff'; + $sniffClassName = str_replace('\Tests\\', '\Sniffs\\', $sniffClassName); + $sniffClassName = Common::cleanSniffClass($sniffClassName); + + $restrictions = [strtolower($sniffClassName) => true]; + $ruleset->registerSniffs([$sniffFile], $restrictions, []); + $ruleset->populateTokenListeners(); + + $failureMessages = []; + foreach ($testFiles as $testFile) { + $filename = basename($testFile); + $oldConfig = $config->getSettings(); + + try { + $this->setCliValues($filename, $config); + $phpcsFile = new LocalFile($testFile, $ruleset, $config); + $phpcsFile->process(); + } catch (RuntimeException $e) { + $this->fail('An unexpected exception has been caught: '.$e->getMessage()); + } + + $failures = $this->generateFailureMessages($phpcsFile); + $failureMessages = array_merge($failureMessages, $failures); + + if ($phpcsFile->getFixableCount() > 0) { + // Attempt to fix the errors. + $phpcsFile->fixer->fixFile(); + $fixable = $phpcsFile->getFixableCount(); + if ($fixable > 0) { + $failureMessages[] = "Failed to fix $fixable fixable violations in $filename"; + } + + // Check for a .fixed file to check for accuracy of fixes. + $fixedFile = $testFile.'.fixed'; + if (file_exists($fixedFile) === true) { + $diff = $phpcsFile->fixer->generateDiff($fixedFile); + if (trim($diff) !== '') { + $filename = basename($testFile); + $fixedFilename = basename($fixedFile); + $failureMessages[] = "Fixed version of $filename does not match expected version in $fixedFilename; the diff is\n$diff"; + } + } + } + + // Restore the config. + $config->setSettings($oldConfig); + }//end foreach + + if (empty($failureMessages) === false) { + $this->fail(implode(PHP_EOL, $failureMessages)); + } + + }//end testSniff() + + + /** + * Generate a list of test failures for a given sniffed file. + * + * @param \PHP_CodeSniffer\Files\LocalFile $file The file being tested. + * + * @return array + * @throws \PHP_CodeSniffer\Exceptions\RuntimeException + */ + public function generateFailureMessages(LocalFile $file) + { + $testFile = $file->getFilename(); + + $foundErrors = $file->getErrors(); + $foundWarnings = $file->getWarnings(); + $expectedErrors = $this->getErrorList(basename($testFile)); + $expectedWarnings = $this->getWarningList(basename($testFile)); + + if (is_array($expectedErrors) === false) { + throw new RuntimeException('getErrorList() must return an array'); + } + + if (is_array($expectedWarnings) === false) { + throw new RuntimeException('getWarningList() must return an array'); + } + + /* + We merge errors and warnings together to make it easier + to iterate over them and produce the errors string. In this way, + we can report on errors and warnings in the same line even though + it's not really structured to allow that. + */ + + $allProblems = []; + $failureMessages = []; + + foreach ($foundErrors as $line => $lineErrors) { + foreach ($lineErrors as $column => $errors) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundErrorsTemp = []; + foreach ($allProblems[$line]['found_errors'] as $foundError) { + $foundErrorsTemp[] = $foundError; + } + + $errorsTemp = []; + foreach ($errors as $foundError) { + $errorsTemp[] = $foundError['message'].' ('.$foundError['source'].')'; + + $source = $foundError['source']; + if (in_array($source, $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES']) === false) { + $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'][] = $source; + } + + if ($foundError['fixable'] === true + && in_array($source, $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']) === false + ) { + $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'][] = $source; + } + } + + $allProblems[$line]['found_errors'] = array_merge($foundErrorsTemp, $errorsTemp); + }//end foreach + + if (isset($expectedErrors[$line]) === true) { + $allProblems[$line]['expected_errors'] = $expectedErrors[$line]; + } else { + $allProblems[$line]['expected_errors'] = 0; + } + + unset($expectedErrors[$line]); + }//end foreach + + foreach ($expectedErrors as $line => $numErrors) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_errors'] = $numErrors; + } + + foreach ($foundWarnings as $line => $lineWarnings) { + foreach ($lineWarnings as $column => $warnings) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $foundWarningsTemp = []; + foreach ($allProblems[$line]['found_warnings'] as $foundWarning) { + $foundWarningsTemp[] = $foundWarning; + } + + $warningsTemp = []; + foreach ($warnings as $warning) { + $warningsTemp[] = $warning['message'].' ('.$warning['source'].')'; + } + + $allProblems[$line]['found_warnings'] = array_merge($foundWarningsTemp, $warningsTemp); + }//end foreach + + if (isset($expectedWarnings[$line]) === true) { + $allProblems[$line]['expected_warnings'] = $expectedWarnings[$line]; + } else { + $allProblems[$line]['expected_warnings'] = 0; + } + + unset($expectedWarnings[$line]); + }//end foreach + + foreach ($expectedWarnings as $line => $numWarnings) { + if (isset($allProblems[$line]) === false) { + $allProblems[$line] = [ + 'expected_errors' => 0, + 'expected_warnings' => 0, + 'found_errors' => [], + 'found_warnings' => [], + ]; + } + + $allProblems[$line]['expected_warnings'] = $numWarnings; + } + + // Order the messages by line number. + ksort($allProblems); + + foreach ($allProblems as $line => $problems) { + $numErrors = count($problems['found_errors']); + $numWarnings = count($problems['found_warnings']); + $expectedErrors = $problems['expected_errors']; + $expectedWarnings = $problems['expected_warnings']; + + $errors = ''; + $foundString = ''; + + if ($expectedErrors !== $numErrors || $expectedWarnings !== $numWarnings) { + $lineMessage = "[LINE $line]"; + $expectedMessage = 'Expected '; + $foundMessage = 'in '.basename($testFile).' but found '; + + if ($expectedErrors !== $numErrors) { + $expectedMessage .= "$expectedErrors error(s)"; + $foundMessage .= "$numErrors error(s)"; + if ($numErrors !== 0) { + $foundString .= 'error(s)'; + $errors .= implode(PHP_EOL.' -> ', $problems['found_errors']); + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= ' and '; + $foundMessage .= ' and '; + if ($numWarnings !== 0) { + if ($foundString !== '') { + $foundString .= ' and '; + } + } + } + } + + if ($expectedWarnings !== $numWarnings) { + $expectedMessage .= "$expectedWarnings warning(s)"; + $foundMessage .= "$numWarnings warning(s)"; + if ($numWarnings !== 0) { + $foundString .= 'warning(s)'; + if (empty($errors) === false) { + $errors .= PHP_EOL.' -> '; + } + + $errors .= implode(PHP_EOL.' -> ', $problems['found_warnings']); + } + } + + $fullMessage = "$lineMessage $expectedMessage $foundMessage."; + if ($errors !== '') { + $fullMessage .= " The $foundString found were:".PHP_EOL." -> $errors"; + } + + $failureMessages[] = $fullMessage; + }//end if + }//end foreach + + return $failureMessages; + + }//end generateFailureMessages() + + + /** + * Get a list of CLI values to set before the file is tested. + * + * @param string $filename The name of the file being tested. + * @param \PHP_CodeSniffer\Config $config The config data for the run. + * + * @return void + */ + public function setCliValues($filename, $config) + { + return; + + }//end setCliValues() + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @return array<int, int> + */ + abstract protected function getErrorList(); + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @return array<int, int> + */ + abstract protected function getWarningList(); + + +}//end class