diff --git a/.travis.yml b/.travis.yml index e078e89011dc66acc22d89eabcb1ee9c77b61f21..8ef207921448faabc136049b85b34138492c5689 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,7 @@ env: - TEST_SUITE=integration_part_1 - TEST_SUITE=integration_part_2 - TEST_SUITE=integration_integrity - - TEST_SUITE=static_phpcs - - TEST_SUITE=static_annotation + - TEST_SUITE=static cache: apt: true directories: @@ -21,9 +20,9 @@ cache: matrix: exclude: - php: 5.6 - env: TEST_SUITE=static_phpcs - - php: 5.6 - env: TEST_SUITE=static_annotation + env: TEST_SUITE=static + - php: 7.0 + env: TEST_SUITE=static before_install: - sudo apt-get update -qq - sudo apt-get install -y -qq postfix @@ -68,6 +67,4 @@ script: # Integration integrity tests - sh -c "if [ '$TEST_SUITE' = 'integration_integrity' ]; then cd dev/tests/integration/; ./../../../vendor/bin/phpunit -c phpunit.xml.dist testsuite/Magento/Test/Integrity; fi" # Static tests [Code Style] - - sh -c "if [ '$TEST_SUITE' = 'static_phpcs' ]; then cd dev/tests/static; ./../../../vendor/bin/phpunit -c phpunit.xml.dist --filter 'Magento\\\\Test\\\\Php\\\\LiveCodeTest::testCodeStyle'; fi" - # Static tests [Code Style] - - sh -c "if [ '$TEST_SUITE' = 'static_annotation' ]; then cd dev/tests/static; ./../../../vendor/bin/phpunit -c phpunit.xml.dist --filter 'Magento\\\\Test\\\\Php\\\\LiveCodeTest::testAnnotationStandard'; fi" + - sh -c "if [ '$TEST_SUITE' = 'static' ]; then cd dev/tests/static/; php get_github_changes.php --output-file='$TRAVIS_BUILD_DIR/dev/tests/static/testsuite/Magento/Test/_files/changed_files_ce.txt' --base-path='$TRAVIS_BUILD_DIR' --repo='https://github.com/magento/magento2.git'; cd dev/tests/static; ./../../../vendor/bin/phpunit -c phpunit.xml.dist --filter 'Magento\\\\Test\\\\Php\\\\LiveCodeTest'; fi" diff --git a/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeMessDetector.php b/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeMessDetector.php index ed5c2b33fdb300f95da2efff0e1ceb3835ad1575..9a53e422280ea7b0d589d0f79d24b37fdc6ce36e 100644 --- a/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeMessDetector.php +++ b/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeMessDetector.php @@ -61,7 +61,7 @@ class CodeMessDetector implements ToolInterface $commandLineArguments = [ 'run_file_mock', //emulate script name in console arguments implode(',', $whiteList), - 'xml', //report format + 'text', //report format $this->rulesetFile, '--reportfile', $this->reportFile, diff --git a/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeSniffer.php b/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeSniffer.php index 8fad6ea044f991990631bfc98b90822e7875ff3f..7f6f02ae5b117c4fee7e6ae67e58c38f8d79d9f7 100644 --- a/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeSniffer.php +++ b/dev/tests/static/framework/Magento/TestFramework/CodingStandard/Tool/CodeSniffer.php @@ -88,9 +88,8 @@ class CodeSniffer implements ToolInterface, ExtensionInterface $settings['files'] = $whiteList; $settings['standard'] = [$this->rulesetDir]; $settings['extensions'] = $this->extensions; - $settings['reportFile'] = $this->reportFile; $settings['warningSeverity'] = 0; - $settings['reports']['checkstyle'] = null; + $settings['reports']['full'] = $this->reportFile; $this->wrapper->setValues($settings); diff --git a/dev/tests/static/get_github_changes.php b/dev/tests/static/get_github_changes.php new file mode 100644 index 0000000000000000000000000000000000000000..3c4130a840530689f3295920d6ff5081f4032753 --- /dev/null +++ b/dev/tests/static/get_github_changes.php @@ -0,0 +1,293 @@ +<?php + +/** + * Script to get changes between feature branch and the mainline + * + * @category dev + * @package build + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +// @codingStandardsIgnoreFile + +define( +'USAGE', +<<<USAGE + php -f get_github_changes.php -- + --output-file="<output_file>" + --base-path="<base_path>" + --repo="<main_repo>" + [--file-formats="<comma_separated_list_of_formats>"] + +USAGE +); + +$options = getopt('', ['output-file:', 'base-path:', 'repo:', 'file-formats:']); + +$requiredOptions = ['output-file', 'base-path', 'repo']; +if (!validateInput($options, $requiredOptions)) { + echo USAGE; + exit(1); +} + +$fileFormats = explode(',', isset($options['file-formats']) ? $options['file-formats'] : 'php'); + +$mainline = 'mainline_' . (string)rand(0, 9999); +$repo = getRepo($options, $mainline); +$changes = retrieveChangesAcrossForks($mainline, $repo); +$changedFiles = getChangedFiles($changes, $fileFormats); +generateChangedFilesList($options['output-file'], $changedFiles); +cleanup($repo, $mainline); + +/** + * Generates a file containing changed files + * + * @param string $outputFile + * @param array $changedFiles + * @return void + */ +function generateChangedFilesList($outputFile, $changedFiles) +{ + $changedFilesList = fopen($outputFile, 'w'); + foreach ($changedFiles as $file) { + fwrite($changedFilesList, $file . PHP_EOL); + } + fclose($changedFilesList); +} + +/** + * Gets list of changed files + * + * @param array $changes + * @param array $fileFormats + * @return array + */ +function getChangedFiles($changes, $fileFormats) +{ + $files = []; + foreach ($changes as $fileName) { + foreach ($fileFormats as $format) { + $isFileFormat = strpos($fileName, '.' . $format); + if ($isFileFormat) { + $files[] = $fileName; + } + } + } + + return $files; +} + +/** + * Retrieves changes across forks + * + * @param array $options + * @return array + * @throws Exception + */ +function getRepo($options, $mainline) +{ + $repo = new GitRepo($options['base-path']); + $repo->addRemote($mainline, $options['repo']); + $repo->fetch($mainline); + return $repo; +} + +/** + * @param $repo + * @return array + */ +function retrieveChangesAcrossForks($mainline, $repo) +{ + return $repo->compareChanges($mainline, 'develop'); +} + +/** + * Deletes temporary "base" repo + * + * @param GitRepo $repo + * @param string $repo + */ +function cleanup($repo, $mainline) +{ + $repo->removeRemote($mainline); +} + +/** + * Validates input options based on required options + * + * @param array $options + * @param array $requiredOptions + * @return bool + */ +function validateInput(array $options, array $requiredOptions) +{ + foreach ($requiredOptions as $requiredOption) { + if (!isset($options[$requiredOption]) || empty($options[$requiredOption])) { + return false; + } + } + return true; +} + + +class GitRepo +{ + /** + * Absolute path to git project + * + * @var string + */ + private $workTree; + + /** + * @var array + */ + private $remoteList = []; + + /** + * @param string $workTree absolute path to git project + */ + public function __construct($workTree) + { + if (empty($workTree) || !is_dir($workTree)) { + throw new UnexpectedValueException('Working tree should be a valid path to directory'); + } + $this->workTree = $workTree; + } + + /** + * Adds remote + * + * @param string $alias + * @param string $url + */ + public function addRemote($alias, $url) + { + if (isset($this->remoteList[$alias])) { + return; + } + $this->remoteList[$alias] = $url; + + $this->call(sprintf('remote add %s %s', $alias, $url)); + } + + /** + * Remove remote + * + * @param string $alias + */ + public function removeRemote($alias) + { + if (isset($this->remoteList[$alias])) { + $this->call(sprintf('remote remove %s', $alias)); + } + } + + /** + * Fetches remote + * + * @param string $remoteAlias + */ + public function fetch($remoteAlias) + { + if (!isset($this->remoteList[$remoteAlias])) { + throw new LogicException('Alias is not defined'); + } + + $this->call(sprintf('fetch %s', $remoteAlias)); + } + + /** + * Returns files changes between branch + * + * @param string $remoteAlias + * @param string $remoteBranch + * @return array + */ + public function compareChanges($remoteAlias, $remoteBranch) + { + if (!isset($this->remoteList[$remoteAlias])) { + throw new LogicException('Alias is not defined'); + } + + $result = $this->call(sprintf('log %s/%s..HEAD --name-status --oneline', $remoteAlias, $remoteBranch)); + + return is_array($result) + ? $this->filterChangedBackFiles( + $this->filterChangedFiles($result), + $remoteAlias, + $remoteBranch + ) + : []; + } + + /** + * Filters git cli output for changed files + * + * @param array $changes + * @return array + */ + protected function filterChangedFiles(array $changes) + { + $changedFilesMasks = [ + 'M' => "M\t", + 'A' => "A\t" + ]; + $filteredChanges = []; + foreach ($changes as $fileName) { + foreach ($changedFilesMasks as $mask) { + if (strpos($fileName, $mask) === 0) { + $fileName = str_replace($mask, '', $fileName); + $fileName = trim($fileName); + if (!in_array($fileName, $filteredChanges) && is_file($this->workTree . '/' . $fileName)) { + $filteredChanges[] = $fileName; + } + break; + } + } + } + return $filteredChanges; + } + + /** + * Makes a diff of file for specified remote/branch and filters only those have real changes + * + * @param array $changes + * @param string $remoteAlias + * @param string $remoteBranch + * @return array + */ + protected function filterChangedBackFiles(array $changes, $remoteAlias, $remoteBranch) + { + $filteredChanges = []; + foreach ($changes as $fileName) { + $result = $this->call(sprintf( + 'diff HEAD %s/%s -- %s', $remoteAlias, $remoteBranch, $this->workTree .'/'. $fileName) + ); + if ($result) { + $filteredChanges[] = $fileName; + } + } + + return $filteredChanges; + } + + /** + * Makes call ro git cli + * + * @param string $command + * @return mixed + */ + private function call($command) + { + $gitCmd = sprintf( + 'git --git-dir %s --work-tree %s', + escapeshellarg("{$this->workTree}/.git"), + escapeshellarg($this->workTree) + ); + $tmp = sprintf('%s %s', $gitCmd, $command); + exec(escapeshellcmd($tmp), $output); + return $output; + } +} diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php index 2fd1427270d331c3a2fdbce6a2a76f59bb154775..f91001f79bd84f31003d8a119b29a7abb92ffe79 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/ObsoleteCodeTest.php @@ -109,7 +109,7 @@ class ObsoleteCodeTest extends \PHPUnit_Framework_TestCase public function testPhpFiles() { $invoker = new AggregateInvoker($this); - $changedFiles = ChangedFiles::getPhpFiles(__DIR__ . '/_files/changed_files*'); + $changedFiles = ChangedFiles::getPhpFiles(__DIR__ . '/../_files/changed_files*'); $blacklistFiles = $this->getBlacklistFiles(); foreach ($blacklistFiles as $blacklistFile) { unset($changedFiles[BP . $blacklistFile]); diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php index cb6e9e69d8288cc3a82a19a4dd3247c1e5a8f29c..c08d1458b183d6ddc5187eb4570791d62db39240 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/RestrictedCodeTest.php @@ -74,7 +74,7 @@ class RestrictedCodeTest extends \PHPUnit_Framework_TestCase public function testPhpFiles() { $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this); - $testFiles = \Magento\TestFramework\Utility\ChangedFiles::getPhpFiles(__DIR__ . '/_files/changed_files*'); + $testFiles = \Magento\TestFramework\Utility\ChangedFiles::getPhpFiles(__DIR__ . '/../_files/changed_files*'); foreach (self::$_fixtureFiles as $fixtureFile) { if (array_key_exists(BP . $fixtureFile, $testFiles)) { unset($testFiles[BP . $fixtureFile]); diff --git a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php index c667e01ecad22a00edf0c2b7c0b838bc43a780ba..fa87da37dce8f7598561d295d51ea5d126aac94f 100644 --- a/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php +++ b/dev/tests/static/testsuite/Magento/Test/Php/LiveCodeTest.php @@ -57,7 +57,7 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase $directoriesToCheck = Files::init()->readLists(__DIR__ . '/_files/whitelist/common.txt'); $changedFiles = []; - foreach (glob(__DIR__ . '/_files/changed_files*') as $listFile) { + foreach (glob(__DIR__ . '/../_files/changed_files*') as $listFile) { $changedFiles = array_merge($changedFiles, file($listFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)); } array_walk( @@ -97,7 +97,7 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase */ public function testCodeStylePsr2() { - $reportFile = self::$reportDir . '/phpcs_psr2_report.xml'; + $reportFile = self::$reportDir . '/phpcs_psr2_report.txt'; $wrapper = new Wrapper(); $codeSniffer = new CodeSniffer('PSR2', $reportFile, $wrapper); if (!$codeSniffer->canRun()) { @@ -109,10 +109,15 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase $result = $codeSniffer->run(self::getWhitelist()); + $output = ""; + if (file_exists($reportFile)) { + $handle = fopen($reportFile, 'r'); + $output = fread($handle, filesize($reportFile)); + } $this->assertEquals( 0, $result, - "PHP Code Sniffer has found {$result} error(s): See detailed report in {$reportFile}" + "PHP Code Sniffer has found {$result} error(s): " . PHP_EOL . $output ); } @@ -123,7 +128,7 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase */ public function testCodeStyle() { - $reportFile = self::$reportDir . '/phpcs_report.xml'; + $reportFile = self::$reportDir . '/phpcs_report.txt'; $wrapper = new Wrapper(); $codeSniffer = new CodeSniffer(realpath(__DIR__ . '/_files/phpcs'), $reportFile, $wrapper); if (!$codeSniffer->canRun()) { @@ -131,10 +136,17 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase } $codeSniffer->setExtensions(['php', 'phtml']); $result = $codeSniffer->run(self::getWhitelist(['php', 'phtml'])); + + $output = ""; + if (file_exists($reportFile)) { + $handle = fopen($reportFile, 'r'); + $output = fread($handle, filesize($reportFile)); + } + $this->assertEquals( 0, $result, - "PHP Code Sniffer has found {$result} error(s): See detailed report in {$reportFile}" + "PHP Code Sniffer has found {$result} error(s): " . PHP_EOL . $output ); } @@ -146,7 +158,7 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase */ public function testAnnotationStandard() { - $reportFile = self::$reportDir . '/phpcs_annotations_report.xml'; + $reportFile = self::$reportDir . '/phpcs_annotations_report.txt'; $wrapper = new Wrapper(); $codeSniffer = new CodeSniffer( realpath(__DIR__ . '/../../../../framework/Magento/ruleset.xml'), @@ -158,10 +170,15 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase } $result = $codeSniffer->run(self::getWhitelist(['php'])); + $output = ""; + if (file_exists($reportFile)) { + $handle = fopen($reportFile, 'r'); + $output = fread($handle, filesize($reportFile)); + } $this->assertEquals( 0, $result, - "PHP Code Sniffer has found {$result} error(s): See detailed report in {$reportFile}" + "PHP Code Sniffer has found {$result} error(s): " . PHP_EOL . $output ); } @@ -172,17 +189,26 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase */ public function testCodeMess() { - $reportFile = self::$reportDir . '/phpmd_report.xml'; + $reportFile = self::$reportDir . '/phpmd_report.txt'; $codeMessDetector = new CodeMessDetector(realpath(__DIR__ . '/_files/phpmd/ruleset.xml'), $reportFile); if (!$codeMessDetector->canRun()) { $this->markTestSkipped('PHP Mess Detector is not available.'); } + + $result = $codeMessDetector->run(self::getWhitelist(['php'])); + + $output = ""; + if (file_exists($reportFile)) { + $handle = fopen($reportFile, 'r'); + $output = fread($handle, filesize($reportFile)); + } + $this->assertEquals( Command::EXIT_SUCCESS, - $codeMessDetector->run(self::getWhitelist(['php'])), - "PHP Code Mess has found error(s): See detailed report in {$reportFile}" + $result, + "PHP Code Mess has found error(s):" . PHP_EOL . $output ); // delete empty reports @@ -212,9 +238,17 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase $copyPasteDetector->setBlackList($blackList); + $result = $copyPasteDetector->run([BP]); + + $output = ""; + if (file_exists($reportFile)) { + $handle = fopen($reportFile, 'r'); + $output = fread($handle, filesize($reportFile)); + } + $this->assertTrue( - $copyPasteDetector->run([BP]), - "PHP Copy/Paste Detector has found error(s): See detailed report in {$reportFile}" + $result, + "PHP Copy/Paste Detector has found error(s):" . PHP_EOL . $output ); } @@ -330,4 +364,4 @@ class LiveCodeTest extends PHPUnit_Framework_TestCase } return $methods; } -} +} \ No newline at end of file diff --git a/dev/tests/static/testsuite/Magento/Test/_files/.gitignore b/dev/tests/static/testsuite/Magento/Test/_files/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..11b4bb12f5316d10b506a44104228630cf92a52f --- /dev/null +++ b/dev/tests/static/testsuite/Magento/Test/_files/.gitignore @@ -0,0 +1,2 @@ +/* +!/.gitignore \ No newline at end of file