diff --git a/Installer.php b/Installer.php deleted file mode 100644 index a91dedf..0000000 --- a/Installer.php +++ /dev/null @@ -1,148 +0,0 @@ -io = $io; - } - - public function deactivate(Composer $composer, IOInterface $io) - { - } - - public function uninstall(Composer $composer, IOInterface $io) { - $this->deleteFile(); - } - - protected function isOperationOnC3(PackageEvent $event) - { - if (static::composerV2()) { - return true; - } - $name = ''; - - if ($event->getOperation() instanceof InstallOperation) { - list(, $name) = explode('/', $event->getOperation()->getPackage()->getName()); - } elseif ($event->getOperation() instanceof UpdateOperation) { - list(, $name) = explode('/', $event->getOperation()->getTargetPackage()->getName()); - } elseif ($event->getOperation() instanceof UninstallOperation) { - list(, $name) = explode('/', $event->getOperation()->getPackage()->getName()); - } - - return $name === 'c3'; - } - - public static function getSubscribedEvents() - { - if (static::composerV2()) { - return [ - ScriptEvents::POST_INSTALL_CMD => [ - ['copyC3V2', 0] - ], - ScriptEvents::POST_UPDATE_CMD => [ - ['askForUpdateV2', 0] - ], - ]; - } - return [ - PackageEvents::POST_PACKAGE_INSTALL => [ - ['copyC3', 0] - ], - PackageEvents::POST_PACKAGE_UPDATE => [ - ['askForUpdate', 0] - ], - PackageEvents::POST_PACKAGE_UNINSTALL => [ - ['deleteC3', 0] - ] - ]; - } - - public function copyC3(PackageEvent $event) - { - if (!$this->isOperationOnC3($event)) { - return; - } - - $this->copyC3V2($event); - } - - public function copyC3V2(Event $event) - { - if ($this->c3NotChanged()) { - $this->io->write("[codeception/c3] c3.php is already up-to-date"); - return; - } - if (file_exists(getcwd() . DIRECTORY_SEPARATOR . 'c3.php')) { - $replace = $this->io->askConfirmation("c3.php has changed Do you want to replace c3.php with latest version?", false); - if (!$replace) { - return; - } - } - - $this->io->write("[codeception/c3] Copying c3.php to the root of your project..."); - copy(__DIR__ . DIRECTORY_SEPARATOR . 'c3.php', getcwd() . DIRECTORY_SEPARATOR.'c3.php'); - $this->io->write("[codeception/c3] Include c3.php into index.php in order to collect codecoverage from server scripts"); - } - - public function askForUpdate(PackageEvent $event) - { - if (!$this->isOperationOnC3($event) || $this->c3NotChanged()) { - return; - } - $this->copyC3($event); - } - - public function askForUpdateV2(Event $event) - { - if ($this->c3NotChanged()) { - return; - } - $this->copyC3V2($event); - } - - private function c3NotChanged() - { - return file_exists(getcwd() . DIRECTORY_SEPARATOR . 'c3.php') && - md5_file(__DIR__ . DIRECTORY_SEPARATOR . 'c3.php') === md5_file(getcwd() . DIRECTORY_SEPARATOR . 'c3.php'); - } - - public function deleteC3(PackageEvent $event) - { - if (!$this->isOperationOnC3($event)) { - return; - } - $this->deleteFile(); - } - - private function deleteFile() { - if (file_exists(getcwd() . DIRECTORY_SEPARATOR . 'c3.php')) { - $this->io->write("[codeception/c3] Deleting c3.php from the root of your project..."); - unlink(getcwd() . DIRECTORY_SEPARATOR . 'c3.php'); - } - } - - private static function composerV2() - { - return Comparator::greaterThanOrEqualTo(PluginInterface::PLUGIN_API_VERSION, '2.0.0'); - } - -} diff --git a/c3.php b/c3.php index 3c59a62..ccc51df 100644 --- a/c3.php +++ b/c3.php @@ -8,399 +8,442 @@ * @author tiger */ -// $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'] = 1; +namespace Codeception; use SebastianBergmann\CodeCoverage\Driver\Driver; use SebastianBergmann\CodeCoverage\Filter as CodeCoverageFilter; +use Codeception\Configuration; +use PHP_CodeCoverage; -if (isset($_COOKIE['CODECEPTION_CODECOVERAGE'])) { - $cookie = json_decode($_COOKIE['CODECEPTION_CODECOVERAGE'], true); +// $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'] = 1; - // fix for improperly encoded JSON in Code Coverage cookie with WebDriver. - // @see https://github.com/Codeception/Codeception/issues/874 - if (!is_array($cookie)) { - $cookie = json_decode($cookie, true); - } +class C3 { - if ($cookie) { - foreach ($cookie as $key => $value) { - if (!empty($value)) { - $_SERVER["HTTP_X_CODECEPTION_" . strtoupper($key)] = $value; - } - } - } -} + /** + * @var string + */ + private $configDir; -if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE', $_SERVER)) { - return; -} + /** + * @var string + */ + private $autoloadRootDir; -if (!function_exists('__c3_error')) { - function __c3_error($message) + /** + * @param string $configDir where to look for codeception.yml and codeception.dist.yml + */ + public function __construct($configDir) { - $errorLogFile = defined('C3_CODECOVERAGE_ERROR_LOG_FILE') ? - C3_CODECOVERAGE_ERROR_LOG_FILE : - C3_CODECOVERAGE_MEDIATE_STORAGE . DIRECTORY_SEPARATOR . 'error.txt'; - if (is_writable($errorLogFile)) { - file_put_contents($errorLogFile, $message); - } else { - $message = "Could not write error to log file ($errorLogFile), original message: $message"; - } - if (!headers_sent()) { - header('X-Codeception-CodeCoverage-Error: ' . str_replace("\n", ' ', $message), true, 500); - } - setcookie('CODECEPTION_CODECOVERAGE_ERROR', $message); + $this->configDir = realpath($configDir); + $this->autoloadRootDir = $this->configDir; } -} -// Autoload Codeception classes -if (!class_exists('\\Codeception\\Codecept') || !function_exists('codecept_is_path_absolute')) { - if (file_exists(__DIR__ . '/codecept.phar')) { - require_once 'phar://' . __DIR__ . '/codecept.phar/autoload.php'; - } elseif (stream_resolve_include_path(__DIR__ . '/vendor/autoload.php')) { - require_once __DIR__ . '/vendor/autoload.php'; - // Required to load some methods only available at codeception/autoload.php - if (stream_resolve_include_path(__DIR__ . '/vendor/codeception/codeception/autoload.php')) { - require_once __DIR__ . '/vendor/codeception/codeception/autoload.php'; - } - } elseif (stream_resolve_include_path('Codeception/autoload.php')) { - require_once 'Codeception/autoload.php'; - } else { - __c3_error('Codeception is not loaded. Please check that either PHAR or Composer package can be used'); + /** + * @param string $dir directory from where to attempt autoloading Codeception + */ + public function setAutoloadRootDir($dir) + { + $this->autoloadRootDir = $dir; } -} -// phpunit codecoverage shimming -if (!class_exists('PHP_CodeCoverage') and class_exists('SebastianBergmann\CodeCoverage\CodeCoverage')) { - class_alias('SebastianBergmann\CodeCoverage\CodeCoverage', 'PHP_CodeCoverage'); - class_alias('SebastianBergmann\CodeCoverage\Report\Text', 'PHP_CodeCoverage_Report_Text'); - class_alias('SebastianBergmann\CodeCoverage\Report\PHP', 'PHP_CodeCoverage_Report_PHP'); - class_alias('SebastianBergmann\CodeCoverage\Report\Clover', 'PHP_CodeCoverage_Report_Clover'); - class_alias('SebastianBergmann\CodeCoverage\Report\Crap4j', 'PHP_CodeCoverage_Report_Crap4j'); - class_alias('SebastianBergmann\CodeCoverage\Report\Html\Facade', 'PHP_CodeCoverage_Report_HTML'); - class_alias('SebastianBergmann\CodeCoverage\Report\Xml\Facade', 'PHP_CodeCoverage_Report_XML'); - class_alias('SebastianBergmann\CodeCoverage\Exception', 'PHP_CodeCoverage_Exception'); -} -// phpunit version -if (!class_exists('PHPUnit_Runner_Version') && class_exists('PHPUnit\Runner\Version')) { - class_alias('PHPUnit\Runner\Version', 'PHPUnit_Runner_Version'); -} + /** + * Run Codeception C3 Coverage collection. + * + * @throws Exception\ConfigurationException + */ + public function run() + { + if (isset($_COOKIE['CODECEPTION_CODECOVERAGE'])) { + $cookie = json_decode($_COOKIE['CODECEPTION_CODECOVERAGE'], true); -// Load Codeception Config -$configDistFile = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.dist.yml'; -$configFile = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.yml'; + // fix for improperly encoded JSON in Code Coverage cookie with WebDriver. + // @see https://github.com/Codeception/Codeception/issues/874 + if (!is_array($cookie)) { + $cookie = json_decode($cookie, true); + } -if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'])) { - $configFile = realpath(__DIR__) . DIRECTORY_SEPARATOR . $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG']; -} -if (file_exists($configFile)) { - // Use codeception.yml for configuration. -} elseif (file_exists($configDistFile)) { - // Use codeception.dist.yml for configuration. - $configFile = $configDistFile; -} else { - __c3_error(sprintf("Codeception config file '%s' not found", $configFile)); -} -try { - \Codeception\Configuration::config($configFile); -} catch (\Exception $e) { - __c3_error($e->getMessage()); -} + if ($cookie) { + foreach ($cookie as $key => $value) { + if (!empty($value)) { + $_SERVER["HTTP_X_CODECEPTION_" . strtoupper($key)] = $value; + } + } + } + } -if (!defined('C3_CODECOVERAGE_MEDIATE_STORAGE')) { + if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE', $_SERVER)) { + return; + } - // workaround for 'zend_mm_heap corrupted' problem - gc_disable(); + if (!function_exists('__c3_error')) { + function __c3_error($message) + { + $errorLogFile = defined('C3_CODECOVERAGE_ERROR_LOG_FILE') ? + C3_CODECOVERAGE_ERROR_LOG_FILE : + C3_CODECOVERAGE_MEDIATE_STORAGE . DIRECTORY_SEPARATOR . 'error.txt'; + if (is_writable($errorLogFile)) { + file_put_contents($errorLogFile, $message); + } else { + $message = "Could not write error to log file ($errorLogFile), original message: $message"; + } + if (!headers_sent()) { + header('X-Codeception-CodeCoverage-Error: ' . str_replace("\n", ' ', $message), true, 500); + } + setcookie('CODECEPTION_CODECOVERAGE_ERROR', $message); + } + } - $memoryLimit = ini_get('memory_limit'); - $requiredMemory = '384M'; - if ((substr($memoryLimit, -1) === 'M' && (int)$memoryLimit < (int)$requiredMemory) - || (substr($memoryLimit, -1) === 'K' && (int)$memoryLimit < (int)$requiredMemory * 1024) - || (ctype_digit($memoryLimit) && (int)$memoryLimit < (int)$requiredMemory * 1024 * 1024) - ) { - ini_set('memory_limit', $requiredMemory); - } + // Autoload Codeception classes + if (!class_exists('\\Codeception\\Codecept') || !function_exists('codecept_is_path_absolute')) { + if (file_exists($this->autoloadRootDir . '/codecept.phar')) { + require_once 'phar://' . $this->autoloadRootDir . '/codecept.phar/autoload.php'; + } elseif (stream_resolve_include_path($this->autoloadRootDir . '/vendor/autoload.php')) { + require_once $this->autoloadRootDir . '/vendor/autoload.php'; + // Required to load some methods only available at codeception/autoload.php + if (stream_resolve_include_path($this->autoloadRootDir . '/vendor/codeception/codeception/autoload.php')) { + require_once $this->autoloadRootDir . '/vendor/codeception/codeception/autoload.php'; + } + } elseif (stream_resolve_include_path('Codeception/autoload.php')) { + require_once 'Codeception/autoload.php'; + } else { + __c3_error('Codeception is not loaded. Please check that either PHAR or Composer package can be used'); + } + } - define('C3_CODECOVERAGE_MEDIATE_STORAGE', Codeception\Configuration::logDir() . 'c3tmp'); - define('C3_CODECOVERAGE_PROJECT_ROOT', Codeception\Configuration::projectDir()); - define('C3_CODECOVERAGE_TESTNAME', $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE']); + // phpunit codecoverage shimming + if (!class_exists('PHP_CodeCoverage') and class_exists('SebastianBergmann\CodeCoverage\CodeCoverage')) { + class_alias('SebastianBergmann\CodeCoverage\CodeCoverage', 'PHP_CodeCoverage'); + class_alias('SebastianBergmann\CodeCoverage\Report\Text', 'PHP_CodeCoverage_Report_Text'); + class_alias('SebastianBergmann\CodeCoverage\Report\PHP', 'PHP_CodeCoverage_Report_PHP'); + class_alias('SebastianBergmann\CodeCoverage\Report\Clover', 'PHP_CodeCoverage_Report_Clover'); + class_alias('SebastianBergmann\CodeCoverage\Report\Crap4j', 'PHP_CodeCoverage_Report_Crap4j'); + class_alias('SebastianBergmann\CodeCoverage\Report\Html\Facade', 'PHP_CodeCoverage_Report_HTML'); + class_alias('SebastianBergmann\CodeCoverage\Report\Xml\Facade', 'PHP_CodeCoverage_Report_XML'); + class_alias('SebastianBergmann\CodeCoverage\Exception', 'PHP_CodeCoverage_Exception'); + } + // phpunit version + if (!class_exists('PHPUnit_Runner_Version') && class_exists('PHPUnit\Runner\Version')) { + class_alias('PHPUnit\Runner\Version', 'PHPUnit_Runner_Version'); + } - function __c3_build_html_report(PHP_CodeCoverage $codeCoverage, $path) - { - $writer = new PHP_CodeCoverage_Report_HTML(); - $writer->process($codeCoverage, $path . 'html'); + // Load Codeception Config + $configDistFile = $this->configDir . DIRECTORY_SEPARATOR . 'codeception.dist.yml'; + $configFile = $this->configDir . DIRECTORY_SEPARATOR . 'codeception.yml'; - if (file_exists($path . '.tar')) { - unlink($path . '.tar'); + if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'])) { + $configFile = $this->configDir . DIRECTORY_SEPARATOR . $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG']; + } + if (file_exists($configFile)) { + // Use codeception.yml for configuration. + } elseif (file_exists($configDistFile)) { + // Use codeception.dist.yml for configuration. + $configFile = $configDistFile; + } else { + __c3_error(sprintf("Codeception config file '%s' not found", $configFile)); + } + try { + Configuration::config($configFile); + } catch (\Exception $e) { + __c3_error($e->getMessage()); } - $phar = new PharData($path . '.tar'); - $phar->setSignatureAlgorithm(Phar::SHA1); - $files = $phar->buildFromDirectory($path . 'html'); - array_map('unlink', $files); + if (!defined('C3_CODECOVERAGE_MEDIATE_STORAGE')) { + + // workaround for 'zend_mm_heap corrupted' problem + gc_disable(); - if (in_array('GZ', Phar::getSupportedCompression())) { - if (file_exists($path . '.tar.gz')) { - unlink($path . '.tar.gz'); + $memoryLimit = ini_get('memory_limit'); + $requiredMemory = '384M'; + if ((substr($memoryLimit, -1) === 'M' && (int)$memoryLimit < (int)$requiredMemory) + || (substr($memoryLimit, -1) === 'K' && (int)$memoryLimit < (int)$requiredMemory * 1024) + || (ctype_digit($memoryLimit) && (int)$memoryLimit < (int)$requiredMemory * 1024 * 1024) + ) { + ini_set('memory_limit', $requiredMemory); } - $phar->compress(\Phar::GZ); + define('C3_CODECOVERAGE_MEDIATE_STORAGE', Configuration::logDir() . 'c3tmp'); + define('C3_CODECOVERAGE_PROJECT_ROOT', Configuration::projectDir()); + define('C3_CODECOVERAGE_TESTNAME', $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE']); - // close the file so that we can rename it - unset($phar); + function __c3_build_html_report(PHP_CodeCoverage $codeCoverage, $path) + { + $writer = new PHP_CodeCoverage_Report_HTML(); + $writer->process($codeCoverage, $path . 'html'); - unlink($path . '.tar'); - rename($path . '.tar.gz', $path . '.tar'); - } + if (file_exists($path . '.tar')) { + unlink($path . '.tar'); + } - return $path . '.tar'; - } + $phar = new PharData($path . '.tar'); + $phar->setSignatureAlgorithm(Phar::SHA1); + $files = $phar->buildFromDirectory($path . 'html'); + array_map('unlink', $files); - function __c3_build_clover_report(PHP_CodeCoverage $codeCoverage, $path) - { - $writer = new PHP_CodeCoverage_Report_Clover(); - $writer->process($codeCoverage, $path . '.clover.xml'); + if (in_array('GZ', Phar::getSupportedCompression())) { + if (file_exists($path . '.tar.gz')) { + unlink($path . '.tar.gz'); + } - return $path . '.clover.xml'; - } + $phar->compress(\Phar::GZ); - function __c3_build_crap4j_report(PHP_CodeCoverage $codeCoverage, $path) - { - $writer = new PHP_CodeCoverage_Report_Crap4j(); - $writer->process($codeCoverage, $path . '.crap4j.xml'); + // close the file so that we can rename it + unset($phar); - return $path . '.crap4j.xml'; - } + unlink($path . '.tar'); + rename($path . '.tar.gz', $path . '.tar'); + } - function __c3_build_cobertura_report(PHP_CodeCoverage $codeCoverage, $path) - { - if (!class_exists(\SebastianBergmann\CodeCoverage\Report\Cobertura::class)) { - throw new Exception("Cobertura report requires php-code-coverage >= 9.2"); - } - $writer = new \SebastianBergmann\CodeCoverage\Report\Cobertura(); - $writer->process($codeCoverage, $path . '.cobertura.xml'); + return $path . '.tar'; + } - return $path . '.cobertura.xml'; - } + function __c3_build_clover_report(PHP_CodeCoverage $codeCoverage, $path) + { + $writer = new PHP_CodeCoverage_Report_Clover(); + $writer->process($codeCoverage, $path . '.clover.xml'); - function __c3_build_phpunit_report(PHP_CodeCoverage $codeCoverage, $path) - { - $writer = new PHP_CodeCoverage_Report_XML(\PHPUnit_Runner_Version::id()); - $writer->process($codeCoverage, $path . 'phpunit'); + return $path . '.clover.xml'; + } - if (file_exists($path . '.tar')) { - unlink($path . '.tar'); - } + function __c3_build_crap4j_report(PHP_CodeCoverage $codeCoverage, $path) + { + $writer = new PHP_CodeCoverage_Report_Crap4j(); + $writer->process($codeCoverage, $path . '.crap4j.xml'); - $phar = new PharData($path . '.tar'); - $phar->setSignatureAlgorithm(Phar::SHA1); - $files = $phar->buildFromDirectory($path . 'phpunit'); - array_map('unlink', $files); + return $path . '.crap4j.xml'; + } + + function __c3_build_cobertura_report(PHP_CodeCoverage $codeCoverage, $path) + { + if (!class_exists(\SebastianBergmann\CodeCoverage\Report\Cobertura::class)) { + throw new Exception("Cobertura report requires php-code-coverage >= 9.2"); + } + $writer = new \SebastianBergmann\CodeCoverage\Report\Cobertura(); + $writer->process($codeCoverage, $path . '.cobertura.xml'); - if (in_array('GZ', Phar::getSupportedCompression())) { - if (file_exists($path . '.tar.gz')) { - unlink($path . '.tar.gz'); + return $path . '.cobertura.xml'; } - $phar->compress(\Phar::GZ); + function __c3_build_phpunit_report(PHP_CodeCoverage $codeCoverage, $path) + { + $writer = new PHP_CodeCoverage_Report_XML(\PHPUnit_Runner_Version::id()); + $writer->process($codeCoverage, $path . 'phpunit'); - // close the file so that we can rename it - unset($phar); + if (file_exists($path . '.tar')) { + unlink($path . '.tar'); + } - unlink($path . '.tar'); - rename($path . '.tar.gz', $path . '.tar'); - } + $phar = new PharData($path . '.tar'); + $phar->setSignatureAlgorithm(Phar::SHA1); + $files = $phar->buildFromDirectory($path . 'phpunit'); + array_map('unlink', $files); - return $path . '.tar'; - } + if (in_array('GZ', Phar::getSupportedCompression())) { + if (file_exists($path . '.tar.gz')) { + unlink($path . '.tar.gz'); + } - function __c3_send_file($filename) - { - if (!headers_sent()) { - readfile($filename); - } + $phar->compress(\Phar::GZ); - return __c3_exit(); - } + // close the file so that we can rename it + unset($phar); - /** - * @param $filename - * @param bool $lock Lock the file for writing? - * @return [null|PHP_CodeCoverage|\SebastianBergmann\CodeCoverage\CodeCoverage, resource] - */ - function __c3_factory($filename, $lock = false) - { - $file = null; - if ($filename !== null && is_readable($filename)) { - if ($lock) { - $file = fopen($filename, 'r+'); - if (flock($file, LOCK_EX)) { - $phpCoverage = unserialize(stream_get_contents($file)); - } else { - __c3_error("Failed to acquire write-lock for $filename"); + unlink($path . '.tar'); + rename($path . '.tar.gz', $path . '.tar'); } - } else { - $phpCoverage = unserialize(file_get_contents($filename)); - } - return array($phpCoverage, $file); - } else { - if (method_exists(Driver::class, 'forLineCoverage')) { - //php-code-coverage 9+ - $filter = new CodeCoverageFilter(); - $driver = Driver::forLineCoverage($filter); - $phpCoverage = new PHP_CodeCoverage($driver, $filter); - } else { - //php-code-coverage 8 or older - $phpCoverage = new PHP_CodeCoverage(); + return $path . '.tar'; } - } - if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'])) { - $suite = $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE']; - try { - $settings = \Codeception\Configuration::suiteSettings($suite, \Codeception\Configuration::config()); - } catch (Exception $e) { - __c3_error($e->getMessage()); + function __c3_send_file($filename) + { + if (!headers_sent()) { + readfile($filename); + } + + return __c3_exit(); } - } else { - $settings = \Codeception\Configuration::config(); - } - try { - \Codeception\Coverage\Filter::setup($phpCoverage) - ->whiteList($settings) - ->blackList($settings); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } + /** + * @param $filename + * @param bool $lock Lock the file for writing? + * @return [null|PHP_CodeCoverage|\SebastianBergmann\CodeCoverage\CodeCoverage, resource] + */ + function __c3_factory($filename, $lock = false) + { + $file = null; + if ($filename !== null && is_readable($filename)) { + if ($lock) { + $file = fopen($filename, 'r+'); + if (flock($file, LOCK_EX)) { + $phpCoverage = unserialize(stream_get_contents($file)); + } else { + __c3_error("Failed to acquire write-lock for $filename"); + } + } else { + $phpCoverage = unserialize(file_get_contents($filename)); + } - return array($phpCoverage, $file); - } + return array($phpCoverage, $file); + } else { + if (method_exists(Driver::class, 'forLineCoverage')) { + //php-code-coverage 9+ + $filter = new CodeCoverageFilter(); + $driver = Driver::forLineCoverage($filter); + $phpCoverage = new PHP_CodeCoverage($driver, $filter); + } else { + //php-code-coverage 8 or older + $phpCoverage = new PHP_CodeCoverage(); + } + } - function __c3_exit() - { - if (!isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'])) { - exit; - } - return null; - } + if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'])) { + $suite = $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE']; + try { + $settings = Configuration::suiteSettings($suite, Configuration::config()); + } catch (Exception $e) { + __c3_error($e->getMessage()); + } + } else { + $settings = Configuration::config(); + } - function __c3_clear() - { - \Codeception\Util\FileSystem::doEmptyDir(C3_CODECOVERAGE_MEDIATE_STORAGE); - } -} + try { + \Codeception\Coverage\Filter::setup($phpCoverage) + ->whiteList($settings) + ->blackList($settings); + } catch (Exception $e) { + __c3_error($e->getMessage()); + } -if (!is_dir(C3_CODECOVERAGE_MEDIATE_STORAGE)) { - if (mkdir(C3_CODECOVERAGE_MEDIATE_STORAGE, 0777, true) === false) { - __c3_error('Failed to create directory "' . C3_CODECOVERAGE_MEDIATE_STORAGE . '"'); - } -} + return array($phpCoverage, $file); + } -// evaluate base path for c3-related files -$path = realpath(C3_CODECOVERAGE_MEDIATE_STORAGE) . DIRECTORY_SEPARATOR . 'codecoverage'; + function __c3_exit() + { + if (!isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'])) { + exit; + } + return null; + } -$requestedC3Report = (strpos($_SERVER['REQUEST_URI'], 'c3/report') !== false); + function __c3_clear() + { + \Codeception\Util\FileSystem::doEmptyDir(C3_CODECOVERAGE_MEDIATE_STORAGE); + } + } -$completeReport = $currentReport = $path . '.serialized'; -if ($requestedC3Report) { - set_time_limit(0); + if (!is_dir(C3_CODECOVERAGE_MEDIATE_STORAGE)) { + if (mkdir(C3_CODECOVERAGE_MEDIATE_STORAGE, 0777, true) === false) { + __c3_error('Failed to create directory "' . C3_CODECOVERAGE_MEDIATE_STORAGE . '"'); + } + } - $route = ltrim(strrchr(rtrim($_SERVER['REQUEST_URI'], '/'), '/'), '/'); + // evaluate base path for c3-related files + $path = realpath(C3_CODECOVERAGE_MEDIATE_STORAGE) . DIRECTORY_SEPARATOR . 'codecoverage'; - if ($route === 'clear') { - __c3_clear(); - return __c3_exit(); - } + $requestedC3Report = (strpos($_SERVER['REQUEST_URI'], 'c3/report') !== false); - list($codeCoverage, ) = __c3_factory($completeReport); + $completeReport = $currentReport = $path . '.serialized'; + if ($requestedC3Report) { + set_time_limit(0); - switch ($route) { - case 'html': - try { - __c3_send_file(__c3_build_html_report($codeCoverage, $path)); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } - return __c3_exit(); - case 'clover': - try { - __c3_send_file(__c3_build_clover_report($codeCoverage, $path)); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } - return __c3_exit(); - case 'crap4j': - try { - __c3_send_file(__c3_build_crap4j_report($codeCoverage, $path)); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } - return __c3_exit(); - case 'serialized': - try { - __c3_send_file($completeReport); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } - return __c3_exit(); - case 'phpunit': - try { - __c3_send_file(__c3_build_phpunit_report($codeCoverage, $path)); - } catch (Exception $e) { - __c3_error($e->getMessage()); + $route = ltrim(strrchr(rtrim($_SERVER['REQUEST_URI'], '/'), '/'), '/'); + + if ($route === 'clear') { + __c3_clear(); + return __c3_exit(); } - return __c3_exit(); - case 'cobertura': - try { - __c3_send_file(__c3_build_cobertura_report($codeCoverage, $path)); - } catch (Exception $e) { - __c3_error($e->getMessage()); + + list($codeCoverage, ) = __c3_factory($completeReport); + + switch ($route) { + case 'html': + try { + __c3_send_file(__c3_build_html_report($codeCoverage, $path)); + } catch (Exception $e) { + __c3_error($e->getMessage()); + } + return __c3_exit(); + case 'clover': + try { + __c3_send_file(__c3_build_clover_report($codeCoverage, $path)); + } catch (Exception $e) { + __c3_error($e->getMessage()); + } + return __c3_exit(); + case 'crap4j': + try { + __c3_send_file(__c3_build_crap4j_report($codeCoverage, $path)); + } catch (Exception $e) { + __c3_error($e->getMessage()); + } + return __c3_exit(); + case 'serialized': + try { + __c3_send_file($completeReport); + } catch (Exception $e) { + __c3_error($e->getMessage()); + } + return __c3_exit(); + case 'phpunit': + try { + __c3_send_file(__c3_build_phpunit_report($codeCoverage, $path)); + } catch (Exception $e) { + __c3_error($e->getMessage()); + } + return __c3_exit(); + case 'cobertura': + try { + __c3_send_file(__c3_build_cobertura_report($codeCoverage, $path)); + } catch (Exception $e) { + __c3_error($e->getMessage()); + } + return __c3_exit(); } - return __c3_exit(); - } -} else { - list($codeCoverage, ) = __c3_factory(null); - $codeCoverage->start(C3_CODECOVERAGE_TESTNAME); - if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG', $_SERVER)) { - register_shutdown_function( - function () use ($codeCoverage, $currentReport) { - $codeCoverage->stop(); - if (!file_exists(dirname($currentReport))) { // verify directory exists - if (!mkdir(dirname($currentReport), 0777, true)) { - __c3_error("Can't write CodeCoverage report into $currentReport"); + } else { + list($codeCoverage, ) = __c3_factory(null); + $codeCoverage->start(C3_CODECOVERAGE_TESTNAME); + if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG', $_SERVER)) { + register_shutdown_function( + function () use ($codeCoverage, $currentReport) { + $codeCoverage->stop(); + if (!file_exists(dirname($currentReport))) { // verify directory exists + if (!mkdir(dirname($currentReport), 0777, true)) { + __c3_error("Can't write CodeCoverage report into $currentReport"); + } + } + + // This will either lock the existing report for writing and return it along with a file pointer, + // or return a fresh PHP_CodeCoverage object without a file pointer. We'll merge the current request + // into that coverage object, write it to disk, and release the lock. By doing this in the end of + // the request, we avoid this scenario, where Request 2 overwrites the changes from Request 1: + // + // Time -> + // Request 1 [ ] + // Request 2 [ ] + // + // In addition, by locking the file for exclusive writing, we make sure no other request try to + // read/write to the file at the same time as this request (leading to a corrupt file). flock() is a + // blocking call, so it waits until an exclusive lock can be acquired before continuing. + + list($existingCodeCoverage, $file) = __c3_factory($currentReport, true); + $existingCodeCoverage->merge($codeCoverage); + + if ($file === null) { + file_put_contents($currentReport, serialize($existingCodeCoverage), LOCK_EX); + } else { + fseek($file, 0); + fwrite($file, serialize($existingCodeCoverage)); + fflush($file); + flock($file, LOCK_UN); + fclose($file); + } } - } - - // This will either lock the existing report for writing and return it along with a file pointer, - // or return a fresh PHP_CodeCoverage object without a file pointer. We'll merge the current request - // into that coverage object, write it to disk, and release the lock. By doing this in the end of - // the request, we avoid this scenario, where Request 2 overwrites the changes from Request 1: - // - // Time -> - // Request 1 [ ] - // Request 2 [ ] - // - // In addition, by locking the file for exclusive writing, we make sure no other request try to - // read/write to the file at the same time as this request (leading to a corrupt file). flock() is a - // blocking call, so it waits until an exclusive lock can be acquired before continuing. - - list($existingCodeCoverage, $file) = __c3_factory($currentReport, true); - $existingCodeCoverage->merge($codeCoverage); - - if ($file === null) { - file_put_contents($currentReport, serialize($existingCodeCoverage), LOCK_EX); - } else { - fseek($file, 0); - fwrite($file, serialize($existingCodeCoverage)); - fflush($file); - flock($file, LOCK_UN); - fclose($file); - } + ); } - ); + } } + } // @codeCoverageIgnoreEnd diff --git a/composer.json b/composer.json index 654caf8..473bb1d 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description":"CodeCoverage collector for Codeception", "keywords":["code coverage", "CodeCoverage"], "homepage":"http://codeception.com/", - "type": "composer-plugin", + "type": "library", "minimum-stability": "dev", "prefer-stable": true, "license":"MIT", @@ -19,18 +19,9 @@ } ], "require": { - "php": ">=5.4.0", - "composer-plugin-api": "^1.0 || ^2.0" - }, - "require-dev": { - "composer/composer": "^1.0 || ^2.0" - }, - "extra": { - "class": "Codeception\\c3\\Installer" + "php": ">=5.4.0" }, "autoload": { - "psr-4": { - "Codeception\\c3\\": "." - } + "classmap": ["c3.php"] } }