mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°7662 Fix the handling of PHP native deprecations (e.g. call strftime on PHP 8.1)
This commit is contained in:
@@ -13,143 +13,256 @@ use DeprecatedCallsLog;
|
||||
class DeprecatedCallsLogTest extends ItopTestCase
|
||||
{
|
||||
/**
|
||||
* We are testing for a undefined offset error. This was throwing a Notice, but starting with PHP 8.0 it was converted to a Warning ! Also the message was changed :(
|
||||
*
|
||||
* @link https://www.php.net/manual/en/migration80.incompatible.php check "A number of notices have been converted into warnings:"
|
||||
* @dataProvider StripCallStackProvider
|
||||
*/
|
||||
private function SetUndefinedOffsetExceptionToExpect(): void
|
||||
public function testStripCallStack($sInputStack, $sExpectedStack)
|
||||
{
|
||||
/** @noinspection ConstantCanBeUsedInspection Preferring the function call as it is easier to read and won't cost that much in this PHPUnit context */
|
||||
if (version_compare(PHP_VERSION, '8.0', '>=')) {
|
||||
$this->expectWarning();
|
||||
$sUndefinedOffsetExceptionMessage = 'Undefined array key "tutu"';
|
||||
} else {
|
||||
$this->expectNotice();
|
||||
$sUndefinedOffsetExceptionMessage = 'Undefined index: tutu';
|
||||
}
|
||||
$this->expectExceptionMessage($sUndefinedOffsetExceptionMessage);
|
||||
$this->assertEquals(
|
||||
$sExpectedStack,
|
||||
$this->InvokeNonPublicStaticMethod(DeprecatedCallsLog::class, 'StripCallStack', [$sInputStack]),
|
||||
'The top item of the call stack should be the first item meaningful to track deprecated calls, not the intermediate layers of the PHP engine'
|
||||
);
|
||||
}
|
||||
|
||||
public function testPhpNoticeWithoutDeprecatedCallsLog(): void
|
||||
{
|
||||
$this->SetUndefinedOffsetExceptionToExpect();
|
||||
|
||||
$aArray = [];
|
||||
if ('toto' === $aArray['tutu']) {
|
||||
//Do nothing, just raising a undefined offset warning
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess Necessary, due to the DeprecatedCallsLog being enabled (no mean to reset)
|
||||
*
|
||||
* The error handler set by DeprecatedCallsLog during startup was causing PHPUnit to miss PHP notices like "undefined offset"
|
||||
*
|
||||
* The error handler is now disabled when running PHPUnit
|
||||
*
|
||||
* @since 3.0.4 N°6274
|
||||
* @covers DeprecatedCallsLog::DeprecatedNoticesErrorHandler
|
||||
*/
|
||||
public function testPhpNoticeWithDeprecatedCallsLog(): void
|
||||
{
|
||||
$this->RequireOnceItopFile('core/log.class.inc.php');
|
||||
DeprecatedCallsLog::Enable(); // will set error handler
|
||||
$this->SetUndefinedOffsetExceptionToExpect();
|
||||
|
||||
$aArray = [];
|
||||
if ('toto' === $aArray['tutu']) {
|
||||
//Do nothing, just raising a undefined offset warning
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider GetMessageFromStackProvider
|
||||
*/
|
||||
public function testGetMessageFromStack($aDebugBacktrace, $sExpectedMessage): void
|
||||
{
|
||||
$sActualMessage = $this->InvokeNonPublicStaticMethod(DeprecatedCallsLog::class, 'GetMessageFromStack', [$aDebugBacktrace]);
|
||||
$this->assertEquals($sExpectedMessage, $sActualMessage);
|
||||
}
|
||||
|
||||
public function GetMessageFromStackProvider()
|
||||
public function StripCallStackProvider()
|
||||
{
|
||||
return [
|
||||
'Call in a file outside of a function or class' => [
|
||||
[
|
||||
/* A deprecated PHP method is invoked from scratch.php, at line 25 (note: the name of the method is not present in the callstack) */
|
||||
'Should preserve the handler when the notice is fired by PHP itself' => [
|
||||
'in' => [
|
||||
[
|
||||
'file' => 'whateverfolder/scratch.php',
|
||||
'line' => 25,
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
],
|
||||
'out' => [
|
||||
[
|
||||
'file' => 'whateverfolder/scratch.php',
|
||||
'line' => 25,
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
],
|
||||
],
|
||||
'Should skip the handler when the notice is fired by a call to trigger_error' => [
|
||||
'in' => [
|
||||
[
|
||||
'file' => 'C:\Dev\wamp64\www\itop-32\sources\Application\WebPage\WebPage.php',
|
||||
'line' => '866',
|
||||
'function' => 'NotifyDeprecatedPhpMethod',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'C:\Dev\wamp64\www\itop-32\extensions\itop-object-copier\copy.php',
|
||||
'line' => '130',
|
||||
'function' => 'add_linked_script',
|
||||
'class' => 'Combodo\iTop\Application\WebPage\WebPage',
|
||||
'type' => '->',
|
||||
'file' => 'whateverfolder/scratch.php',
|
||||
'line' => 25,
|
||||
'function' => 'trigger_error',
|
||||
],
|
||||
],
|
||||
'out' => [
|
||||
[
|
||||
'file' => 'whateverfolder/scratch.php',
|
||||
'line' => 25,
|
||||
'function' => 'trigger_error',
|
||||
],
|
||||
],
|
||||
],
|
||||
'Should skip two levels when the notice is fired by trigger_deprecation (Symfony helper)' => [
|
||||
'in' => [
|
||||
[
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'C:\Dev\wamp64\www\itop-32\pages\exec.php',
|
||||
'line' => '102',
|
||||
'args' => ['C:\Dev\wamp64\www\itop-32\extensions\itop-object-copier\copy.php'],
|
||||
'file' => 'symfony/deprecation.php',
|
||||
'line' => 12,
|
||||
'function' => 'trigger_error',
|
||||
],
|
||||
[
|
||||
'file' => 'symfony/service.php',
|
||||
'line' => 25,
|
||||
'function' => 'trigger_deprecation',
|
||||
],
|
||||
],
|
||||
'out' => [
|
||||
[
|
||||
'file' => 'symfony/service.php',
|
||||
'line' => 25,
|
||||
'function' => 'trigger_deprecation',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider SummarizeCallStackProvider
|
||||
*/
|
||||
public function testSummarizeCallStack($sInputStackStripped, $sExpectedSummary)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$sExpectedSummary,
|
||||
$this->InvokeNonPublicStaticMethod(DeprecatedCallsLog::class, 'SummarizeCallStack', [$sInputStackStripped])
|
||||
);
|
||||
}
|
||||
|
||||
public function SummarizeCallStackProvider()
|
||||
{
|
||||
// All tests are based on a call stack issued from a deprecated PHP function
|
||||
// Other cases are similar: what counts on the top level item is the file and line number of the deprecated call
|
||||
return [
|
||||
'From the main page (deprecated PHP function)' => [
|
||||
'in:stripped call stack' => [
|
||||
[
|
||||
'file' => 'whateverfolder/scratch.php',
|
||||
'line' => 25,
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
],
|
||||
'out' => 'whateverfolder/scratch.php#25',
|
||||
],
|
||||
'From an iTop method (deprecated PHP function)' => [
|
||||
'in:stripped call stack' => [
|
||||
[
|
||||
'file' => 'whateverfolder/someclass.php',
|
||||
'line' => 18,
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'whateverfolder/index.php',
|
||||
'line' => 25,
|
||||
'function' => 'SomeMethod',
|
||||
'class' => 'SomeClass',
|
||||
'type' => '->',
|
||||
],
|
||||
],
|
||||
'out' => 'SomeClass->SomeMethod (whateverfolder/someclass.php#18), itself called from whateverfolder/index.php#25',
|
||||
],
|
||||
'From an iTop static method (deprecated PHP function)' => [
|
||||
'in:stripped call stack' => [
|
||||
[
|
||||
'file' => 'whateverfolder/someclass.php',
|
||||
'line' => 18,
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'whateverfolder/index.php',
|
||||
'line' => 25,
|
||||
'function' => 'SomeMethod',
|
||||
'class' => 'SomeClass',
|
||||
'type' => '::',
|
||||
],
|
||||
],
|
||||
'out' => 'SomeClass::SomeMethod (whateverfolder/someclass.php#18), itself called from whateverfolder/index.php#25',
|
||||
],
|
||||
'From an iTop function (deprecated PHP function)' => [
|
||||
'in:stripped call stack' => [
|
||||
[
|
||||
'file' => 'whateverfolder/someclass.php',
|
||||
'line' => 18,
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'whateverfolder/index.php',
|
||||
'line' => 25,
|
||||
'function' => 'SomeFunction',
|
||||
],
|
||||
],
|
||||
'out' => 'SomeFunction (whateverfolder/someclass.php#18), itself called from whateverfolder/index.php#25',
|
||||
],
|
||||
'From a code snippet (deprecated PHP function)' => [
|
||||
'in:stripped call stack' => [
|
||||
[
|
||||
'file' => 'itop-root/env-production/core/main.php',
|
||||
'line' => 1290,
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'itop-root/core/metamodel.class.php',
|
||||
'line' => 6698,
|
||||
'function' => 'require_once',
|
||||
],
|
||||
[
|
||||
'file' => 'itop-root/env-production/autoload.php',
|
||||
'line' => 6,
|
||||
'function' => 'IncludeModule',
|
||||
'class' => 'MetaModel',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'itop-root/core/metamodel.class.php',
|
||||
'line' => 6487,
|
||||
'function' => 'require_once',
|
||||
],
|
||||
],
|
||||
'Call to Combodo\iTop\Application\WebPage\WebPage::add_linked_script in C:\Dev\wamp64\www\itop-32\extensions\itop-object-copier\copy.php#L130 (from C:\Dev\wamp64\www\itop-32\pages\exec.php#L102)',
|
||||
'out' => 'itop-root/env-production/core/main.php#1290'
|
||||
],
|
||||
|
||||
'Call in a file function, outside of a class' => [
|
||||
[
|
||||
[
|
||||
'file' => 'C:\\Dev\\wamp64\\www\\itop-32\\sources\\Application\\WebPage\\WebPage.php',
|
||||
'line' => 866,
|
||||
'function' => 'NotifyDeprecatedPhpMethod',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'C:\\Dev\\wamp64\\www\\itop-32\\extensions\\itop-object-copier\\copy.php',
|
||||
'line' => 81,
|
||||
'function' => 'add_linked_script',
|
||||
'class' => 'Combodo\\iTop\\Application\\WebPage\\WebPage',
|
||||
'type' => '->',
|
||||
],
|
||||
[
|
||||
'file' => 'C:\\Dev\\wamp64\\www\\itop-32\\extensions\\itop-object-copier\\copy.php',
|
||||
'line' => 123,
|
||||
'function' => 'myFunction',
|
||||
],
|
||||
'From a persistent object method (deprecated PHP function)' => [
|
||||
'in:stripped call stack' => [
|
||||
[
|
||||
'file' => 'itop-root/env-production/itop-tickets/model.itop-tickets.php',
|
||||
'line' => 165,
|
||||
'function' => 'DeprecatedNoticesErrorHandler',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'itop-root/core/dbobject.class.php',
|
||||
'line' => 6575,
|
||||
'function' => 'OnBeforeWriteTicket',
|
||||
'class' => 'Ticket',
|
||||
'type' => '->',
|
||||
],
|
||||
[
|
||||
'file' => 'itop-root/application/cmdbabstract.class.inc.php',
|
||||
'line' => 5933,
|
||||
'function' => 'FireEvent',
|
||||
'class' => 'DBObject',
|
||||
'type' => '->',
|
||||
],
|
||||
[
|
||||
'file' => 'itop-root/core/dbobject.class.php',
|
||||
'line' => 3643,
|
||||
'function' => 'FireEventBeforeWrite',
|
||||
'class' => 'cmdbAbstractObject',
|
||||
'type' => '->',
|
||||
],
|
||||
[
|
||||
'file' => 'itop-root/application/cmdbabstract.class.inc.php',
|
||||
'line' => 4593,
|
||||
'function' => 'DBUpdate',
|
||||
'class' => 'DBObject',
|
||||
'type' => '->',
|
||||
],
|
||||
[
|
||||
'file' => 'itop-root/sources/Controller/Base/Layout/ObjectController.php',
|
||||
'line' => 649,
|
||||
'function' => 'DBUpdate',
|
||||
'class' => 'cmdbAbstractObject',
|
||||
'type' => '->',
|
||||
],
|
||||
[
|
||||
'file' => 'itop-root/pages/UI.php',
|
||||
'line' => 720,
|
||||
'function' => 'OperationApplyModify',
|
||||
'class' => 'Combodo\\iTop\\Controller\\Base\\Layout\\ObjectController',
|
||||
'type' => '->',
|
||||
],
|
||||
],
|
||||
'Call to Combodo\iTop\Application\WebPage\WebPage::add_linked_script in C:\Dev\wamp64\www\itop-32\extensions\itop-object-copier\copy.php#L81 (from C:\Dev\wamp64\www\itop-32\extensions\itop-object-copier\copy.php#L123)',
|
||||
],
|
||||
|
||||
'Call from a class method' => [
|
||||
[
|
||||
[
|
||||
'file' => 'C:\\Dev\\wamp64\\www\\itop-32\\sources\\Application\\WebPage\\WebPage.php',
|
||||
'line' => 866,
|
||||
'function' => 'NotifyDeprecatedPhpMethod',
|
||||
'class' => 'DeprecatedCallsLog',
|
||||
'type' => '::',
|
||||
],
|
||||
[
|
||||
'file' => 'C:\\Dev\\wamp64\\www\\itop-32\\extensions\\itop-object-copier\\copy.php',
|
||||
'line' => 82,
|
||||
'function' => 'add_linked_script',
|
||||
'class' => 'Combodo\\iTop\\Application\\WebPage\\WebPage',
|
||||
'type' => '->',
|
||||
],
|
||||
[
|
||||
'file' => 'C:\\Dev\\wamp64\\www\\itop-32\\extensions\\itop-object-copier\\copy.php',
|
||||
'line' => 125,
|
||||
'function' => 'MyMethod',
|
||||
'class' => 'MyClass',
|
||||
'type' => '::',
|
||||
],
|
||||
],
|
||||
'Call to Combodo\iTop\Application\WebPage\WebPage::add_linked_script in C:\Dev\wamp64\www\itop-32\extensions\itop-object-copier\copy.php#L82 (from MyClass::MyMethod in C:\Dev\wamp64\www\itop-32\extensions\itop-object-copier\copy.php#L125)',
|
||||
'out' => 'Ticket->OnBeforeWriteTicket (itop-root/env-production/itop-tickets/model.itop-tickets.php#165), itself called from DBObject->FireEvent (itop-root/core/dbobject.class.php#6575)'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user