SlayerBirden /
dataflow-server
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | // @codingStandardsIgnoreFile |
||
| 3 | // @codeCoverageIgnoreStart |
||
| 4 | |||
| 5 | /** |
||
| 6 | * C3 - Codeception Code Coverage |
||
| 7 | * |
||
| 8 | * @author tiger |
||
| 9 | */ |
||
| 10 | |||
| 11 | // $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'] = 1; |
||
| 12 | |||
| 13 | if (isset($_COOKIE['CODECEPTION_CODECOVERAGE'])) { |
||
| 14 | $cookie = json_decode($_COOKIE['CODECEPTION_CODECOVERAGE'], true); |
||
| 15 | |||
| 16 | // fix for improperly encoded JSON in Code Coverage cookie with WebDriver. |
||
| 17 | // @see https://github.com/Codeception/Codeception/issues/874 |
||
| 18 | if (!is_array($cookie)) { |
||
| 19 | $cookie = json_decode($cookie, true); |
||
| 20 | } |
||
| 21 | |||
| 22 | if ($cookie) { |
||
| 23 | foreach ($cookie as $key => $value) { |
||
| 24 | $_SERVER["HTTP_X_CODECEPTION_" . strtoupper($key)] = $value; |
||
| 25 | } |
||
| 26 | } |
||
| 27 | } |
||
| 28 | |||
| 29 | if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE', $_SERVER)) { |
||
| 30 | return; |
||
| 31 | } |
||
| 32 | |||
| 33 | if (!function_exists('__c3_error')) { |
||
| 34 | function __c3_error($message) |
||
| 35 | { |
||
| 36 | $errorLogFile = defined('C3_CODECOVERAGE_ERROR_LOG_FILE') ? |
||
| 37 | C3_CODECOVERAGE_ERROR_LOG_FILE : |
||
| 38 | C3_CODECOVERAGE_MEDIATE_STORAGE . DIRECTORY_SEPARATOR . 'error.txt'; |
||
| 39 | if (is_writable($errorLogFile)) { |
||
| 40 | file_put_contents($errorLogFile, $message); |
||
| 41 | } else { |
||
| 42 | $message = "Could not write error to log file ($errorLogFile), original message: $message"; |
||
| 43 | } |
||
| 44 | if (!headers_sent()) { |
||
| 45 | header('X-Codeception-CodeCoverage-Error: ' . str_replace("\n", ' ', $message), true, 500); |
||
| 46 | } |
||
| 47 | setcookie('CODECEPTION_CODECOVERAGE_ERROR', $message); |
||
| 48 | } |
||
| 49 | } |
||
| 50 | |||
| 51 | // phpunit codecoverage shimming |
||
| 52 | if (!class_exists('PHP_CodeCoverage') and class_exists('SebastianBergmann\CodeCoverage\CodeCoverage')) { |
||
| 53 | class_alias('SebastianBergmann\CodeCoverage\CodeCoverage', 'PHP_CodeCoverage'); |
||
| 54 | class_alias('SebastianBergmann\CodeCoverage\Report\Text', 'PHP_CodeCoverage_Report_Text'); |
||
| 55 | class_alias('SebastianBergmann\CodeCoverage\Report\PHP', 'PHP_CodeCoverage_Report_PHP'); |
||
| 56 | class_alias('SebastianBergmann\CodeCoverage\Report\Clover', 'PHP_CodeCoverage_Report_Clover'); |
||
| 57 | class_alias('SebastianBergmann\CodeCoverage\Report\Crap4j', 'PHP_CodeCoverage_Report_Crap4j'); |
||
| 58 | class_alias('SebastianBergmann\CodeCoverage\Report\Html\Facade', 'PHP_CodeCoverage_Report_HTML'); |
||
| 59 | class_alias('SebastianBergmann\CodeCoverage\Report\Xml\Facade', 'PHP_CodeCoverage_Report_XML'); |
||
| 60 | class_alias('SebastianBergmann\CodeCoverage\Exception', 'PHP_CodeCoverage_Exception'); |
||
| 61 | } |
||
| 62 | // phpunit version |
||
| 63 | if (!class_exists('PHPUnit_Runner_Version') && class_exists('PHPUnit\Runner\Version')) { |
||
| 64 | class_alias('PHPUnit\Runner\Version', 'PHPUnit_Runner_Version'); |
||
| 65 | } |
||
| 66 | |||
| 67 | // Autoload Codeception classes |
||
| 68 | if (!class_exists('\\Codeception\\Codecept')) { |
||
| 69 | if (file_exists(__DIR__ . '/codecept.phar')) { |
||
| 70 | require_once 'phar://' . __DIR__ . '/codecept.phar/autoload.php'; |
||
| 71 | } elseif (stream_resolve_include_path(__DIR__ . '/vendor/autoload.php')) { |
||
| 72 | require_once __DIR__ . '/vendor/autoload.php'; |
||
| 73 | // Required to load some methods only available at codeception/autoload.php |
||
| 74 | if (stream_resolve_include_path(__DIR__ . '/vendor/codeception/codeception/autoload.php')) { |
||
| 75 | require_once __DIR__ . '/vendor/codeception/codeception/autoload.php'; |
||
| 76 | } |
||
| 77 | } elseif (stream_resolve_include_path('Codeception/autoload.php')) { |
||
| 78 | require_once 'Codeception/autoload.php'; |
||
| 79 | } else { |
||
| 80 | __c3_error('Codeception is not loaded. Please check that either PHAR or Composer package can be used'); |
||
| 81 | } |
||
| 82 | } |
||
| 83 | |||
| 84 | // Load Codeception Config |
||
| 85 | $config_dist_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.dist.yml'; |
||
| 86 | $config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.yml'; |
||
| 87 | |||
| 88 | if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'])) { |
||
| 89 | $config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG']; |
||
| 90 | } |
||
| 91 | if (file_exists($config_file)) { |
||
| 92 | // Use codeception.yml for configuration. |
||
| 93 | } elseif (file_exists($config_dist_file)) { |
||
| 94 | // Use codeception.dist.yml for configuration. |
||
| 95 | $config_file = $config_dist_file; |
||
| 96 | } else { |
||
| 97 | __c3_error(sprintf("Codeception config file '%s' not found", $config_file)); |
||
| 98 | } |
||
| 99 | try { |
||
| 100 | \Codeception\Configuration::config($config_file); |
||
| 101 | } catch (\Exception $e) { |
||
| 102 | __c3_error($e->getMessage()); |
||
| 103 | } |
||
| 104 | |||
| 105 | if (!defined('C3_CODECOVERAGE_MEDIATE_STORAGE')) { |
||
| 106 | |||
| 107 | // workaround for 'zend_mm_heap corrupted' problem |
||
| 108 | gc_disable(); |
||
| 109 | |||
| 110 | $memoryLimit = ini_get('memory_limit'); |
||
| 111 | $requiredMemory = '384M'; |
||
| 112 | if ((substr($memoryLimit, -1) === 'M' && (int)$memoryLimit < (int)$requiredMemory) |
||
| 113 | || (substr($memoryLimit, -1) === 'K' && (int)$memoryLimit < (int)$requiredMemory * 1024) |
||
| 114 | || (ctype_digit($memoryLimit) && (int)$memoryLimit < (int)$requiredMemory * 1024 * 1024) |
||
| 115 | ) { |
||
| 116 | ini_set('memory_limit', $requiredMemory); |
||
| 117 | } |
||
| 118 | |||
| 119 | define('C3_CODECOVERAGE_MEDIATE_STORAGE', Codeception\Configuration::logDir() . 'c3tmp'); |
||
| 120 | define('C3_CODECOVERAGE_PROJECT_ROOT', Codeception\Configuration::projectDir()); |
||
| 121 | define('C3_CODECOVERAGE_TESTNAME', $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE']); |
||
| 122 | |||
| 123 | function __c3_build_html_report(PHP_CodeCoverage $codeCoverage, $path) |
||
| 124 | { |
||
| 125 | $writer = new PHP_CodeCoverage_Report_HTML(); |
||
| 126 | $writer->process($codeCoverage, $path . 'html'); |
||
| 127 | |||
| 128 | if (file_exists($path . '.tar')) { |
||
| 129 | unlink($path . '.tar'); |
||
| 130 | } |
||
| 131 | |||
| 132 | $phar = new PharData($path . '.tar'); |
||
| 133 | $phar->setSignatureAlgorithm(Phar::SHA1); |
||
| 134 | $files = $phar->buildFromDirectory($path . 'html'); |
||
| 135 | array_map('unlink', $files); |
||
| 136 | |||
| 137 | if (in_array('GZ', Phar::getSupportedCompression())) { |
||
| 138 | if (file_exists($path . '.tar.gz')) { |
||
| 139 | unlink($path . '.tar.gz'); |
||
| 140 | } |
||
| 141 | |||
| 142 | $phar->compress(\Phar::GZ); |
||
| 143 | |||
| 144 | // close the file so that we can rename it |
||
| 145 | unset($phar); |
||
| 146 | |||
| 147 | unlink($path . '.tar'); |
||
| 148 | rename($path . '.tar.gz', $path . '.tar'); |
||
| 149 | } |
||
| 150 | |||
| 151 | return $path . '.tar'; |
||
| 152 | } |
||
| 153 | |||
| 154 | function __c3_build_clover_report(PHP_CodeCoverage $codeCoverage, $path) |
||
| 155 | { |
||
| 156 | $writer = new PHP_CodeCoverage_Report_Clover(); |
||
| 157 | $writer->process($codeCoverage, $path . '.clover.xml'); |
||
| 158 | |||
| 159 | return $path . '.clover.xml'; |
||
| 160 | } |
||
| 161 | |||
| 162 | function __c3_build_crap4j_report(PHP_CodeCoverage $codeCoverage, $path) |
||
| 163 | { |
||
| 164 | $writer = new PHP_CodeCoverage_Report_Crap4j(); |
||
| 165 | $writer->process($codeCoverage, $path . '.crap4j.xml'); |
||
| 166 | |||
| 167 | return $path . '.crap4j.xml'; |
||
| 168 | } |
||
| 169 | |||
| 170 | function __c3_build_phpunit_report(PHP_CodeCoverage $codeCoverage, $path) |
||
| 171 | { |
||
| 172 | $writer = new PHP_CodeCoverage_Report_XML(\PHPUnit_Runner_Version::id()); |
||
| 173 | $writer->process($codeCoverage, $path . 'phpunit'); |
||
| 174 | |||
| 175 | if (file_exists($path . '.tar')) { |
||
| 176 | unlink($path . '.tar'); |
||
| 177 | } |
||
| 178 | |||
| 179 | $phar = new PharData($path . '.tar'); |
||
| 180 | $phar->setSignatureAlgorithm(Phar::SHA1); |
||
| 181 | $files = $phar->buildFromDirectory($path . 'phpunit'); |
||
| 182 | array_map('unlink', $files); |
||
| 183 | |||
| 184 | if (in_array('GZ', Phar::getSupportedCompression())) { |
||
| 185 | if (file_exists($path . '.tar.gz')) { |
||
| 186 | unlink($path . '.tar.gz'); |
||
| 187 | } |
||
| 188 | |||
| 189 | $phar->compress(\Phar::GZ); |
||
| 190 | |||
| 191 | // close the file so that we can rename it |
||
| 192 | unset($phar); |
||
| 193 | |||
| 194 | unlink($path . '.tar'); |
||
| 195 | rename($path . '.tar.gz', $path . '.tar'); |
||
| 196 | } |
||
| 197 | |||
| 198 | return $path . '.tar'; |
||
| 199 | } |
||
| 200 | |||
| 201 | function __c3_send_file($filename) |
||
| 202 | { |
||
| 203 | if (!headers_sent()) { |
||
| 204 | readfile($filename); |
||
| 205 | } |
||
| 206 | |||
| 207 | return __c3_exit(); |
||
| 208 | } |
||
| 209 | |||
| 210 | /** |
||
| 211 | * @param $filename |
||
| 212 | * @param bool $lock Lock the file for writing? |
||
| 213 | * @return [null|PHP_CodeCoverage|\SebastianBergmann\CodeCoverage\CodeCoverage, resource] |
||
|
0 ignored issues
–
show
|
|||
| 214 | */ |
||
| 215 | function __c3_factory($filename, $lock=false) |
||
| 216 | { |
||
| 217 | $file = null; |
||
| 218 | if ($filename !== null && is_readable($filename)) { |
||
| 219 | if ($lock) { |
||
| 220 | $file = fopen($filename, 'r+'); |
||
| 221 | if (flock($file, LOCK_EX)) { |
||
| 222 | $phpCoverage = unserialize(stream_get_contents($file)); |
||
| 223 | } else { |
||
| 224 | __c3_error("Failed to acquire write-lock for $filename"); |
||
| 225 | } |
||
| 226 | } else { |
||
| 227 | $phpCoverage = unserialize(file_get_contents($filename)); |
||
| 228 | } |
||
| 229 | |||
| 230 | return array($phpCoverage, $file); |
||
|
0 ignored issues
–
show
The variable
$phpCoverage does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
Loading history...
|
|||
| 231 | } else { |
||
| 232 | $phpCoverage = new PHP_CodeCoverage(); |
||
| 233 | } |
||
| 234 | |||
| 235 | if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'])) { |
||
| 236 | $suite = $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE']; |
||
| 237 | try { |
||
| 238 | $settings = \Codeception\Configuration::suiteSettings($suite, \Codeception\Configuration::config()); |
||
| 239 | } catch (Exception $e) { |
||
| 240 | __c3_error($e->getMessage()); |
||
| 241 | } |
||
| 242 | } else { |
||
| 243 | $settings = \Codeception\Configuration::config(); |
||
| 244 | } |
||
| 245 | |||
| 246 | try { |
||
| 247 | \Codeception\Coverage\Filter::setup($phpCoverage) |
||
| 248 | ->whiteList($settings) |
||
| 249 | ->blackList($settings); |
||
| 250 | } catch (Exception $e) { |
||
| 251 | __c3_error($e->getMessage()); |
||
| 252 | } |
||
| 253 | |||
| 254 | return array($phpCoverage, $file); |
||
| 255 | } |
||
| 256 | |||
| 257 | function __c3_exit() |
||
| 258 | { |
||
| 259 | if (!isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'])) { |
||
| 260 | exit; |
||
|
0 ignored issues
–
show
The function __c3_exit() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an Loading history...
|
|||
| 261 | } |
||
| 262 | return null; |
||
| 263 | } |
||
| 264 | |||
| 265 | function __c3_clear() |
||
| 266 | { |
||
| 267 | \Codeception\Util\FileSystem::doEmptyDir(C3_CODECOVERAGE_MEDIATE_STORAGE); |
||
| 268 | } |
||
| 269 | } |
||
| 270 | |||
| 271 | if (!is_dir(C3_CODECOVERAGE_MEDIATE_STORAGE)) { |
||
| 272 | if (mkdir(C3_CODECOVERAGE_MEDIATE_STORAGE, 0777, true) === false) { |
||
| 273 | __c3_error('Failed to create directory "' . C3_CODECOVERAGE_MEDIATE_STORAGE . '"'); |
||
| 274 | } |
||
| 275 | } |
||
| 276 | |||
| 277 | // evaluate base path for c3-related files |
||
| 278 | $path = realpath(C3_CODECOVERAGE_MEDIATE_STORAGE) . DIRECTORY_SEPARATOR . 'codecoverage'; |
||
| 279 | |||
| 280 | $requested_c3_report = (strpos($_SERVER['REQUEST_URI'], 'c3/report') !== false); |
||
| 281 | |||
| 282 | $complete_report = $current_report = $path . '.serialized'; |
||
| 283 | if ($requested_c3_report) { |
||
| 284 | set_time_limit(0); |
||
| 285 | |||
| 286 | $route = ltrim(strrchr($_SERVER['REQUEST_URI'], '/'), '/'); |
||
| 287 | |||
| 288 | if ($route === 'clear') { |
||
| 289 | __c3_clear(); |
||
| 290 | return __c3_exit(); |
||
| 291 | } |
||
| 292 | |||
| 293 | list($codeCoverage, ) = __c3_factory($complete_report); |
||
| 294 | |||
| 295 | switch ($route) { |
||
| 296 | case 'html': |
||
| 297 | try { |
||
| 298 | __c3_send_file(__c3_build_html_report($codeCoverage, $path)); |
||
| 299 | } catch (Exception $e) { |
||
| 300 | __c3_error($e->getMessage()); |
||
| 301 | } |
||
| 302 | return __c3_exit(); |
||
| 303 | case 'clover': |
||
| 304 | try { |
||
| 305 | __c3_send_file(__c3_build_clover_report($codeCoverage, $path)); |
||
| 306 | } catch (Exception $e) { |
||
| 307 | __c3_error($e->getMessage()); |
||
| 308 | } |
||
| 309 | return __c3_exit(); |
||
| 310 | case 'crap4j': |
||
| 311 | try { |
||
| 312 | __c3_send_file(__c3_build_crap4j_report($codeCoverage, $path)); |
||
| 313 | } catch (Exception $e) { |
||
| 314 | __c3_error($e->getMessage()); |
||
| 315 | } |
||
| 316 | return __c3_exit(); |
||
| 317 | case 'serialized': |
||
| 318 | try { |
||
| 319 | __c3_send_file($complete_report); |
||
| 320 | } catch (Exception $e) { |
||
| 321 | __c3_error($e->getMessage()); |
||
| 322 | } |
||
| 323 | return __c3_exit(); |
||
| 324 | case 'phpunit': |
||
| 325 | try { |
||
| 326 | __c3_send_file(__c3_build_phpunit_report($codeCoverage, $path)); |
||
| 327 | } catch (Exception $e) { |
||
| 328 | __c3_error($e->getMessage()); |
||
| 329 | } |
||
| 330 | return __c3_exit(); |
||
| 331 | } |
||
| 332 | |||
| 333 | } else { |
||
| 334 | list($codeCoverage, ) = __c3_factory(null); |
||
| 335 | $codeCoverage->start(C3_CODECOVERAGE_TESTNAME); |
||
| 336 | if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG', $_SERVER)) { |
||
| 337 | register_shutdown_function( |
||
| 338 | function () use ($codeCoverage, $current_report) { |
||
| 339 | |||
| 340 | $codeCoverage->stop(); |
||
| 341 | if (!file_exists(dirname($current_report))) { // verify directory exists |
||
| 342 | if (!mkdir(dirname($current_report), 0777, true)) { |
||
| 343 | __c3_error("Can't write CodeCoverage report into $current_report"); |
||
| 344 | } |
||
| 345 | } |
||
| 346 | |||
| 347 | // This will either lock the existing report for writing and return it along with a file pointer, |
||
| 348 | // or return a fresh PHP_CodeCoverage object without a file pointer. We'll merge the current request |
||
| 349 | // into that coverage object, write it to disk, and release the lock. By doing this in the end of |
||
| 350 | // the request, we avoid this scenario, where Request 2 overwrites the changes from Request 1: |
||
| 351 | // |
||
| 352 | // Time -> |
||
| 353 | // Request 1 [ <read> <write> ] |
||
| 354 | // Request 2 [ <read> <write> ] |
||
| 355 | // |
||
| 356 | // In addition, by locking the file for exclusive writing, we make sure no other request try to |
||
| 357 | // read/write to the file at the same time as this request (leading to a corrupt file). flock() is a |
||
| 358 | // blocking call, so it waits until an exclusive lock can be acquired before continuing. |
||
| 359 | |||
| 360 | list($existingCodeCoverage, $file) = __c3_factory($current_report, true); |
||
| 361 | $existingCodeCoverage->merge($codeCoverage); |
||
| 362 | |||
| 363 | if ($file === null) { |
||
| 364 | file_put_contents($current_report, serialize($existingCodeCoverage), LOCK_EX); |
||
| 365 | } else { |
||
| 366 | fseek($file, 0); |
||
| 367 | fwrite($file, serialize($existingCodeCoverage)); |
||
| 368 | fflush($file); |
||
| 369 | flock($file, LOCK_UN); |
||
| 370 | fclose($file); |
||
| 371 | } |
||
| 372 | } |
||
| 373 | ); |
||
| 374 | } |
||
| 375 | } |
||
| 376 | |||
| 377 | // @codeCoverageIgnoreEnd |
||
| 378 |
This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.