mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-28 21:18:46 +02:00
Merge remote-tracking branch 'origin/support/2.7' into support/3.0
# Conflicts: # tests/manual-visual-tests/Backoffice/RenderAllUiBlocks.php # tests/php-unit-tests/ItopDataTestCase.php # tests/php-unit-tests/ItopTestCase.php # tests/php-unit-tests/integration-tests/dictionaries-test/fr.dictionary.itop.core.KO.wrong_php # tests/php-unit-tests/integration-tests/dictionaries-test/fr.dictionary.itop.core.OK.php # tests/php-unit-tests/integration-tests/iTopModulesPhpVersionChecklistTest.php # tests/php-unit-tests/integration-tests/iTopXmlVersionChecklistTest.php # tests/php-unit-tests/phpunit.xml.dist # tests/php-unit-tests/unitary-tests/application/SCSSCompilationTest.php # tests/php-unit-tests/unitary-tests/application/Session/SessionTest.php # tests/php-unit-tests/unitary-tests/application/ThemeHandlerTest.php # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/DO_NOT_CHANGE.css-variables.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/DO_NOT_CHANGE.light-grey.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/README.md # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/_included_file3.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/cross_reference1.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/cross_reference2.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/feature1/_feature1.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/included_file1.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/included_scss/included_file2.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/included_scss/included_file4.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/multi_imports.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/shortcut.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/shortcut2.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/simple_import.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/simple_import2.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/typography.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css/ui-lightness/DO_NOT_CHANGE.jqueryui.scss # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_18_b81900_40x40.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-bg_diagonals-thick_20_666666_40x40.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_1c94c4_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_222222_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_E87C1E_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_F26522_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_ffd27a_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/css/ui-lightness/images/ui-icons_ffffff_256x240.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/ac-background.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/actions_right.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/bg.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/breadcrumb-separator.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/calendar.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/delete.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/desc.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/error.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/eye-closed-555.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/eye-closed-fff.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/eye-open-555.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/eye-open-fff.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/full-screen.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/green-header.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/green-square.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/indicator.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/info-mini.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/minus.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/ok.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/orange-header.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/plus.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/red-header.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/truncated.png # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-collapsable-last.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-collapsable.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-expandable-last.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-expandable.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-item-last.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/images/tv-item.gif # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_imagemodified.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_importmodified.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_stylesheet.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_testcompilethemes.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_varchanged.css # tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/theme-parameters.json # tests/php-unit-tests/unitary-tests/application/theme-handler/getimages/expected-getimages.json # tests/php-unit-tests/unitary-tests/application/theme-handler/getimages/test-getimages.scss # tests/php-unit-tests/unitary-tests/core/ActionEmailTest.php # tests/php-unit-tests/unitary-tests/core/AttributeDefTest.inc.php # tests/php-unit-tests/unitary-tests/core/AttributeURLDefaultPattern.php # tests/php-unit-tests/unitary-tests/core/AttributeURLTest.php # tests/php-unit-tests/unitary-tests/core/BulkChangeTest.inc.php # tests/php-unit-tests/unitary-tests/core/CSVParserTest.php # tests/php-unit-tests/unitary-tests/core/DBObjectTest.php # tests/php-unit-tests/unitary-tests/core/DBSearchAddConditionPointingTo.php # tests/php-unit-tests/unitary-tests/core/ExpressionEvaluateTest.php # tests/php-unit-tests/unitary-tests/core/GetSelectFilterTest.php # tests/php-unit-tests/unitary-tests/core/InlineImageTest.php # tests/php-unit-tests/unitary-tests/core/Log/ExceptionLogTest.php # tests/php-unit-tests/unitary-tests/core/Log/ExceptionLogTest/Exceptions.php # tests/php-unit-tests/unitary-tests/core/Log/LogAPITest.php # tests/php-unit-tests/unitary-tests/core/Log/LogFileNameBuilderTest.php # tests/php-unit-tests/unitary-tests/core/LogAPITest.php # tests/php-unit-tests/unitary-tests/core/LogFileNameBuilderTest.php # tests/php-unit-tests/unitary-tests/core/MetaModelTest.php # tests/php-unit-tests/unitary-tests/core/OQLTest.php # tests/php-unit-tests/unitary-tests/core/UniquenessConstraintTest.php # tests/php-unit-tests/unitary-tests/core/XMLDataLoaderTest.php # tests/php-unit-tests/unitary-tests/core/dictApcuTest.php # tests/php-unit-tests/unitary-tests/core/dictTest.php # tests/php-unit-tests/unitary-tests/core/ormCaseLogTest.php # tests/php-unit-tests/unitary-tests/core/ormPasswordTest.php # tests/php-unit-tests/unitary-tests/core/ormStyleTest.php # tests/php-unit-tests/unitary-tests/setup/MFCompilerTest.php # tests/php-unit-tests/unitary-tests/setup/SubMFCompiler.php # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/1.7_to_1.6.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/1.7_to_1.6.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.6_to_1.7_2.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.6_to_1.7_2.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_1.6.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_1.6.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_1.6_2.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_1.6_2.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_3.0.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/1.7_to_3.0.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/3.0_to_1.7.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/3.0_to_1.7.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/Bug_4569.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/Convert-samples/Bug_4569.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_deleted.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_deleted.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_not-in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_deleted_to_not-in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_deleted.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_deleted.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_not-in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_in-definition_to_not-in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_deleted.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_deleted.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_not-in-definition.expected.xml # tests/php-unit-tests/unitary-tests/setup/iTopDesignFormat/MoveNode-samples/from_not-in-definition_to_not-in-definition.input.xml # tests/php-unit-tests/unitary-tests/setup/ressources/datamodels/datamodel-branding.xml # tests/php-unit-tests/unitary-tests/sources/application/Helper/WebResourcesHelperTest.php # tests/php-unit-tests/unitary-tests/sources/application/status/StatusIncTest.php # tests/php-unit-tests/unitary-tests/sources/application/status/status.php # tests/php-unit-tests/unitary-tests/synchro/DataSynchroTest.php
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Core;
|
||||
|
||||
use CMDBSource;
|
||||
use Combodo\iTop\Core\DbConnectionWrapper;
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
use utils;
|
||||
|
||||
/**
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @package Combodo\iTop\Test\UnitTest\Core
|
||||
*/
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class CMDBSourceTest extends ItopTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
|
||||
parent::setUp();
|
||||
$this->RequireOnceItopFile('/core/cmdbsource.class.inc.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers CMDBSource::IsSameFieldTypes
|
||||
* @dataProvider compareFieldTypesProvider
|
||||
*
|
||||
* @param boolean $bResult
|
||||
* @param string $sItopFieldType
|
||||
* @param string $sDbFieldType
|
||||
*/
|
||||
public function testCompareFieldTypes($bResult, $sItopFieldType, $sDbFieldType)
|
||||
{
|
||||
$this->assertEquals($bResult, CMDBSource::IsSameFieldTypes($sItopFieldType, $sDbFieldType), "$sItopFieldType\n VS\n $sDbFieldType");
|
||||
}
|
||||
|
||||
public function compareFieldTypesProvider()
|
||||
{
|
||||
return array(
|
||||
'same datetime types' => array(true, 'DATETIME', 'DATETIME'),
|
||||
'different types' => array(false, 'VARCHAR(255)', 'INT(11)'),
|
||||
'different types, same type options' => array(false, 'VARCHAR(11)', 'INT(11)'),
|
||||
'same int declaration, same case' => array(true, 'INT(11)', 'INT(11)'),
|
||||
'same int declaration, different case on data type' => array(true, 'INT(11)', 'int(11)'),
|
||||
'same enum declaration, same case' => array(
|
||||
true,
|
||||
"ENUM('error','idle','planned','running')",
|
||||
"ENUM('error','idle','planned','running')",
|
||||
),
|
||||
'same enum declaration, different case on data type' => array(
|
||||
true,
|
||||
"ENUM('error','idle','planned','running')",
|
||||
"enum('error','idle','planned','running')",
|
||||
),
|
||||
'same enum declaration, different case on type options' => array(
|
||||
false,
|
||||
"ENUM('ERROR','IDLE','planned','running')",
|
||||
"ENUM('error','idle','planned','running')",
|
||||
),
|
||||
'same enum declaration, different case on both data type and type options' => array(
|
||||
false,
|
||||
"ENUM('ERROR','IDLE','planned','running')",
|
||||
"enum('error','idle','planned','running')",
|
||||
),
|
||||
'MariaDB 10.2 nullable datetime' => array(
|
||||
true,
|
||||
'DATETIME',
|
||||
"datetime DEFAULT 'NULL'",
|
||||
),
|
||||
'MariaDB 10.2 nullable text' => array(
|
||||
true,
|
||||
'TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci',
|
||||
"text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 'NULL'",
|
||||
),
|
||||
'MariaDB 10.2 nullable unsigned int' => array(
|
||||
true,
|
||||
'INT(11) UNSIGNED',
|
||||
"int(11) unsigned DEFAULT 'NULL'",
|
||||
),
|
||||
'MariaDB 10.2 varchar with default value' => array(
|
||||
true,
|
||||
'VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 0',
|
||||
"varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '0'",
|
||||
),
|
||||
'varchar with default value not at the end' => array(
|
||||
true,
|
||||
"VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 0 COMMENT 'my comment'",
|
||||
"varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '0' COMMENT 'my comment'",
|
||||
),
|
||||
'MariaDB 10.2 Enum with string default value' => array(
|
||||
true,
|
||||
"ENUM('error','idle','planned','running') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 'planned'",
|
||||
"enum('error','idle','planned','running') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 'planned'",
|
||||
),
|
||||
'MariaDB 10.2 Enum with numeric default value' => array(
|
||||
true,
|
||||
"ENUM('1','2','3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '1'",
|
||||
"enum('1','2','3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '1'",
|
||||
),
|
||||
'ENUM with values containing parenthesis' => array(
|
||||
true, // see N°3065 : if having distinct values having parenthesis in enum values will cause comparison to be inexact
|
||||
"ENUM('CSP A','CSP M','NA','OEM(ROC)','OPEN(VL)','RETAIL (Boite)') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
|
||||
"enum('CSP A','CSP M','NA','OEM(ROC)','OPEN(VL)','RETAIL (Boite)') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
|
||||
),
|
||||
// N°3065 before the fix this returned true :(
|
||||
'ENUM with different values, containing parenthesis' => array(
|
||||
false,
|
||||
"ENUM('value 1 (with parenthesis)','value 2') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
|
||||
"enum('value 1 (with parenthesis)','value 3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \ConfigException
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
* @since 3.0.0 N°4215
|
||||
*/
|
||||
public function testIsOpenedDbConnectionUsingTls()
|
||||
{
|
||||
$oConfig = utils::GetConfig();
|
||||
CMDBSource::InitFromConfig($oConfig);
|
||||
$oMysqli = CMDBSource::GetMysqli();
|
||||
|
||||
// resets \CMDBSource::$oMySQLiForQuery to simulate call to \CMDBSource::Init with a TLS connexion
|
||||
DbConnectionWrapper::SetDbConnection(null);
|
||||
|
||||
// before N°4215 fix, this was crashing : "Call to a member function query() on null"
|
||||
$bIsTlsCnx = $this->InvokeNonPublicStaticMethod(CMDBSource::class, 'IsOpenedDbConnectionUsingTls', [$oMysqli]);
|
||||
$this->assertFalse($bIsTlsCnx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Core;
|
||||
|
||||
|
||||
use CMDBSource;
|
||||
use Exception;
|
||||
use IssueLog;
|
||||
use MySQLException;
|
||||
use utils;
|
||||
|
||||
class DeadLockInjection
|
||||
{
|
||||
private $bMustFail = false;
|
||||
private $iRequestCount = 0;
|
||||
private $iFailAt = 0;
|
||||
private $bShowRequest = true;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param int $iFailAt
|
||||
*/
|
||||
public function SetFailAt($iFailAt)
|
||||
{
|
||||
$this->bMustFail = true;
|
||||
$this->iRequestCount = 0;
|
||||
$this->iFailAt = $iFailAt;
|
||||
$this->bShowRequest = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bShowRequest
|
||||
*/
|
||||
public function SetShowRequest($bShowRequest)
|
||||
{
|
||||
$this->bShowRequest = $bShowRequest;
|
||||
}
|
||||
|
||||
|
||||
public function query($sSQL)
|
||||
{
|
||||
if (utils::StartsWith($sSQL, "SELECT")) {
|
||||
return;
|
||||
}
|
||||
if ($this->bShowRequest) {
|
||||
$sShortSQL = substr(preg_replace("/\s+/", " ", substr($sSQL, 0, 180)), 0, 150);
|
||||
echo "$sShortSQL\n";
|
||||
}
|
||||
if (CMDBSource::IsInsideTransaction() && $this->bMustFail) {
|
||||
$this->iRequestCount++;
|
||||
if ($this->iRequestCount == $this->iFailAt) {
|
||||
echo "Generating a FAKE DEADLOCK\n";
|
||||
IssueLog::Trace("Generating a FAKE DEADLOCK", 'cmdbsource');
|
||||
throw new MySQLException("FAKE DEADLOCK", [], new Exception("FAKE DEADLOCK", 1213));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Core;
|
||||
|
||||
use CMDBSource;
|
||||
use Combodo\iTop\Core\DbConnectionWrapper;
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use MySQLTransactionNotClosedException;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*
|
||||
* @group itopRequestMgmt
|
||||
* @group specificOrgInSampleData
|
||||
* Class TransactionsTest
|
||||
*
|
||||
* @package Combodo\iTop\Test\UnitTest\Core
|
||||
*/
|
||||
class TransactionsTest extends ItopTestCase
|
||||
{
|
||||
/** @var DeadLockInjection */
|
||||
private $oMySQLiMock;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
require_once('DeadLockInjection.php');
|
||||
$this->RequireOnceItopFile('/core/cmdbsource.class.inc.php');
|
||||
$sEnv = 'production';
|
||||
$sConfigFile = APPCONF.$sEnv.'/config-itop.php';
|
||||
|
||||
MetaModel::Startup($sConfigFile, false, true, false, $sEnv);
|
||||
|
||||
$oInitialMysqli = CMDBSource::GetMysqli();
|
||||
$this->oMySQLiMock = new DeadLockInjection();
|
||||
|
||||
$oMockMysqli = $this->getMockBuilder('mysqli')
|
||||
->setMethods(['query'])
|
||||
->getMock();
|
||||
$oMockMysqli->expects($this->any())
|
||||
->method('query')
|
||||
->will($this->returnCallback(
|
||||
function ($sSql) use ($oInitialMysqli) {
|
||||
$this->oMySQLiMock->query($sSql);
|
||||
return $oInitialMysqli->query($sSql);
|
||||
}
|
||||
));
|
||||
|
||||
DbConnectionWrapper::SetDbConnectionMockForQuery($oMockMysqli);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test DBInsertNoReload database transaction by provoking deadlock exceptions
|
||||
*
|
||||
* @dataProvider DBInsertProvider
|
||||
*
|
||||
* @param int $iFailAt Specify the request occurrence that fails
|
||||
* @param bool $bIsInDB Indicates if the object must have been created or not
|
||||
*
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DeleteException
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function testDBInsert($iFailAt, $bIsInDB)
|
||||
{
|
||||
// Create a UserRequest with 2 contacts
|
||||
$oTicket = MetaModel::NewObject('UserRequest', [
|
||||
'ref' => 'Test Ticket',
|
||||
'title' => 'Create OK',
|
||||
'description' => 'Create OK',
|
||||
'caller_id' => 15,
|
||||
'org_id' => 3,
|
||||
]);
|
||||
$oLinkSet = $oTicket->Get('contacts_list');
|
||||
$oLinkSet->AddItem(MetaModel::NewObject('lnkContactToTicket', ['contact_id' => 6]));
|
||||
$oLinkSet->AddItem(MetaModel::NewObject('lnkContactToTicket', ['contact_id' => 7]));
|
||||
|
||||
$this->oMySQLiMock->SetFailAt($iFailAt);
|
||||
$this->debug("---> DBInsert()");
|
||||
try {
|
||||
$oTicket->DBWrite();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// If an exception occurs must be a deadlock
|
||||
$this->assertTrue(CMDBSource::IsDeadlockException($e), $e->getMessage());
|
||||
}
|
||||
|
||||
// Verify if the ticket is considered as saved in the database
|
||||
$this->assertEquals($bIsInDB, !$oTicket->IsNew(), " The ticket should be persisted in the DB");
|
||||
|
||||
if (!$oTicket->IsNew()) {
|
||||
$this->oMySQLiMock->SetShowRequest(false);
|
||||
// Delete created objects
|
||||
$oTicket->DBDelete();
|
||||
}
|
||||
}
|
||||
|
||||
public function DBInsertProvider()
|
||||
{
|
||||
return [
|
||||
"Normal case" => ['iFailAt' => -1, 'bIsInDB' => true],
|
||||
"ticket" => ['iFailAt' => 1, 'bIsInDB' => false],
|
||||
"ticket_request" => ['iFailAt' => 2, 'bIsInDB' => false],
|
||||
"priv_change" => ['iFailAt' => 3, 'bIsInDB' => false],
|
||||
"priv_changeop" => ['iFailAt' => 4, 'bIsInDB' => false],
|
||||
"priv_changeop_create" => ['iFailAt' => 5, 'bIsInDB' => false],
|
||||
"History 4" => ['iFailAt' => 6, 'bIsInDB' => false],
|
||||
"History 5" => ['iFailAt' => 7, 'bIsInDB' => false],
|
||||
"History 6" => ['iFailAt' => 8, 'bIsInDB' => false],
|
||||
"History 7" => ['iFailAt' => 9, 'bIsInDB' => false],
|
||||
"History 8" => ['iFailAt' => 10, 'bIsInDB' => false],
|
||||
"History 9" => ['iFailAt' => 11, 'bIsInDB' => false],
|
||||
"History 10" => ['iFailAt' => 12, 'bIsInDB' => false],
|
||||
"History 11" => ['iFailAt' => 13, 'bIsInDB' => false],
|
||||
"History 12" => ['iFailAt' => 14, 'bIsInDB' => false],
|
||||
"History 13" => ['iFailAt' => 15, 'bIsInDB' => false],
|
||||
"History 14" => ['iFailAt' => 16, 'bIsInDB' => false],
|
||||
"History 15" => ['iFailAt' => 17, 'bIsInDB' => false],
|
||||
"History 16" => ['iFailAt' => 18, 'bIsInDB' => false],
|
||||
"History 17" => ['iFailAt' => 19, 'bIsInDB' => false],
|
||||
"History 18" => ['iFailAt' => 20, 'bIsInDB' => false],
|
||||
"History 19" => ['iFailAt' => 21, 'bIsInDB' => false],
|
||||
"History 20" => ['iFailAt' => 22, 'bIsInDB' => false],
|
||||
"History 21" => ['iFailAt' => 23, 'bIsInDB' => false],
|
||||
"History 22" => ['iFailAt' => 24, 'bIsInDB' => false],
|
||||
"History 23" => ['iFailAt' => 25, 'bIsInDB' => false],
|
||||
"History 24" => ['iFailAt' => 26, 'bIsInDB' => false],
|
||||
"History 25" => ['iFailAt' => 27, 'bIsInDB' => false],
|
||||
"History 26" => ['iFailAt' => 28, 'bIsInDB' => false],
|
||||
"History 27" => ['iFailAt' => 29, 'bIsInDB' => false],
|
||||
"History 28" => ['iFailAt' => 30, 'bIsInDB' => false],
|
||||
"History 29" => ['iFailAt' => 31, 'bIsInDB' => false],
|
||||
"History 30" => ['iFailAt' => 32, 'bIsInDB' => false],
|
||||
"History 31" => ['iFailAt' => 33, 'bIsInDB' => false],
|
||||
"History 32" => ['iFailAt' => 34, 'bIsInDB' => false],
|
||||
"History 33" => ['iFailAt' => 35, 'bIsInDB' => false],
|
||||
"History 34" => ['iFailAt' => 36, 'bIsInDB' => false],
|
||||
"History 35" => ['iFailAt' => 37, 'bIsInDB' => false],
|
||||
"History 36" => ['iFailAt' => 38, 'bIsInDB' => false],
|
||||
"History 37" => ['iFailAt' => 39, 'bIsInDB' => false],
|
||||
"History 38" => ['iFailAt' => 40, 'bIsInDB' => false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test DBUpdate database transaction by provoking deadlock exceptions
|
||||
*
|
||||
* @dataProvider DBUpdateProvider
|
||||
* @param $iFailAt
|
||||
*
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DeleteException
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function testDBUpdate($iFailAt, $bIsModified)
|
||||
{
|
||||
// Create a UserRequest into the database with 2 contacts
|
||||
$oTicket = MetaModel::NewObject('UserRequest', [
|
||||
'ref' => 'Test Ticket',
|
||||
'title' => 'Create OK',
|
||||
'description' => 'Create OK',
|
||||
'solution' => 'Create OK',
|
||||
'caller_id' => 15,
|
||||
'org_id' => 3,
|
||||
]);
|
||||
$oLinkSet = $oTicket->Get('contacts_list');
|
||||
$oLinkSet->AddItem(MetaModel::NewObject('lnkContactToTicket', ['contact_id' => 6]));
|
||||
$oLinkSet->AddItem(MetaModel::NewObject('lnkContactToTicket', ['contact_id' => 7]));
|
||||
//$oTicket->Set('contacts_list', $oLinkSet);
|
||||
|
||||
$this->oMySQLiMock->SetShowRequest(false);
|
||||
$oTicket->DBWrite();
|
||||
|
||||
// Verify that the object is considered as saved in the database
|
||||
$this->assertEquals(true, !$oTicket->IsNew());
|
||||
|
||||
// Reload from db
|
||||
$oTicket = MetaModel::GetObject('UserRequest', $oTicket->GetKey());
|
||||
$oTicket->Set('description', 'Update OK');
|
||||
$oTicket->Set('solution', 'Test OK');
|
||||
$oLinkSet = $oTicket->Get('contacts_list');
|
||||
$oLinkSet->AddItem(MetaModel::NewObject('lnkContactToTicket', ['contact_id' => 8]));
|
||||
$oTicket->Set('contacts_list', $oLinkSet);
|
||||
|
||||
// Provoke an error during the update
|
||||
$this->oMySQLiMock->SetFailAt($iFailAt);
|
||||
$this->debug("---> DBUpdate()");
|
||||
try {
|
||||
$oTicket->DBWrite();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// If an exception occurs must be a deadlock
|
||||
$this->assertTrue(CMDBSource::IsDeadlockException($e));
|
||||
}
|
||||
|
||||
// Verify if the ticket is considered as saved in the database
|
||||
$this->assertEquals($bIsModified, $oTicket->IsModified());
|
||||
|
||||
// Reload from db after the update to check the value present in the database
|
||||
$oTicket = MetaModel::GetObject('UserRequest', $oTicket->GetKey());
|
||||
if ($bIsModified) {
|
||||
$this->assertEquals('Create OK', $oTicket->Get('solution'));
|
||||
} else {
|
||||
$this->assertEquals('Test OK', $oTicket->Get('solution'));
|
||||
}
|
||||
|
||||
if (!$oTicket->IsNew()) {
|
||||
$this->oMySQLiMock->SetShowRequest(false);
|
||||
// Delete created objects
|
||||
$oTicket->DBDelete();
|
||||
}
|
||||
}
|
||||
|
||||
public function DBUpdateProvider()
|
||||
{
|
||||
return [
|
||||
"Normal case" => ['iFailAt' => -1, 'bIsModified' => false],
|
||||
"ticket_request" => ['iFailAt' => 1, 'bIsModified' => true],
|
||||
"lnkcontacttoticket" => ['iFailAt' => 2, 'bIsModified' => true],
|
||||
"History 1" => ['iFailAt' => 3, 'bIsModified' => true],
|
||||
"History 2" => ['iFailAt' => 4, 'bIsModified' => true],
|
||||
"History 3" => ['iFailAt' => 5, 'bIsModified' => true],
|
||||
"History 4" => ['iFailAt' => 6, 'bIsModified' => true],
|
||||
"History 5" => ['iFailAt' => 7, 'bIsModified' => true],
|
||||
"History 6" => ['iFailAt' => 8, 'bIsModified' => true],
|
||||
"History 7" => ['iFailAt' => 9, 'bIsModified' => true],
|
||||
"History 8" => ['iFailAt' => 10, 'bIsModified' => true],
|
||||
"History 9" => ['iFailAt' => 11, 'bIsModified' => true],
|
||||
"History 10" => ['iFailAt' => 12, 'bIsModified' => true],
|
||||
"History 11" => ['iFailAt' => 13, 'bIsModified' => true],
|
||||
"History 12" => ['iFailAt' => 14, 'bIsModified' => true],
|
||||
"History 13" => ['iFailAt' => 15, 'bIsModified' => true],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @doesNotPerformAssertions
|
||||
*/
|
||||
public function testTransactionOpenedThenClosed()
|
||||
{
|
||||
CMDBSource::Query('START TRANSACTION;');
|
||||
CMDBSource::Query('COMMIT;');
|
||||
}
|
||||
|
||||
/**
|
||||
* This will throw an exception in the tearDown method.
|
||||
* This cannot be detected nor by `@expectedException` nor `expectException` method, so we have a specific tearDown impl
|
||||
*
|
||||
* @return void
|
||||
* @doesNotPerformAssertions
|
||||
*/
|
||||
public function testTransactionOpenedNotClosed()
|
||||
{
|
||||
CMDBSource::Query('START TRANSACTION;');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
try {
|
||||
parent::tearDown();
|
||||
}
|
||||
catch (MySQLTransactionNotClosedException $e) {
|
||||
if ($this->getName() === 'testTransactionOpenedNotClosed') {
|
||||
$this->debug('Executing the testTransactionOpenNoClose method throws a '.MySQLTransactionNotClosedException::class.' exception in tearDown');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user