annotate vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php @ 2:92f882872392

Trusted hosts, + remove migration modules
author Chris Cannam
date Tue, 05 Dec 2017 09:26:43 +0000
parents 4c8ae668cc8c
children 7a779792577d
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Bridge\PhpUnit;
Chris@0 13
Chris@0 14 /**
Chris@0 15 * Catch deprecation notices and print a summary report at the end of the test suite.
Chris@0 16 *
Chris@0 17 * @author Nicolas Grekas <p@tchwork.com>
Chris@0 18 */
Chris@0 19 class DeprecationErrorHandler
Chris@0 20 {
Chris@0 21 const MODE_WEAK = 'weak';
Chris@0 22 const MODE_DISABLED = 'disabled';
Chris@0 23
Chris@0 24 private static $isRegistered = false;
Chris@0 25
Chris@0 26 /**
Chris@0 27 * Registers and configures the deprecation handler.
Chris@0 28 *
Chris@0 29 * The following reporting modes are supported:
Chris@0 30 * - use "weak" to hide the deprecation report but keep a global count;
Chris@0 31 * - use "/some-regexp/" to stop the test suite whenever a deprecation
Chris@0 32 * message matches the given regular expression;
Chris@0 33 * - use a number to define the upper bound of allowed deprecations,
Chris@0 34 * making the test suite fail whenever more notices are trigerred.
Chris@0 35 *
Chris@0 36 * @param int|string|false $mode The reporting mode, defaults to not allowing any deprecations
Chris@0 37 */
Chris@0 38 public static function register($mode = 0)
Chris@0 39 {
Chris@0 40 if (self::$isRegistered) {
Chris@0 41 return;
Chris@0 42 }
Chris@0 43
Chris@0 44 $getMode = function () use ($mode) {
Chris@0 45 static $memoizedMode = false;
Chris@0 46
Chris@0 47 if (false !== $memoizedMode) {
Chris@0 48 return $memoizedMode;
Chris@0 49 }
Chris@0 50 if (false === $mode) {
Chris@0 51 $mode = getenv('SYMFONY_DEPRECATIONS_HELPER');
Chris@0 52 }
Chris@0 53 if (DeprecationErrorHandler::MODE_WEAK !== $mode && (!isset($mode[0]) || '/' !== $mode[0])) {
Chris@0 54 $mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0;
Chris@0 55 }
Chris@0 56
Chris@0 57 return $memoizedMode = $mode;
Chris@0 58 };
Chris@0 59
Chris@0 60 $deprecations = array(
Chris@0 61 'unsilencedCount' => 0,
Chris@0 62 'remainingCount' => 0,
Chris@0 63 'legacyCount' => 0,
Chris@0 64 'otherCount' => 0,
Chris@0 65 'unsilenced' => array(),
Chris@0 66 'remaining' => array(),
Chris@0 67 'legacy' => array(),
Chris@0 68 'other' => array(),
Chris@0 69 );
Chris@0 70 $deprecationHandler = function ($type, $msg, $file, $line, $context) use (&$deprecations, $getMode) {
Chris@0 71 $mode = $getMode();
Chris@0 72 if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || DeprecationErrorHandler::MODE_DISABLED === $mode) {
Chris@0 73 return \PHPUnit_Util_ErrorHandler::handleError($type, $msg, $file, $line, $context);
Chris@0 74 }
Chris@0 75
Chris@0 76 $trace = debug_backtrace(true);
Chris@0 77 $group = 'other';
Chris@0 78
Chris@0 79 $i = count($trace);
Chris@0 80 while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_')))) {
Chris@0 81 // No-op
Chris@0 82 }
Chris@0 83
Chris@0 84 if (isset($trace[$i]['object']) || isset($trace[$i]['class'])) {
Chris@0 85 $class = isset($trace[$i]['object']) ? get_class($trace[$i]['object']) : $trace[$i]['class'];
Chris@0 86 $method = $trace[$i]['function'];
Chris@0 87
Chris@0 88 if (0 !== error_reporting()) {
Chris@0 89 $group = 'unsilenced';
Chris@0 90 } elseif (0 === strpos($method, 'testLegacy')
Chris@0 91 || 0 === strpos($method, 'provideLegacy')
Chris@0 92 || 0 === strpos($method, 'getLegacy')
Chris@0 93 || strpos($class, '\Legacy')
Chris@0 94 || in_array('legacy', \PHPUnit_Util_Test::getGroups($class, $method), true)
Chris@0 95 ) {
Chris@0 96 $group = 'legacy';
Chris@0 97 } else {
Chris@0 98 $group = 'remaining';
Chris@0 99 }
Chris@0 100
Chris@0 101 if (isset($mode[0]) && '/' === $mode[0] && preg_match($mode, $msg)) {
Chris@0 102 $e = new \Exception($msg);
Chris@0 103 $r = new \ReflectionProperty($e, 'trace');
Chris@0 104 $r->setAccessible(true);
Chris@0 105 $r->setValue($e, array_slice($trace, 1, $i));
Chris@0 106
Chris@0 107 echo "\n".ucfirst($group).' deprecation triggered by '.$class.'::'.$method.':';
Chris@0 108 echo "\n".$msg;
Chris@0 109 echo "\nStack trace:";
Chris@0 110 echo "\n".str_replace(' '.getcwd().DIRECTORY_SEPARATOR, ' ', $e->getTraceAsString());
Chris@0 111 echo "\n";
Chris@0 112
Chris@0 113 exit(1);
Chris@0 114 }
Chris@0 115 if ('legacy' !== $group && DeprecationErrorHandler::MODE_WEAK !== $mode) {
Chris@0 116 $ref = &$deprecations[$group][$msg]['count'];
Chris@0 117 ++$ref;
Chris@0 118 $ref = &$deprecations[$group][$msg][$class.'::'.$method];
Chris@0 119 ++$ref;
Chris@0 120 }
Chris@0 121 } elseif (DeprecationErrorHandler::MODE_WEAK !== $mode) {
Chris@0 122 $ref = &$deprecations[$group][$msg]['count'];
Chris@0 123 ++$ref;
Chris@0 124 }
Chris@0 125 ++$deprecations[$group.'Count'];
Chris@0 126 };
Chris@0 127 $oldErrorHandler = set_error_handler($deprecationHandler);
Chris@0 128
Chris@0 129 if (null !== $oldErrorHandler) {
Chris@0 130 restore_error_handler();
Chris@0 131 if (array('PHPUnit_Util_ErrorHandler', 'handleError') === $oldErrorHandler) {
Chris@0 132 restore_error_handler();
Chris@0 133 self::register($mode);
Chris@0 134 }
Chris@0 135 } else {
Chris@0 136 self::$isRegistered = true;
Chris@0 137 if (self::hasColorSupport()) {
Chris@0 138 $colorize = function ($str, $red) {
Chris@0 139 $color = $red ? '41;37' : '43;30';
Chris@0 140
Chris@0 141 return "\x1B[{$color}m{$str}\x1B[0m";
Chris@0 142 };
Chris@0 143 } else {
Chris@0 144 $colorize = function ($str) { return $str; };
Chris@0 145 }
Chris@0 146 register_shutdown_function(function () use ($getMode, &$deprecations, $deprecationHandler, $colorize) {
Chris@0 147 $mode = $getMode();
Chris@0 148 if (isset($mode[0]) && '/' === $mode[0]) {
Chris@0 149 return;
Chris@0 150 }
Chris@0 151 $currErrorHandler = set_error_handler('var_dump');
Chris@0 152 restore_error_handler();
Chris@0 153
Chris@0 154 if (DeprecationErrorHandler::MODE_WEAK === $mode) {
Chris@0 155 $colorize = function ($str) { return $str; };
Chris@0 156 }
Chris@0 157 if ($currErrorHandler !== $deprecationHandler) {
Chris@0 158 echo "\n", $colorize('THE ERROR HANDLER HAS CHANGED!', true), "\n";
Chris@0 159 }
Chris@0 160
Chris@0 161 $cmp = function ($a, $b) {
Chris@0 162 return $b['count'] - $a['count'];
Chris@0 163 };
Chris@0 164
Chris@0 165 foreach (array('unsilenced', 'remaining', 'legacy', 'other') as $group) {
Chris@0 166 if ($deprecations[$group.'Count']) {
Chris@0 167 echo "\n", $colorize(sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']), 'legacy' !== $group), "\n";
Chris@0 168
Chris@0 169 uasort($deprecations[$group], $cmp);
Chris@0 170
Chris@0 171 foreach ($deprecations[$group] as $msg => $notices) {
Chris@0 172 echo "\n", rtrim($msg, '.'), ': ', $notices['count'], "x\n";
Chris@0 173
Chris@0 174 arsort($notices);
Chris@0 175
Chris@0 176 foreach ($notices as $method => $count) {
Chris@0 177 if ('count' !== $method) {
Chris@0 178 echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n";
Chris@0 179 }
Chris@0 180 }
Chris@0 181 }
Chris@0 182 }
Chris@0 183 }
Chris@0 184 if (!empty($notices)) {
Chris@0 185 echo "\n";
Chris@0 186 }
Chris@0 187
Chris@0 188 if (DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']) {
Chris@0 189 exit(1);
Chris@0 190 }
Chris@0 191 });
Chris@0 192 }
Chris@0 193 }
Chris@0 194
Chris@0 195 private static function hasColorSupport()
Chris@0 196 {
Chris@0 197 if ('\\' === DIRECTORY_SEPARATOR) {
Chris@0 198 return
Chris@0 199 '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
Chris@0 200 || false !== getenv('ANSICON')
Chris@0 201 || 'ON' === getenv('ConEmuANSI')
Chris@0 202 || 'xterm' === getenv('TERM');
Chris@0 203 }
Chris@0 204
Chris@0 205 return defined('STDOUT') && function_exists('posix_isatty') && @posix_isatty(STDOUT);
Chris@0 206 }
Chris@0 207 }