Merge remote-tracking branch 'origin/support/2.7' into support/3.0

# Conflicts:
#	composer.json
#	core/cmdbchangeop.class.inc.php
#	core/cmdbobject.class.inc.php
#	css/light-grey.scss
#	setup/setuputils.class.inc.php
#	test/ItopTestCase.php
#	test/core/ConfigTest.php
#	test/core/LogAPITest.php
#	test/core/UserRightsTest.php
#	test/core/dictApcuTest.php
#	test/core/dictTest.php
#	test/core/iTopConfigParserTest.php
#	test/core/ormLinkSetTest.php
#	test/phpunit.xml.dist
#	test/postbuild_integration.xml.dist
#	test/setup/SetupUtilsTest.php
#	test/status/StatusIncTest.php
#	webservices/cron.php
This commit is contained in:
Pierre Goiffon
2022-04-22 15:26:18 +02:00
67 changed files with 1063 additions and 712 deletions

3
.gitignore vendored
View File

@@ -45,6 +45,9 @@ test/vendor/*
!/log/index.php
!/log/web.config
# PHPUnit cache file
/test/.phpunit.result.cache
# Jetbrains
/.idea/**

View File

@@ -1402,11 +1402,11 @@ interface iBackofficeDictEntriesPrefixesExtension
/**
* Implement this interface to add content to any enhanced portal page
*
* IMPORTANT! Experimental API, may be removed at anytime, we don't recommend to use it just now!
*
* @api
* @package Extensibility
* @since 2.4.0
*
* @since 2.4.0 interface creation
* @since 2.7.0 change method signatures due to Silex to Symfony migration
*/
interface iPortalUIExtension
{
@@ -1479,7 +1479,11 @@ interface iPortalUIExtension
}
/**
* IMPORTANT! Experimental API, may be removed at anytime, we don't recommend to use it just now!
* Extend this class instead of iPortalUIExtension if you don't need to overload all methods
*
* @api
* @package Extensibility
* @since 2.4.0
*/
abstract class AbstractPortalUIExtension implements iPortalUIExtension
{

View File

@@ -1272,7 +1272,7 @@ class DesignerComboField extends DesignerFormField
$sChecked = $this->defaultValue ? 'checked' : '';
$sMandatory = $this->bMandatory ? 'true' : 'false';
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
if ($this->IsSorted())
if ($this->IsSorted() && isset($this->aAllowedValues) )
{
asort($this->aAllowedValues);
}
@@ -1320,19 +1320,17 @@ class DesignerComboField extends DesignerFormField
$sHtml .= "<option value=\"\">".$this->sNullLabel."</option>";
}
}
foreach($this->aAllowedValues as $sKey => $sDisplayValue)
{
if ($this->bMultipleSelection)
{
$sSelected = in_array($sKey, $this->defaultValue) ? 'selected' : '';
if ( isset($this->aAllowedValues) ) {
foreach ($this->aAllowedValues as $sKey => $sDisplayValue) {
if ($this->bMultipleSelection) {
$sSelected = in_array($sKey, $this->defaultValue) ? 'selected' : '';
} else {
$sSelected = ($sKey == $this->defaultValue) ? 'selected' : '';
}
// Quick and dirty: display the menu parents as a tree
$sHtmlValue = str_replace(' ', '&nbsp;', $sDisplayValue);
$sHtml .= "<option value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\" $sSelected>$sHtmlValue</option>";
}
else
{
$sSelected = ($sKey == $this->defaultValue) ? 'selected' : '';
}
// Quick and dirty: display the menu parents as a tree
$sHtmlValue = str_replace(' ', '&nbsp;', htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8'));
$sHtml .= "<option value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\" $sSelected>$sHtmlValue</option>";
}
$sHtml .= "</select></span>";
if ($this->bOtherChoices)

View File

@@ -78,23 +78,31 @@ class CMDBChangeOp extends DBObject implements iCMDBChangeOp
}
/**
* @inheritDoc
*/
* Describe (as a text string) the modifications corresponding to this change
*/
public function GetDescription()
{
return '';
}
/**
* Safety net: in case the change is not given, let's guarantee that it will
* be set to the current ongoing change (or create a new one)
*/
* Safety net:
* * if change isn't persisted yet, use the current change and persist it if needed
* * in case the change is not given, let's guarantee that it will be set to the current ongoing change (or create a new one)
*
* @since 2.7.7 3.0.2 3.1.0 N°3717 do persist the current change if needed
*/
protected function OnInsert()
{
if ($this->Get('change') <= 0)
{
$this->Set('change', CMDBObject::GetCurrentChange());
$iChange = $this->Get('change');
if (($iChange <= 0) || (is_null($iChange))) {
$oChange = CMDBObject::GetCurrentChange();
if ($oChange->IsNew()) {
$oChange->DBWrite();
}
$this->Set('change', $oChange);
}
parent::OnInsert();
}
}

View File

@@ -113,6 +113,26 @@ abstract class CMDBObject extends DBObject
self::$m_oCurrChange = $oChange;
}
/**
* @param string $sUserInfo
* @param string $sOrigin
* @param \DateTime $oDate
*
* @throws \CoreException
*
* @since 2.7.7 3.0.2 3.1.0 N°3717 new method to reset current change
*/
public static function SetCurrentChangeFromParams($sUserInfo, $sOrigin = null, $oDate = null)
{
static::SetTrackInfo($sUserInfo);
static::SetTrackOrigin($sOrigin);
static::CreateChange();
if (!is_null($oDate)) {
static::$m_oCurrChange->Set("date", $oDate);
}
}
//
// Todo: simplify the APIs and do not pass the current change as an argument anymore
// SetTrackInfo to be invoked in very few cases (UI.php, CSV import, Data synchro)
@@ -144,6 +164,8 @@ abstract class CMDBObject extends DBObject
* $oMyChange->Set("userinfo", 'this is done by ... for ...');
* $iChangeId = $oMyChange->DBInsert();
*
* **warning** : this will do nothing if current change already exists !
*
* @see SetCurrentChange to specify a CMDBObject instance instead
*
* @param string $sInfo
@@ -171,6 +193,8 @@ abstract class CMDBObject extends DBObject
/**
* Provides information about the origin of the change
*
* **warning** : this will do nothing if current change already exists !
*
* @see SetTrackInfo
* @see SetCurrentChange to specify a CMDBObject instance instead
*
@@ -181,18 +205,15 @@ abstract class CMDBObject extends DBObject
{
self::$m_sOrigin = $sOrigin;
}
/**
* Get the additional information (defaulting to user name)
*/
protected static function GetTrackInfo()
*/
public static function GetTrackInfo()
{
if (is_null(self::$m_sInfo))
{
if (is_null(self::$m_sInfo)) {
return CMDBChange::GetCurrentUserName();
}
else
{
} else {
return self::$m_sInfo;
}
}
@@ -243,6 +264,9 @@ abstract class CMDBObject extends DBObject
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*
* @since 2.7.7 3.0.2 3.1.0 N°3717 {@see CMDBChange} **will be persisted later** in {@see \CMDBChangeOp::OnInsert} (was done previously directly here)
* This will avoid creating in DB CMDBChange lines without any corresponding CMDBChangeOp
*/
protected static function CreateChange()
{
@@ -251,7 +275,6 @@ abstract class CMDBObject extends DBObject
self::$m_oCurrChange->Set("userinfo", self::GetTrackInfo());
self::$m_oCurrChange->Set("user_id", self::GetTrackUserId());
self::$m_oCurrChange->Set("origin", self::GetTrackOrigin());
self::$m_oCurrChange->DBInsert();
}
/**

View File

@@ -2582,6 +2582,12 @@
}
}
}
&[data-attribute-type="AttributeDuration"] {
.field_value_container {
white-space: nowrap;
}
}
}
.one-col-details .details .field_container.field_small {

View File

@@ -359,9 +359,7 @@ function DisplayLostAttachments(iTopWebPage &$oP, ApplicationContext &$oAppConte
$sHistoryEntry = Dict::Format('DBTools:LostAttachments:History', $oOrmDocument->GetFileName());
CMDBObject::SetTrackInfo(UserRights::GetUserFriendlyName());
$oChangeOp = MetaModel::NewObject('CMDBChangeOpPlugin');
/** @var \Change $oChange */
$oChange = CMDBObject::GetCurrentChange();
$oChangeOp->Set('change', $oChange->GetKey());
// CMDBChangeOp.change will be automatically filled
$oChangeOp->Set('objclass', $sTargetClass);
$oChangeOp->Set('objkey', $sTargetId);
$oChangeOp->Set('description', $sHistoryEntry);

View File

@@ -304,75 +304,61 @@ function ValidateField(sFieldId, sPattern, bMandatory, sFormId, nullValue, origi
function ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue)
{
var bValid;
var sExplain = '';
var sTextContent;
if ($('#'+sFieldId).size() > 0) {
var bValid;
var sExplain = '';
var sTextContent;
if ($('#'+sFieldId).prop('disabled'))
{
bValid = true; // disabled fields are not checked
}
else
{
// Get the contents without the tags
var oFormattedContents = $("#cke_"+sFieldId+" iframe");
if (oFormattedContents.length == 0)
{
var oSourceContents = $("#cke_"+sFieldId+" textarea.cke_source");
sTextContent = oSourceContents.val();
}
else
{
sTextContent = oFormattedContents.contents().find("body").text();
if (sTextContent == '')
{
// No plain text, maybe there is just an image...
var oImg = oFormattedContents.contents().find("body img");
if (oImg.length != 0)
{
sTextContent = 'image';
if ($('#'+sFieldId).prop('disabled')) {
bValid = true; // disabled fields are not checked
} else {
// Get the contents without the tags
var oFormattedContents = $("#cke_"+sFieldId+" iframe");
if (oFormattedContents.length == 0) {
var oSourceContents = $("#cke_"+sFieldId+" textarea.cke_source");
sTextContent = oSourceContents.val();
} else {
sTextContent = oFormattedContents.contents().find("body").text();
if (sTextContent == '') {
// No plain text, maybe there is just an image...
var oImg = oFormattedContents.contents().find("body img");
if (oImg.length != 0) {
sTextContent = 'image';
}
}
}
}
// Get the original value without the tags
var oFormattedOriginalContents = (originalValue !== undefined) ? $('<div></div>').html(originalValue) : undefined;
var sTextOriginalContents = (oFormattedOriginalContents !== undefined) ? oFormattedOriginalContents.text() : undefined;
if (bMandatory && (sTextContent == nullValue))
{
bValid = false;
sExplain = Dict.S('UI:ValueMustBeSet');
}
else if ((sTextOriginalContents != undefined) && (sTextContent == sTextOriginalContents))
{
bValid = false;
if (sTextOriginalContents == nullValue)
{
// Get the original value without the tags
var oFormattedOriginalContents = (originalValue !== undefined) ? $('<div></div>').html(originalValue) : undefined;
var sTextOriginalContents = (oFormattedOriginalContents !== undefined) ? oFormattedOriginalContents.text() : undefined;
if (bMandatory && (sTextContent == nullValue)) {
bValid = false;
sExplain = Dict.S('UI:ValueMustBeSet');
}
else
{
// Note: value change check is not working well yet as the HTML to Text conversion is not exactly the same when done from the PHP value or the CKEditor value.
sExplain = Dict.S('UI:ValueMustBeChanged');
} else if ((sTextOriginalContents != undefined) && (sTextContent == sTextOriginalContents)) {
bValid = false;
if (sTextOriginalContents == nullValue) {
sExplain = Dict.S('UI:ValueMustBeSet');
} else {
// Note: value change check is not working well yet as the HTML to Text conversion is not exactly the same when done from the PHP value or the CKEditor value.
sExplain = Dict.S('UI:ValueMustBeChanged');
}
} else {
bValid = true;
}
}
else
{
bValid = true;
ReportFieldValidationStatus(sFieldId, sFormId, bValid, sExplain);
if ($('#'+sFieldId).data('timeout_validate') == undefined) {
// We need to check periodically as CKEditor doesn't trigger our events. More details in UIHTMLEditorWidget::Display() @ line 92
var iTimeoutValidate = setInterval(function () {
ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue);
}, 500);
$('#'+sFieldId).data('timeout_validate', iTimeoutValidate);
}
}
ReportFieldValidationStatus(sFieldId, sFormId, bValid, sExplain);
if ($('#'+sFieldId).data('timeout_validate') == undefined) {
// We need to check periodically as CKEditor doesn't trigger our events. More details in UIHTMLEditorWidget::Display() @ line 92
var iTimeoutValidate = setInterval(function () {
ValidateCKEditField(sFieldId, sPattern, bMandatory, sFormId, nullValue, originalValue);
}, 500);
$('#'+sFieldId).data('timeout_validate', iTimeoutValidate);
}
}
function ResetPwd(id)

View File

@@ -1118,7 +1118,16 @@ EOF
$aUpdatedDecoded = array();
foreach ($aUpdatedProperties as $sProp) {
$sDecodedProp = str_replace('attr_', '', $sProp); // Remove the attr_ prefix
$aCurrentValues[$sDecodedProp] = (isset($aPreviousValues[$sProp]) ? $aPreviousValues[$sProp] : ''); // Set the previous value
// Set the previous value
if ( isset($aPreviousValues[$sProp]) && $aPreviousValues[$sProp] != '' ){
$aCurrentValues[$sDecodedProp] = $aPreviousValues[$sProp];
} else {
if(gettype($aCurrentValues[$sDecodedProp]) == "array") {
$aCurrentValues[$sDecodedProp] = [];
} else {
$aCurrentValues[$sDecodedProp] = '';
}
}
$aUpdatedDecoded[] = $sDecodedProp;
}

View File

@@ -19,9 +19,47 @@
*
*/
class MissingDependencyException extends Exception
class MissingDependencyException extends CoreException
{
/**
* @see \ModuleDiscovery::OrderModulesByDependencies property init
* @var array<string, array<string>>
* module id as key
* another array as value, containing : 'module' with module info, 'dependencies' with missing dependencies
*/
public $aModulesInfo;
/**
* @return string HTML to print to the user the modules impacted
* @since 2.7.7 3.0.2 3.1.0 PR #280
*/
public function getHtmlDesc($sHighlightHtmlBegin = null, $sHighlightHtmlEnd = null)
{
$sErrorMessage = <<<HTML
<p>The following modules have unmet dependencies:</p>
<ul>
HTML;
foreach ($this->aModulesInfo as $sModuleId => $aModuleErrors) {
$sModuleLabel = $aModuleErrors['module']['label'];
$aModuleMissingDependencies = $aModuleErrors['dependencies'];
$sErrorMessage .= <<<HTML
<li><strong>{$sModuleLabel}</strong> ({$sModuleId}):
<ul>
HTML;
foreach ($aModuleMissingDependencies as $sMissingModule) {
$sErrorMessage .= "<li>{$sMissingModule}</li>";
}
$sErrorMessage .= <<<HTML
</ul>
</li>
HTML;
}
$sErrorMessage .= '</ul>';
return $sErrorMessage;
}
}
class ModuleDiscovery

View File

@@ -1394,7 +1394,7 @@ class WizStepModulesChoice extends WizardStep
}
catch(MissingDependencyException $e)
{
$oPage->warning($e->getMessage());
$oPage->warning($e->getHtmlDesc());
}
$this->bUpgrade = ($this->oWizard->GetParameter('install_mode') != 'install');
@@ -2138,7 +2138,7 @@ class WizStepSummary extends WizardStep
catch(MissingDependencyException $e)
{
$this->bDependencyCheck = false;
$this->sDependencyIssue = $e->getMessage();
$this->sDependencyIssue = $e->getHtmlDesc();
}
}
return $this->bDependencyCheck;

View File

@@ -79,7 +79,7 @@ class ItopDataTestCase extends ItopTestCase
/**
* @throws Exception
*/
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/utils.inc.php');
@@ -101,15 +101,12 @@ class ItopDataTestCase extends ItopTestCase
/**
* @throws Exception
*/
protected function tearDown()
protected function tearDown(): void
{
if (static::USE_TRANSACTION)
{
if (static::USE_TRANSACTION) {
$this->debug("ROLLBACK !!!");
CMDBSource::Query('ROLLBACK');
}
else
{
} else {
$this->debug("");
$this->aCreatedObjects = array_reverse($this->aCreatedObjects);
foreach ($this->aCreatedObjects as $oObject)

View File

@@ -34,7 +34,8 @@ class ItopTestCase extends TestCase
{
const TEST_LOG_DIR = 'test';
protected function setUp()
/** @noinspection UsingInclusionOnceReturnValueInspection avoid errors for approot includes */
protected function setUp(): void
{
@include_once '../approot.inc.php';
@include_once '../../approot.inc.php';
@@ -57,9 +58,9 @@ class ItopTestCase extends TestCase
{
echo "$sMsg\n";
}
else
{
print_r($sMsg);
else {
/** @noinspection ForgottenDebugOutputInspection */
print_r($sMsg);
}
}
}

View File

@@ -21,10 +21,10 @@ class DataLocalizerTest extends ItopDataTestCase
const USE_TRANSACTION = false;
const TEST_CSV_RESULT = 'DataLocalizerTest.csv';
public function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');
ApplicationContext::SetPluginProperty('QueryLocalizerPlugin', 'language_code', 'FR FR');
SetupUtils::builddir(APPROOT.'log/test/OQLToSQL');

View File

@@ -22,10 +22,9 @@ class OQLToSQLAllCLassesTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;
public function setUp()
public function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');
SetupUtils::builddir(APPROOT.'log/test/OQLToSQL');
}

View File

@@ -19,10 +19,9 @@ class OQLToSQLTest extends ItopDataTestCase
const USE_TRANSACTION = false;
const TEST_CSV_RESULT = 'OQLToSQLTest.csv';
public function setUp()
public function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');
SetupUtils::builddir(APPROOT.'log/test/OQLToSQL');
}

View File

@@ -24,10 +24,9 @@ class OQLToSQLNestedSelectTest extends ItopDataTestCase
const USE_TRANSACTION = false;
const TEST_CSV_RESULT = 'OQLToSQLTest.csv';
public function setUp()
public function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');
SetupUtils::builddir(APPROOT.'log/test/OQLToSQL');
}

View File

@@ -26,10 +26,9 @@ class OQLToSQLTest extends ItopDataTestCase
const USE_TRANSACTION = false;
const TEST_CSV_RESULT = 'OQLToSQLTest.csv';
public function setUp()
public function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');
SetupUtils::builddir(APPROOT.'log/test/OQLToSQL');
}

View File

@@ -24,13 +24,6 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
*/
class DashboardLayoutTest extends ItopTestCase
{
public function setUp()
{
parent::setUp();
require_once APPROOT.'application/dashboardlayout.class.inc.php';
}
/**
* @return array
*/

View File

@@ -24,12 +24,6 @@
*/
class UtilsTest extends \Combodo\iTop\Test\UnitTest\ItopTestCase
{
public function setUp()
{
parent::setUp();
require_once(APPROOT.'application/utils.inc.php');
}
public function testEndsWith()
{
$this->assertFalse(utils::EndsWith('a', 'bbbb'));

View File

@@ -27,7 +27,7 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
class iTopComposerTest extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
clearstatcache();
@@ -40,7 +40,7 @@ class iTopComposerTest extends ItopTestCase
public function testIsTestDir($sDirName, $bIsTest)
{
$isTestDir = iTopComposer::IsTestDir($sDirName);
$this->assertInternalType('int', $isTestDir);
$this->assertIsInt($isTestDir);
if (true === $bIsTest) {
$this->assertTrue(($isTestDir > 0));
} else {

View File

@@ -34,13 +34,6 @@ class privUITransactionFileTest extends ItopDataTestCase
const USER1_TEST_LOGIN = 'user1_support_test_privUITransaction';
const USER2_TEST_LOGIN = 'user2_support_test_privUITransaction';
public function setUp()
{
parent::setUp();
require_once(APPROOT.'/application/startup.inc.php');
// require_once(APPROOT.'application/utils.inc.php');
}
/**
* @dataProvider cleanupOldTransactionsProvider
*/

View File

@@ -53,16 +53,6 @@ class CriterionConversionTest extends ItopDataTestCase
{
const CREATE_TEST_ORG = true;
/**
* @throws \Exception
*/
protected function setUp()
{
parent::setUp();
require_once(APPROOT."sources/application/search/criterionconversionabstract.class.inc.php");
}
/**
* @dataProvider ToOqlProvider
*

View File

@@ -29,7 +29,7 @@
namespace Combodo\iTop\Test\UnitTest\Application\Search;
use Combodo\iTop\Application\Search\CriterionParser;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
/**
* @group itopRequestMgmt
@@ -37,16 +37,8 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
* @preserveGlobalState disabled
* @backupGlobals disabled
*/
class CriterionParserTest extends ItopTestCase
class CriterionParserTest extends ItopDataTestCase
{
protected function setUp()
{
parent::setUp();
require_once(APPROOT."application/startup.inc.php");
require_once(APPROOT."sources/application/search/criterionparser.class.inc.php");
}
public function testParse()
{
$sBaseOql = 'SELECT UserRequest';

View File

@@ -38,16 +38,6 @@ class SearchFormTest extends ItopDataTestCase
{
const CREATE_TEST_ORG = true;
/**
* @throws Exception
*/
protected function setUp()
{
parent::setUp();
require_once(APPROOT."sources/application/search/searchform.class.inc.php");
}
/**
* @dataProvider GetFieldsProvider
* @throws \OQLException

View File

@@ -1,10 +1,10 @@
{
"require": {
"phpunit/phpunit": "^6"
},
"autoload": {
"psr-4": { "": "src/" }
"require-dev": {
"phpunit/phpunit": "^8.5.23"
},
"autoload": {
"psr-4": {
"": "src/"
}
}
}

994
test/composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,8 @@ use MetaModel;
class BulkChangeTest extends ItopDataTestCase {
const CREATE_TEST_ORG = true;
protected function setUp() {
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'core/bulkchange.class.inc.php');

View File

@@ -0,0 +1,75 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Core;
use CMDBObject;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use MetaModel;
/**
* @since 2.7.7 3.0.2 3.1.0 N°3717 tests history objects creation
*
* @package Combodo\iTop\Test\UnitTest\Core
*/
/**
* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
* @backupGlobals disabled
*/
class CMDBObjectTest extends ItopDataTestCase
{
/**
* @covers CMDBObject::SetCurrentChange
*/
public function testCurrentChange()
{
// save initial conditions
$oInitialCurrentChange = CMDBObject::GetCurrentChange();
$sInitialTrackInfo = CMDBObject::GetTrackInfo();
// reset current change
CMDBObject::SetCurrentChange(null);
//-- new object with only track info
$sTrackInfo = 'PHPUnit test';
CMDBObject::SetTrackInfo($sTrackInfo);
/** @var \DocumentWeb $oTestObject */
$oTestObject = MetaModel::NewObject('DocumentWeb');
$oTestObject->Set('name', 'PHPUnit test');
$oTestObject->Set('org_id', 1);
$oTestObject->Set('url', 'https://www.combodo.com');
$oTestObject->DBWrite();
self::assertFalse(CMDBObject::GetCurrentChange()->IsNew(), 'TrackInfo : Current change persisted');
self::assertEquals($sTrackInfo, CMDBObject::GetCurrentChange()->Get('userinfo'),
'TrackInfo : current change created with expected trackinfo');
//-- new object with non persisted current change
$sTrackInfo2 = $sTrackInfo.'_2';
/** @var \CMDBChange $oCustomChange */
$oCustomChange = MetaModel::NewObject('CMDBChange');
$oCustomChange->Set('date', time());
$oCustomChange->Set('userinfo', $sTrackInfo2);
CMDBObject::SetCurrentChange($oCustomChange);
$oTestObject->Set('url', 'https://fr.wikipedia.org');
$oTestObject->DBUpdate();
self::assertFalse(CMDBObject::GetCurrentChange()->IsNew(), 'SetCurrentChange : Current change persisted');
self::assertEquals($sTrackInfo2, CMDBObject::GetCurrentChange()->Get('userinfo'),
'SetCurrentChange : current change created with expected trackinfo');
//-- new object with current change init using helper method
$sTrackInfo3 = $sTrackInfo.'_3';
CMDBObject::SetCurrentChangeFromParams($sTrackInfo3);
$oTestObject->Set('url', 'https://en.wikipedia.org');
$oTestObject->DBUpdate();
self::assertFalse(CMDBObject::GetCurrentChange()->IsNew(), 'SetCurrentChangeFromParams : Current change persisted');
self::assertEquals($sTrackInfo3, CMDBObject::GetCurrentChange()->Get('userinfo'),
'SetCurrentChangeFromParams : current change created with expected trackinfo');
// restore initial conditions
$oTestObject->DBDelete();
CMDBObject::SetCurrentChange($oInitialCurrentChange);
CMDBObject::SetTrackInfo($sInitialTrackInfo);
}
}

View File

@@ -21,7 +21,7 @@ use utils;
*/
class CMDBSourceTest extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();

View File

@@ -27,10 +27,10 @@ class TransactionsTest extends ItopTestCase
/** @var DeadLockInjection */
private $oMySQLiMock;
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once ('DeadLockInjection.php');
require_once('DeadLockInjection.php');
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
$sEnv = 'production';
$sConfigFile = APPCONF.$sEnv.'/config-itop.php';

View File

@@ -23,7 +23,6 @@ namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use ConfigPlaceholdersResolver;
use PHPUnit\Framework\TestCase;
/**
* @runTestsInSeparateProcesses
@@ -32,10 +31,10 @@ use PHPUnit\Framework\TestCase;
*/
class ConfigPlaceholdersResolverTest extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once (APPROOT.'core/config.class.inc.php');
require_once(APPROOT.'core/config.class.inc.php');
}
/**
* @dataProvider providerResolve

View File

@@ -31,10 +31,10 @@ use Config;
*/
class ConfigTest extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once (APPROOT.'core/config.class.inc.php');
require_once(APPROOT.'core/config.class.inc.php');
}
/**

View File

@@ -42,7 +42,7 @@ class DBObjectTest extends ItopDataTestCase
{
const CREATE_TEST_ORG = true;
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'core/dbobject.class.php');

View File

@@ -19,7 +19,7 @@ use DBSearch;
class DBSearchIntersectTest extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');
@@ -337,7 +337,6 @@ class DBSearchIntersectTest extends ItopTestCase
/**
* @dataProvider IntersectOptimizationProvider
* @doesNotPerformAssertions
*
* @param string $sOQL
* @param string $sResult

View File

@@ -20,7 +20,7 @@ class DBSearchJoinTest extends ItopDataTestCase {
const USE_TRANSACTION = false;
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');

View File

@@ -54,7 +54,7 @@ class DBSearchTest extends ItopDataTestCase
/**
* @throws \Exception
*/
protected function setUp()
protected function setUp(): void
{
parent::setUp();

View File

@@ -19,7 +19,7 @@ class DBSearchUpdateRealiasingMapTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');

View File

@@ -27,7 +27,7 @@ class LogAPITest extends ItopDataTestCase
private $mockFileLog;
private $oMetaModelConfig;
protected function setUp()
protected function setUp():void
{
parent::setUp();

View File

@@ -28,21 +28,20 @@ class LogFileNameBuilderTest extends ItopTestCase
clearstatcache(true, $sLogFile);
}
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once APPROOT.'core/log.class.inc.php';
}
protected function tearDown()
protected function tearDown(): void
{
parent::tearDown();
// remove log files created in the test
$aTestLogFiles = glob(__DIR__.DIRECTORY_SEPARATOR.self::TEST_LOGFILE_PREFIX.'*.'.self::TEST_LOGFILE_EXTENSION);
foreach ($aTestLogFiles as $sLogFile)
{
foreach ($aTestLogFiles as $sLogFile) {
unlink($sLogFile);
}
}

View File

@@ -24,7 +24,7 @@ class MetaModelTest extends ItopDataTestCase
protected static $sDefaultUserRequestTitle = 'Unit test title';
protected static $sDefaultUserRequestDescription = 'Unit test description';
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once APPROOT.'/core/metamodel.class.php';

View File

@@ -2,11 +2,9 @@
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Portal\Controller\ObjectController;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use ContextTag;
use MetaModel;
use PHPUnit\Exception;
use TriggerOnObjectCreate;
/**
@@ -24,7 +22,7 @@ class TriggerTest extends ItopDataTestCase
const USE_TRANSACTION = false;
protected function setUp()
protected function setUp(): void
{
parent::setUp();
}

View File

@@ -16,7 +16,7 @@ use MetaModel;
*/
class UniquenessConstraintTest extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'/core/metamodel.class.php');

View File

@@ -47,7 +47,7 @@ use utils;
*/
class UserRightsTest extends ItopDataTestCase
{
public function setUp()
public function setUp(): void
{
parent::setUp();

View File

@@ -7,7 +7,7 @@ use DateTime;
class WeeklyScheduledProcessTest extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'core/backgroundprocess.inc.php');

View File

@@ -27,7 +27,6 @@
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use PHPUnit\Framework\TestCase;
define('UNIT_MAX_CACHE_FILES', 10);
@@ -40,7 +39,7 @@ define('UNIT_MAX_CACHE_FILES', 10);
class apcEmulationTest extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'core/apc-emulation.php');
@@ -48,7 +47,7 @@ class apcEmulationTest extends ItopTestCase
apc_clear_cache();
}
public function tearDown()
public function tearDown(): void
{
apc_clear_cache();
}

View File

@@ -41,7 +41,7 @@ class dictApcuTest extends ItopTestCase
private $oApcService;
private $sDictionaryFolder;
protected function setUp()
protected function setUp(): void
{
parent::setUp();
@@ -108,12 +108,12 @@ PHP;
file_put_contents($sDictionaryFolder . DIRECTORY_SEPARATOR . "$sLanguageCodeInFilename.dict.php", $sContent);
}
protected function tearDown()
protected function tearDown(): void
{
foreach (glob(APPROOT."env-$this->sEnvName" . DIRECTORY_SEPARATOR . "dictionaries" . DIRECTORY_SEPARATOR . "*") as $sFile){
foreach (glob(APPROOT."env-$this->sEnvName".DIRECTORY_SEPARATOR."dictionaries".DIRECTORY_SEPARATOR."*") as $sFile) {
unlink($sFile);
}
rmdir(APPROOT."env-$this->sEnvName" . DIRECTORY_SEPARATOR . "dictionaries");
rmdir(APPROOT."env-$this->sEnvName".DIRECTORY_SEPARATOR."dictionaries");
rmdir(APPROOT."env-$this->sEnvName");
}

View File

@@ -39,8 +39,7 @@ use Exception;
class dictTest extends ItopTestCase
{
private $sEnvName;
protected function setUp()
protected function setUp(): void
{
parent::setUp();
@@ -74,7 +73,7 @@ PHP;
$_SESSION['itop_env'] = $this->sEnvName;
}
protected function tearDown()
protected function tearDown(): void
{
foreach (glob(APPROOT."env-$this->sEnvName".DIRECTORY_SEPARATOR."dictionaries".DIRECTORY_SEPARATOR."*") as $sFile) {
unlink($sFile);

View File

@@ -14,10 +14,11 @@ class iTopConfigParserTest extends ItopTestCase
private $tmpSavePath;
private $sConfigPath;
public function setUp()
public function setUp(): void
{
parent::setUp();
require_once APPROOT.'/core/iTopConfigParser.php';
require_once APPROOT.'/setup/runtimeenv.class.inc.php';
clearstatcache();
$this->sConfigPath = utils::GetConfigFilePath();
@@ -32,7 +33,7 @@ class iTopConfigParserTest extends ItopTestCase
clearstatcache();
}
public function tearDown()
public function tearDown(): void
{
parent::tearDown();
if ($this->conf_exists) {
@@ -150,8 +151,6 @@ class iTopConfigParserTest extends ItopTestCase
}
/**
* @doesNotPerformAssertions
*
* @throws \ConfigException
* @throws \CoreException
*/
@@ -202,21 +201,15 @@ CONF;
}
/**
* @doesNotPerformAssertions
*
* @throws \ConfigException
* @throws \CoreException
*/
public function testConfigWriteToFile_FromScratchInstallation()
{
$sConfigPath = utils::GetConfigFilePath();
$oConfig = new Config($sConfigPath, false);
try{
clearstatcache();
$oConfig->WriteToFile();
}catch(\Exception $e)
{
$this->assertTrue(false, "failed writetofile with no initial file: " . $e->getMessage());
}
$oConfig = new Config();
clearstatcache();
$oTestEnv = new RunTimeEnvironment('test-phpunit');
$oTestEnv->WriteConfigFileSafe($oConfig);
$this->assertTrue(true, "Config file was written");
}
}

View File

@@ -47,12 +47,12 @@ class ormLinkSetTest extends ItopDataTestCase
const CREATE_TEST_ORG = true;
/**
* @throws Exception
*/
protected function setUp()
{
parent::setUp();
}
* @throws Exception
*/
protected function setUp(): void
{
parent::setUp();
}
/**
*

View File

@@ -50,7 +50,7 @@ class ormTagSetTest extends ItopDataTestCase
/**
* @throws Exception
*/
protected function setUp()
protected function setUp(): void
{
parent::setUp();

View File

@@ -9,7 +9,7 @@ abstract class AbstractDOMSanitizerTest extends ItopTestCase
const INPUT_DIRECTORY = 'input';
const OUTPUT_DIRECTORY = 'output';
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/utils.inc.php');

View File

@@ -21,13 +21,12 @@ use UserLocal;
class UserLocalTest extends ItopDataTestCase
{
public function setUp()
public function setUp(): void
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');
require_once (APPROOT.'test/coreExtensions/UserLocalTest/UserLocalPasswordPolicyMock.php');
require_once (APPROOT.'env-production/authent-local/model.authent-local.php');
require_once(APPROOT.'test/coreExtensions/UserLocalTest/UserLocalPasswordPolicyMock.php');
require_once(APPROOT.'env-production/authent-local/model.authent-local.php');
}
/**

View File

@@ -29,7 +29,7 @@ use iTopDesignFormat;
*/
class iTopModulesXmlVersionIntegrationTest extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();

View File

@@ -15,7 +15,7 @@ use PhpParser\PrettyPrinter\Standard;
class iTopConfigAstValidatorTest extends ItopTestCase
{
public function setUp()
public function setUp(): void
{
parent::setUp();

View File

@@ -16,7 +16,7 @@ use PhpParser\PrettyPrinter\Standard;
class iTopConfigSyntaxValidatorTest extends ItopTestCase
{
public function setUp()
public function setUp(): void
{
parent::setUp();

View File

@@ -43,14 +43,6 @@ class ItopTicketTest extends ItopDataTestCase
{
const CREATE_TEST_ORG = true;
/**
* @throws Exception
*/
protected function setUp()
{
parent::setUp();
}
/**
* <pre>
* Given:

View File

@@ -1,68 +1,53 @@
<!-- Copyright (c) 2010-2021 Combodo SARL -->
<!-- -->
<!-- This file is part of iTop. -->
<!-- -->
<!-- iTop is free software; you can redistribute it and/or modify -->
<!-- it under the terms of the GNU Affero General Public License as published by -->
<!-- the Free Software Foundation, either version 3 of the License, or -->
<!-- (at your option) any later version. -->
<!-- -->
<!-- iTop is distributed in the hope that it will be useful, -->
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!-- GNU Affero General Public License for more details. -->
<!-- -->
<!-- You should have received a copy of the GNU Affero General Public License -->
<!-- along with iTop. If not, see <http://www.gnu.org/licenses/> -->
<!-- -->
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd"
bootstrap="unittestautoload.php"
backupGlobals="true"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnRisky="false"
stopOnSkipped="false"
verbose="true"
>
<phpunit bootstrap="unittestautoload.php"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
backupGlobals="true"
backupStaticAttributes="false"
cacheTokens="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
forceCoversAnnotation="false"
mapTestClassNameToCoveredClassName="false"
printerClass="\PHPUnit\TextUI\ResultPrinter"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
stopOnRisky="false"
timeoutForSmallTests="1"
timeoutForMediumTests="10"
timeoutForLargeTests="60"
verbose="false">
<php>
<ini name="display_errors" value="true"/>
<ini name="error_reporting" value="true"/>
</php>
<testsuites>
<testsuite name="Extensions">
<directory>../env-production/*/test</directory>
<testsuite name="Application">
<directory>application</directory>
</testsuite>
<testsuite name="Core">
<directory>core</directory>
</testsuite>
<testsuite name="Webservices">
<directory>webservices</directory>
<testsuite name="CoreExtensions">
<directory>coreExtensions</directory>
</testsuite>
<testsuite name="Tickets">
<directory>itop-tickets</directory>
<testsuite name="Integration">
<directory>integration</directory>
</testsuite>
<testsuite name="Config">
<testsuite name="Itop-Config">
<directory>itop-config</directory>
</testsuite>
<testsuite name="Application">
<directory>application</directory>
<testsuite name="Itop-Tickets">
<directory>itop-tickets</directory>
</testsuite>
<!-- OQL : taking too long (20min+)... we should move this to nightlies ! See N°4655 -->
<!--testsuite name="OQL">
<directory>OQL</directory>
</testsuite-->
<testsuite name="Setup">
<directory>setup</directory>
</testsuite>
<testsuite name="Sources">
<directory>sources</directory>
</testsuite>
@@ -72,14 +57,12 @@
<testsuite name="Synchro">
<directory>synchro</directory>
</testsuite>
<testsuite name="Setup">
<directory>setup</directory>
<testsuite name="Webservices">
<directory>webservices</directory>
</testsuite>
<testsuite name="Integration">
<directory>integration</directory>
</testsuite>
<testsuite name="CoreExtensions">
<directory>coreExtensions</directory>
<testsuite name="Extensions">
<directory>../env-production/*/test</directory>
</testsuite>
</testsuites>

View File

@@ -1,44 +1,21 @@
<!-- Copyright (c) 2010-2021 Combodo SARL -->
<!-- -->
<!-- This file is part of iTop. -->
<!-- -->
<!-- iTop is free software; you can redistribute it and/or modify -->
<!-- it under the terms of the GNU Affero General Public License as published by -->
<!-- the Free Software Foundation, either version 3 of the License, or -->
<!-- (at your option) any later version. -->
<!-- -->
<!-- iTop is distributed in the hope that it will be useful, -->
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!-- GNU Affero General Public License for more details. -->
<!-- -->
<!-- You should have received a copy of the GNU Affero General Public License -->
<!-- along with iTop. If not, see <http://www.gnu.org/licenses/> -->
<!-- -->
<phpunit bootstrap="unittestautoload.php"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
backupGlobals="true"
backupStaticAttributes="false"
cacheTokens="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
forceCoversAnnotation="false"
mapTestClassNameToCoveredClassName="false"
printerClass="\PHPUnit\TextUI\ResultPrinter"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
stopOnRisky="false"
timeoutForSmallTests="1"
timeoutForMediumTests="10"
timeoutForLargeTests="60"
verbose="false">
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd"
bootstrap="unittestautoload.php"
backupGlobals="true"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnRisky="false"
stopOnSkipped="false"
verbose="true"
>
<testsuites>
<testsuite name="PostBuildIntegration">

View File

@@ -17,7 +17,7 @@ use PHPUnit\Exception;
*/
class TestForITopDesignFormatClass extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
@@ -148,6 +148,7 @@ class TestForITopDesignFormatClass extends ItopTestCase
{
if (is_dir($sPath))
{
/** @noinspection SlowArrayOperationsInLoopInspection */
$aDataModelFiles = array_merge($aDataModelFiles, $this->GetDataModelFiles($sPath));
}
else if (preg_match("/datamodel\..*\.xml/", basename($sPath)))

View File

@@ -147,6 +147,7 @@ class QueryLogEntry
$iRepeat = utils::ReadParam('repeat', 3);
try
{
$resQuery = null;
$fRefTime = MyHelpers::getmicrotime();
for($i = 0 ; $i < $iRepeat ; $i++)
{
@@ -167,7 +168,6 @@ class QueryLogEntry
catch (Exception $e)
{
$this->aErrors[] = "Failed to execute the SQL:".$e->getMessage();
$resQuery = null;
}
if ($resQuery)
{

View File

@@ -19,12 +19,10 @@ class DBBackupTest extends ItopTestCase
* @throws \MySQLException
* @throws \ConfigException
*/
protected function setUp()
protected function setUp(): void
{
parent::setUp();
require_once(APPROOT.'core/config.class.inc.php');
require_once(APPROOT.'setup/backup.class.inc.php');
require_once(APPROOT.'core/cmdbsource.class.inc.php'); // DBBackup dependency
// We need a connection to the DB, so let's open it !
// We are using the default config file... as the server might not be configured for all the combination we are testing

View File

@@ -22,7 +22,7 @@ class SetupUtilsTest extends ItopTestCase
const INFO = 2;
const TRACE = 3; // for log purposes : replace old SetupLog::Log calls
protected function setUp()
protected function setUp(): void
{
parent::setUp();

View File

@@ -18,7 +18,7 @@ use iTopDesignFormat;
*/
class TestForITopDesignFormatClass extends ItopTestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();

View File

@@ -1,7 +1,5 @@
<?php
include('./vendor/autoload.php');
@include_once('ItopTestCase.php');
@include_once('ItopDataTestCase.php');
@include_once('./vendor/autoload.php');
include('ItopTestCase.php');
include('ItopDataTestCase.php');

View File

@@ -30,16 +30,16 @@ class RestTest extends ItopDataTestCase
/**
* @throws Exception
*/
protected function setUp()
{
parent::setUp();
require_once(APPROOT.'application/startup.inc.php');
$this->sLogin = "rest-user-" . date('dmYHis');
$this->CreateTestOrganization();
protected function setUp(): void
{
parent::setUp();
if (!empty($this->sTmpFile)){
unlink($this->sTmpFile);
}
$this->sLogin = "rest-user-".date('dmYHis');
$this->CreateTestOrganization();
if (!empty($this->sTmpFile)) {
unlink($this->sTmpFile);
}
$sConfigFile = \utils::GetConfig()->GetLoadedFile();
@chmod($sConfigFile, 0770);

View File

@@ -266,9 +266,7 @@ function CronExec($oP, $bVerbose, $bDebug=false)
// N°3219 for each process will use a specific CMDBChange object with a specific track info
// Any BackgroundProcess can overrides this as needed
CMDBObject::SetCurrentChange(null);
CMDBObject::SetTrackInfo("Background task ($sTaskClass)");
CMDBObject::SetTrackOrigin(null);
CMDBObject::SetCurrentChangeFromParams("Background task ($sTaskClass)");
// Run the task and record its next run time
if ($bVerbose)