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

# Conflicts:
#	tests/php-unit-tests/integration-tests/DictionariesConsistencyTest.php
#	tests/php-unit-tests/src/BaseTestCase/ItopTestCase.php
#	tests/php-unit-tests/unitary-tests/core/CMDBSource/TransactionsTest.php
#	tests/php-unit-tests/unitary-tests/sources/Application/TwigBase/Twig/TwigTest.php
This commit is contained in:
Romain Quetiez
2023-10-27 14:12:06 +02:00
23 changed files with 315 additions and 198 deletions

View File

@@ -6,7 +6,7 @@ use Combodo\iTop\Application\Helper\Session;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
/**
* @runTestsInSeparateProcesses
* @runClassInSeparateProcess Required because PHPUnit outputs something earlier, thus causing the headers to be sent
*/
class SessionTest extends ItopTestCase
{
@@ -24,18 +24,9 @@ class SessionTest extends ItopTestCase
/**
* @covers \Combodo\iTop\Application\Helper\Session::Start
*/
public function testStart()
{
$this->assertNull(Session::$iSessionId);
Session::Start();
$this->assertNotNull(Session::$iSessionId);
}
/**
* @covers \Combodo\iTop\Application\Helper\Session::WriteClose
*/
public function testWriteClose()
public function testStartWriteClose()
{
$this->assertNull(Session::$iSessionId);
Session::Start();

View File

@@ -12,46 +12,65 @@ use ThemeHandler;
class ThemeHandlerTest extends ItopTestCase
{
const PATTERN = '|\\\/var[^"]+testimages|';
private $oCompileCSSServiceMock;
private $sCompiledThemesDirAbsPath;
private $sCssAbsPath;
private $sDmCssAbsPath;
private $sJsonThemeParamFile;
private $sTmpDir;
private $aDirsToCleanup= [];
static private $sTmpDir = null;
static private $aDirsToCleanup = [];
static private $sAbsoluteImagePath;
static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
static::$sTmpDir = static::CreateTmpdir().'/';
static::$aDirsToCleanup[] = static::$sTmpDir;
static::$sAbsoluteImagePath = APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/copied/testimages/';
static::RecurseMkdir(static::$sAbsoluteImagePath);
// Required by testCompileThemesxxx - copy images in test dir
static::RecurseCopy(APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/', static::$sAbsoluteImagePath);
static::$aDirsToCleanup[] = dirname(static::$sAbsoluteImagePath);
}
static function tearDownAfterClass(): void
{
foreach (static::$aDirsToCleanup as $sDir)
{
static::RecurseRmdir($sDir);
}
parent::tearDownAfterClass();
}
protected static function InitCSSDirectory()
{
static::RecurseCopy(APPROOT."/tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css", static::$sTmpDir."/branding/css");
}
public function setUp(): void
{
parent::setUp();
$this->RequireOnceItopFile('application/themehandler.class.inc.php');
$this->RequireOnceItopFile('setup/modelfactory.class.inc.php');
$this->RequireOnceUnitTestFile('../setup/SubMFCompiler.php');
$this->oCompileCSSServiceMock = $this->createMock('CompileCSSService');
ThemeHandler::mockCompileCSSService($this->oCompileCSSServiceMock);
$this->sTmpDir = $this->CreateTmpdir().'/';
$this->aDirsToCleanup[] = $this->sTmpDir;
$this->sCompiledThemesDirAbsPath = $this->sTmpDir."branding/themes/";
$this->recurseMkdir($this->sCompiledThemesDirAbsPath."basque-red/");
$this->sCompiledThemesDirAbsPath = static::$sTmpDir."branding/themes/";
static::RecurseMkdir($this->sCompiledThemesDirAbsPath."basque-red/");
$this->sCssAbsPath = $this->sCompiledThemesDirAbsPath.'basque-red/main.css';
$this->sDmCssAbsPath = $this->sCompiledThemesDirAbsPath.'datamodel-compiled-scss-rules.scss';
$this->sJsonThemeParamFile = $this->sCompiledThemesDirAbsPath.'basque-red/theme-parameters.json';
$this->RecurseCopy(APPROOT."/tests/php-unit-tests/unitary-tests/application/theme-handler/expected/css", $this->sTmpDir."/branding/css");
}
public function tearDown(): void
{
parent::tearDown();
foreach ($this->aDirsToCleanup as $sDir)
{
echo $sDir;
$this->RecurseRmdir($sDir);
}
}
function KeepSignatureDiff($sSignature1, $sSignature2) : string {
@@ -83,14 +102,14 @@ class ThemeHandlerTest extends ItopTestCase
$aDiffOuput[$sKey] = $aCurrentDiffVal;
}
} else if ($oVal1 !== $aSignature2[$sKey]){
$aDiffOuput[$sKey] = "expected:$oVal1 | actual:$aSignature2[$sKey]";
$aDiffOuput[$sKey] = "expected:$oVal1 | actual:$aSignature2[$sKey]";
}
}
return json_encode($aDiffOuput, true);
}
function recurseMkdir($dir)
public static function RecurseMkdir($dir)
{
if (is_dir($dir))
{
@@ -98,7 +117,7 @@ class ThemeHandlerTest extends ItopTestCase
}
$sParentDir = dirname($dir);
if (!$this->recurseMkdir($sParentDir))
if (!static::RecurseMkdir($sParentDir))
{
return false;
}
@@ -141,6 +160,8 @@ JSON;
*/
public function testCompileThemeWithoutCssFile_FocusOnParamAttribute($readFromParamAttributeFromJson=false)
{
static::InitCSSDirectory();
$sExpectJsonFilePath = APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/theme-parameters.json';
$sExpectedThemeParamJson = file_get_contents($sExpectJsonFilePath);
$aThemeParameters = json_decode($sExpectedThemeParamJson, true);
@@ -160,11 +181,11 @@ JSON;
if($readFromParamAttributeFromJson)
{
copy($sExpectJsonFilePath, $this->sJsonThemeParamFile);
$this->assertTrue(ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", null, [$this->sTmpDir.'/branding/themes/'], $this->sTmpDir));
$this->assertTrue(ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", null, [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
}
else
{
$this->assertTrue(ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", $aThemeParameters, [$this->sTmpDir.'/branding/themes/'], $this->sTmpDir));
$this->assertTrue(ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", $aThemeParameters, [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
}
$this->assertTrue(is_file($this->sCssAbsPath));
$this->assertEquals($sExpectedThemeParamJson, file_get_contents($this->sJsonThemeParamFile));
@@ -189,14 +210,14 @@ JSON;
*/
public function testCompileThemesEmptyArray($ThemeParametersJson, $CompileCount=0)
{
$sCssPath = $this->sTmpDir . '/branding/themes/basque-red/main.css';
$sCssPath = static::$sTmpDir . '/branding/themes/basque-red/main.css';
copy(APPROOT . 'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main.css', $sCssPath);
$this->oCompileCSSServiceMock->expects($this->exactly($CompileCount))
->method("CompileCSSFromSASS")
->willReturn("====CSSCOMPILEDCONTENT====");
$this->assertEquals($CompileCount!=0,ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", json_decode($ThemeParametersJson, true), [$this->sTmpDir.'/branding/themes/'], $this->sTmpDir));
$this->assertEquals($CompileCount!=0,ThemeHandler::CompileTheme('basque-red', true, "COMPILATIONTIMESTAMP", json_decode($ThemeParametersJson, true), [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
}
public function CompileThemesProviderEmptyArray()
@@ -213,6 +234,14 @@ JSON;
/**
* @return array
* mixed $ThemeParametersJson
* int $iCompileCSSFromSASSCount
* boolean $bMissingFile
* boolean $bFilesTouchedRecently
* boolean $bFileMd5sumModified
* null $sFileToTest
* null $sExpectedMainCssPath
* bool $bSetup
*/
public function CompileThemesProvider()
{
@@ -260,26 +289,24 @@ JSON;
*/
public function testCompileThemes($ThemeParametersJson, $iCompileCSSFromSASSCount, $bMissingFile=false, $bFilesTouchedRecently=false, $bFileMd5sumModified=false, $sFileToTest=null, $sExpectedMainCssPath=null, $bSetup=true)
{
static::InitCSSDirectory();
$sAfterReplacementCssVariableMd5sum='';
if (is_file($this->sTmpDir.'/'.$sFileToTest))
if (is_file(static::$sTmpDir.'/'.$sFileToTest))
{
$sFileToTest = $this->sTmpDir.'/'.$sFileToTest;
$sFileToTest = static::$sTmpDir.'/'.$sFileToTest;
} else {
$sFileToTest = APPROOT.'/'.$sFileToTest;
}
//copy images in test dir
$sAbsoluteImagePath = APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/copied/testimages/';
$this->recurseMkdir($sAbsoluteImagePath);
$this->aDirsToCleanup[] = dirname($sAbsoluteImagePath);
$this->RecurseCopy(APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/testimages/', $sAbsoluteImagePath);
// Backup the file to test
copy($sFileToTest, static::$sTmpDir.'/file-to-test-backup');
//change approot-relative in css-variable to use absolute path
$sCssVarPath = $this->sTmpDir."/branding/css/DO_NOT_CHANGE.css-variables.scss";
$sCssVarPath = static::$sTmpDir."/branding/css/DO_NOT_CHANGE.css-variables.scss";
$sBeforeReplacementCssVariableMd5sum = md5_file($sCssVarPath);
echo 'BEFORE :'.$sBeforeReplacementCssVariableMd5sum.' '.$sCssVarPath.' ';
$sCssVariableContent = file_get_contents($sCssVarPath);
$sLine = '$approot-relative: "'.$sAbsoluteImagePath.'" !default;';
$sLine = '$approot-relative: "'.static::$sAbsoluteImagePath.'" !default;';
$sCssVariableContent = preg_replace("/\\\$approot-relative: \"(.*)\"/", $sLine, $sCssVariableContent);
file_put_contents($sCssVarPath, $sCssVariableContent);
if ($bMissingFile)
@@ -296,30 +323,23 @@ JSON;
//change cssvar md5sum + image absolute paths
$sMainCssContent = file_get_contents(APPROOT."tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/main_testcompilethemes.css");
$sMainCssContent = preg_replace('/MD5SUM/', $sAfterReplacementCssVariableMd5sum, $sMainCssContent);
$sReplacement = rtrim($sAbsoluteImagePath, '/');
$sReplacement = rtrim(static::$sAbsoluteImagePath, '/');
$sReplacement=preg_replace('|\/|', '\/', $sReplacement);
$sMainCssContent = preg_replace(static::PATTERN, $sReplacement, $sMainCssContent);
$cssPath = $this->sTmpDir . '/branding/themes/basque-red/main.css';
echo 'PUT md5sum: '.$sAfterReplacementCssVariableMd5sum.' in '.$cssPath.' ';
$cssPath = static::$sTmpDir . '/branding/themes/basque-red/main.css';
file_put_contents($cssPath, $sMainCssContent);
//should be after main.css modification to make sure precompilation check will be performed
if ($bFilesTouchedRecently)
{
sleep(1);
touch($sFileToTest);
touch($sFileToTest, time() + 2, time() + 2);
}
//same: it should be after main.css modification
if ($bFileMd5sumModified)
{
$sMd5sum = md5_file($sFileToTest);
echo ' BEFORE touch: ' . $sMd5sum .' ' . $sFileToTest;
sleep(1);
file_put_contents($sFileToTest, "###\n".file_get_contents($sFileToTest));
$sMd5sum = md5_file($sFileToTest);
echo ' AFTER touch: ' . $sMd5sum .' ' . $sFileToTest;
touch($sFileToTest, time() + 2, time() + 2);
}
if (is_file($sCssVarPath))
@@ -332,7 +352,7 @@ JSON;
->willReturn("====CSSCOMPILEDCONTENT====");
$aThemeParameters = json_decode($ThemeParametersJson, true);
$this->assertEquals($iCompileCSSFromSASSCount!=0, ThemeHandler::CompileTheme('basque-red', $bSetup, "COMPILATIONTIMESTAMP", $aThemeParameters, [$this->sTmpDir.'/branding/themes/'], $this->sTmpDir));
$this->assertEquals($iCompileCSSFromSASSCount!=0, ThemeHandler::CompileTheme('basque-red', $bSetup, "COMPILATIONTIMESTAMP", $aThemeParameters, [static::$sTmpDir.'/branding/themes/'], static::$sTmpDir));
if ($iCompileCSSFromSASSCount==1)
{
@@ -347,9 +367,11 @@ JSON;
$aReplacements = [$sReplacement, $sAfterReplacementCssVariableMd5sum];
$aReplacements[] = md5(json_encode($aThemeParameters['variables']));
$aReplacements[] = $sAfterReplacementCssVariableMd5sum;
var_dump($aReplacements);
$this->DoInnerJsonValidation($sExpectedMainCssFile, $cssPath, $aPatterns, $aReplacements);
}
// Restore the file to test (possible improvement: do that in tearDown)
copy(static::$sTmpDir.'/file-to-test-backup', $sFileToTest);
}
public function DoInnerJsonValidation($sExpectedCssFile, $sActualCssFile, $aPatterns, $aReplacements)
@@ -396,8 +418,8 @@ JSON;
'\'abc/\'+ $approot-relative + "css/ui-lightness/images/toutou.png?v=" + $version',
"\$approot-relative + \"css/ui-lightness/images/toto.png?v=\" + \$version",
'$approot-relative + \'css/ui-lightness/images/titi.gif?v=\' + $version1',
'"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=" + $version',
'$approot-relative + \'node_modules/raleway-webfont/fonts/Raleway-Thin.jpeg\'',
'"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7?v=" + $version',
'$approot-relative + \'node_modules/raleway-webfont/fonts/Raleway-Thin.jpeg\'',
];
$aIncludedUrls['aCompleteUrls'];
@@ -432,13 +454,13 @@ SCSS;
$aExpectedFoundVariables = [
'gabu' => 'zomeu',
'toto' => 'titi',
'approot-relative' => '../../../../../',
'approot-relative2' => '../../',
'gray-base' => '#000',
'a' => 'b',
'content-color' => '#eeeeee',
'default-font-family' => 'Trebuchet MS,Tahoma,Verdana,Arial,sans-serif',
'icons-filter' => 'hue-rotate(0deg)',
'approot-relative' => '../../../../../',
'approot-relative2' => '../../',
'gray-base' => '#000',
'a' => 'b',
'content-color' => '#eeeeee',
'default-font-family' => 'Trebuchet MS,Tahoma,Verdana,Arial,sans-serif',
'icons-filter' => 'hue-rotate(0deg)',
'toto' => 'titi',
];
$this->assertEquals($aExpectedFoundVariables, $aFoundVariables);
@@ -460,10 +482,10 @@ $icons-filter: hue-rotate(0deg) !default;
$toto : titi;
SCSS;
file_put_contents($this->sTmpDir . DIRECTORY_SEPARATOR . 'css-variable.scss', $sContent);
file_put_contents(static::$sTmpDir . DIRECTORY_SEPARATOR . 'css-variable.scss', $sContent);
$aVariables = ThemeHandler::GetVariablesFromFile(
[ 'css-variable.scss' ],
[ $this->sTmpDir ]
[ static::$sTmpDir ]
);
$aExpectedVariables = [
@@ -512,8 +534,10 @@ SCSS;
public function testGetIncludedImages()
{
$aStylesheetFile=glob($this->sTmpDir."/branding/css/*.scss");
$aStylesheetFile[]=$this->sTmpDir."/branding/css/ui-lightness/DO_NOT_CHANGE.jqueryui.scss";
static::InitCSSDirectory();
$aStylesheetFile=glob(static::$sTmpDir."/branding/css/*.scss");
$aStylesheetFile[]=static::$sTmpDir."/branding/css/ui-lightness/DO_NOT_CHANGE.jqueryui.scss";
$expectJsonFilePath = APPROOT.'tests/php-unit-tests/unitary-tests/application/theme-handler/expected/themes/basque-red/theme-parameters.json';
$expectedThemeParamJson = file_get_contents($expectJsonFilePath);
$aThemeParametersVariables = json_decode($expectedThemeParamJson, true);
@@ -538,7 +562,7 @@ SCSS;
* @throws \Exception
*/
public function testFindStylesheetFile(string $sFileToFind, array $aAllImports){
$sImportsPath = $this->sTmpDir.'branding/';
$sImportsPath = static::$sTmpDir.'branding/';
// Windows compat O:)
$sFileToFind = $this->UpdateDirSep($sFileToFind);

View File

@@ -36,20 +36,18 @@ class ApplicationExtensionTest extends ItopCustomDatamodelTestCase
* - Add the API to the provider
* - Add a class extending / implementing the API in ./Delta/application-extension-usages-in-snippets.xml
*
* @param string $sAPIFQCN
* @param string $sCallMethod
*
* @return void
* @dataProvider ExtensionAPIRegisteredAndCalledProvider
*/
public function testExtensionAPIRegisteredAndCalled(string $sAPIFQCN, string $sCallMethod)
public function testExtensionAPIRegisteredAndCalled()
{
if ($sCallMethod === static::ENUM_API_CALL_METHOD_ENUMPLUGINS) {
$iExtendingClassesCount = count(MetaModel::EnumPlugins($sAPIFQCN));
} else {
$iExtendingClassesCount = count(utils::GetClassesForInterface($sAPIFQCN, '', ['[\\\\/]lib[\\\\/]', '[\\\\/]node_modules[\\\\/]', '[\\\\/]test[\\\\/]', '[\\\\/]tests[\\\\/]']));
foreach ($this->ExtensionAPIRegisteredAndCalledProvider() as list($sAPIFQCN, $sCallMethod)) {
if ($sCallMethod === static::ENUM_API_CALL_METHOD_ENUMPLUGINS) {
$iExtendingClassesCount = count(MetaModel::EnumPlugins($sAPIFQCN));
} else {
$iExtendingClassesCount = count(utils::GetClassesForInterface($sAPIFQCN, '', ['[\\\\/]lib[\\\\/]', '[\\\\/]node_modules[\\\\/]', '[\\\\/]test[\\\\/]', '[\\\\/]tests[\\\\/]']));
}
$this->assertGreaterThan(0, $iExtendingClassesCount, "Found no class extending the $sAPIFQCN API");
}
$this->assertGreaterThan(0, $iExtendingClassesCount, "Found no class extending the $sAPIFQCN API");
}
public function ExtensionAPIRegisteredAndCalledProvider(): array

View File

@@ -25,7 +25,6 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
use utils;
/**
* @runClassInSeparateProcess
* @covers utils
*/
class utilsTest extends ItopTestCase
@@ -245,7 +244,6 @@ class utilsTest extends ItopTestCase
}
/**
* @runInSeparateProcess
* @dataProvider GetAbsoluteUrlAppRootPersistency
*/
public function testGetAbsoluteUrlAppRootPersistency($bBehindReverseProxy,$bForceTrustProxy1 ,$sExpectedAppRootUrl1,$bForceTrustProxy2 , $sExpectedAppRootUrl2,$bForceTrustProxy3 , $sExpectedAppRootUrl3)
@@ -274,6 +272,9 @@ class utilsTest extends ItopTestCase
$this->assertEquals($sExpectedAppRootUrl2, utils::GetAbsoluteUrlAppRoot($bForceTrustProxy2));
$this->assertEquals($sExpectedAppRootUrl3, utils::GetAbsoluteUrlAppRoot($bForceTrustProxy3));
// Leave the place clean
static::SetNonPublicStaticProperty('utils', 'm_sAppRootUrl', null);
}

View File

@@ -26,6 +26,13 @@ class CMDBSourceTest extends ItopTestCase
$this->RequireOnceItopFile('/core/cmdbsource.class.inc.php');
}
protected function tearDown(): void
{
DbConnectionWrapper::SetDbConnectionMockForQuery();
parent::tearDown();
}
/**
* @covers CMDBSource::IsSameFieldTypes
* @dataProvider compareFieldTypesProvider

View File

@@ -1,6 +1,6 @@
<?php
/**
* @copyright Copyright (C) 2010-2023 Combodo SARL
* @copyright Copyright (C) 2010-2021 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -257,30 +257,28 @@ class TransactionsTest extends ItopTestCase
/**
* @return void
* @doesNotPerformAssertions
*/
public function testTransactionOpenedThenClosed()
public function testIsInsideTransaction()
{
CMDBSource::Query('START TRANSACTION;');
CMDBSource::Query('COMMIT;');
}
static::assertFalse(CMDBSource::IsInsideTransaction(), 'Should not be already inside a transaction');
/**
* 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()
{
// First, with a transaction ended by a "COMMIT" statement
CMDBSource::Query('START TRANSACTION;');
static::assertTrue(CMDBSource::IsInsideTransaction(), 'Should be inside a translation');
CMDBSource::Query('COMMIT;');
static::assertFalse(CMDBSource::IsInsideTransaction(), 'Should not be inside a transaction anymore');
// Second, with a transaction ended by a "ROLLBACK" statement
CMDBSource::Query('START TRANSACTION;');
static::assertTrue(CMDBSource::IsInsideTransaction(), 'Should be inside a translation (again)');
CMDBSource::Query('ROLLBACK;');
static::assertFalse(CMDBSource::IsInsideTransaction(), 'Should not be inside a transaction anymore');
}
protected function tearDown(): void
{
try {
DbConnectionWrapper::SetDbConnectionMockForQuery(); // Else will throw error on PHP 8.1+ (see N°6848)
DbConnectionWrapper::SetDbConnectionMockForQuery();
parent::tearDown();
}
catch (MySQLTransactionNotClosedException $e) {

View File

@@ -557,7 +557,7 @@ class ExpressionEvaluateTest extends ItopDataTestCase
public function EveryTimeFormatOnDateRangeProvider()
{
return array(
'10 years, day by day' => array('2000-01-01', 'P1D', 365 * 10),
'10 years, each 17 days' => array('2000-01-01', 'P17D', 365 * 10 / 17),
'1 day, hour by hour' => array('2000-01-01 00:01:02', 'PT1H', 24),
'1 hour, minute by minute' => array('2000-01-01 00:01:02', 'PT1M', 60),
'1 minute, second by second' => array('2000-01-01 00:01:02', 'PT1S', 60),

View File

@@ -30,8 +30,6 @@ class ExceptionLogTest extends ItopDataTestCase
}
/**
* @runInSeparateProcess
*
* @dataProvider logProvider
*/
public function testLogInFile($aLevels, $aExceptions, $sChannel, $aExpectedWriteNumber, $logLevelMin, $aExpectedDbWriteNumber, $logLevelMinWriteInDb)
@@ -91,14 +89,26 @@ class ExceptionLogTest extends ItopDataTestCase
$oExpectedLastEventIssue = $this->InvokeNonPublicStaticMethod('ExceptionLog', 'GetLastEventIssue', []);
if (0 == $iExpectedDbWriteNumber) {
$this->assertNull($oExpectedLastEventIssue);
if (!is_null($oExpectedLastEventIssue)) {
$this->fail("Level '$sLevel': unexpected EventIssue");
}
} else {
$this->assertInstanceOf(\EventIssue::class, $oExpectedLastEventIssue);
$this->assertInstanceOf(\EventIssue::class, $oExpectedLastEventIssue, "Level '$sLevel': missing EventIssue");
$this->assertEquals($aExpectedFileContext, $oExpectedLastEventIssue->Get('data'));
}
}
}
/**
* @return array[]
* aLevels: log levels to iterate on (AND name of the method that will be called on the underlying FileLog)
* aExceptions: For each log level => Exception to generate
* sChannel: Expected 2nd argument to the FileLog::{Level}
* aExpectedWriteNumber: For each log level => Number of times the method FileLog::{Level} will be called
* logLevelMin: Configuration / log_level_min
* iExpectedDbWriteNumber: For each log level => 1 if at least ONE EventIssue has been recorded into the DB
* logLevelMinWriteInDb: Configuration / log_level_min.write_in_db
*/
public function logProvider()
{
return [

View File

@@ -48,12 +48,7 @@ class UserRightsTest extends ItopDataTestCase
{
parent::setUp();
try {
utils::GetConfig()->SetModuleSetting('authent-local', 'password_validation.pattern', '');
self::CreateUser('admin', 1);
}
catch (CoreCannotSaveObjectException $e) {
}
utils::GetConfig()->SetModuleSetting('authent-local', 'password_validation.pattern', '');
}
public static $aClasses = [
@@ -103,6 +98,15 @@ class UserRightsTest extends ItopDataTestCase
public function testLogin($sLogin, $bResult)
{
$_SESSION = [];
if ($sLogin == 'admin') {
// Fixture data required in this case only
try {
self::CreateUser('admin', 1);
}
catch (CoreCannotSaveObjectException $e) {
// The admin account could exist, depending on where and when the test suite is executed
}
}
$this->assertEquals($bResult, UserRights::Login($sLogin));
$this->assertEquals($bResult, UserRights::IsLoggedIn());
UserRights::Logoff();
@@ -487,8 +491,7 @@ class UserRightsTest extends ItopDataTestCase
];
}
/**
* @runInSeparateProcess
*@dataProvider NonAdminCannotListAdminProfilesProvider
* @dataProvider NonAdminCannotListAdminProfilesProvider
*/
public function testNonAdminCannotListAdminProfiles($bHideAdministrators, $iExpectedCount)
{

View File

@@ -32,7 +32,7 @@ define('UNIT_MAX_CACHE_FILES', 10);
/**
* @runTestsInSeparateProcesses
* @runTestsInSeparateProcesses Required (at least) to mock the MetaModel and utils class
*/
class apcEmulationTest extends ItopTestCase
{

View File

@@ -30,9 +30,6 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
use Dict;
/**
* @runTestsInSeparateProcesses
*/
class dictApcuTest extends ItopTestCase
{
private $sEnvName;
@@ -45,9 +42,16 @@ class dictApcuTest extends ItopTestCase
$this->RequireOnceItopFile('core'.DIRECTORY_SEPARATOR.'apc-service.class.inc.php');
$this->sEnvName = time();
// This id will be used as path to the dictionary files
// It must be unique enough for the magic of Dict to operate (due to the use of require_once to load dictionaries)
$this->sEnvName = uniqid();
$_SESSION['itop_env'] = $this->sEnvName;
// Preserve the dictionary for test that will be executed later on
static::BackupStaticProperties('Dict');
// Reset and prepare the dictionary
static::SetNonPublicStaticProperty('Dict', 'm_aData', []);
$this->oApcService = $this->createMock(\ApcService::class);
Dict::SetApcService($this->oApcService);
Dict::EnableCache('toto');
@@ -57,7 +61,8 @@ class dictApcuTest extends ItopTestCase
$this->InitDictionnaries();
}
private function InitDictionnaries(){
private function InitDictionnaries()
{
clearstatcache();
$this->sDictionaryFolder = APPROOT."env-$this->sEnvName" . DIRECTORY_SEPARATOR . "dictionaries";
@mkdir($this->sDictionaryFolder, 0777, true);
@@ -82,7 +87,8 @@ STR;
clearstatcache();
}
private function InitDictionnary($sDictionaryFolder, $sLanguageCode, $sLanguageCodeInFilename, $sLabels){
private function InitDictionnary($sDictionaryFolder, $sLanguageCode, $sLanguageCodeInFilename, $sLabels)
{
$sContent = <<<PHP
<?php
//
@@ -95,7 +101,8 @@ PHP;
file_put_contents($sDictionaryFolder . DIRECTORY_SEPARATOR . "$sLanguageCodeInFilename.dict.php", $sContent);
}
private function InitBrokenDictionnary($sDictionaryFolder, $sLanguageCode, $sLanguageCodeInFilename){
private function InitBrokenDictionnary($sDictionaryFolder, $sLanguageCode, $sLanguageCodeInFilename)
{
$sContent = <<<PHP
<?php
//
@@ -114,10 +121,13 @@ PHP;
rmdir(APPROOT."env-$this->sEnvName".DIRECTORY_SEPARATOR."dictionaries");
rmdir(APPROOT."env-$this->sEnvName");
static::RestoreStaticProperties('Dict');
parent::tearDown();
}
public function InitLangIfNeeded_NoApcProvider(){
public function InitLangIfNeeded_NoApcProvider()
{
return [
'apcu mocked' => [ 'bApcuMocked' => true ],
'integration test - apcu service like in production - install php-apcu before' => [ 'bApcuMocked' => false ],
@@ -127,7 +137,8 @@ PHP;
/**
* @dataProvider InitLangIfNeeded_NoApcProvider
*/
public function testInitLangIfNeeded_NoApc($bApcuMocked){
public function testInitLangIfNeeded_NoApc($bApcuMocked)
{
if ($bApcuMocked) {
$this->oApcService->expects($this->any())
->method('function_exists')
@@ -163,7 +174,8 @@ PHP;
$this->assertEquals('not_defined_label', Dict::S('not_defined_label'));
}
public function testInitLangIfNeeded_Apc_LanguageMismatchDictionnary(){
public function testInitLangIfNeeded_Apc_LanguageMismatchDictionnary()
{
//language mismatch!!
$sLabels = <<<STR
'label1' => 'de1',
@@ -185,7 +197,8 @@ STR;
$this->assertEquals('label1', Dict::S('label1'));
}
public function testInitLangIfNeeded_Apc_BrokenUserDictionnary(){
public function testInitLangIfNeeded_Apc_BrokenUserDictionnary()
{
$this->InitBrokenDictionnary($this->sDictionaryFolder, 'DE DE', 'de-de');
$this->oApcService->expects($this->any())
@@ -205,7 +218,8 @@ STR;
$this->assertEquals('ru1', Dict::S('label1'));
}
public function testInitLangIfNeeded_Apc_BrokenDictionnary_UserAndDefault(){
public function testInitLangIfNeeded_Apc_BrokenDictionnary_UserAndDefault()
{
$this->InitBrokenDictionnary($this->sDictionaryFolder, 'DE DE', 'de-de');
$this->InitBrokenDictionnary($this->sDictionaryFolder, 'RU RU', 'ru-ru');
@@ -224,7 +238,8 @@ STR;
$this->assertEquals('en1', Dict::S('label1'));
}
public function testInitLangIfNeeded_Apc_BrokenDictionnary_ALL(){
public function testInitLangIfNeeded_Apc_BrokenDictionnary_ALL()
{
$this->InitBrokenDictionnary($this->sDictionaryFolder, 'DE DE', 'de-de');
$this->InitBrokenDictionnary($this->sDictionaryFolder, 'RU RU', 'ru-ru');
$this->InitBrokenDictionnary($this->sDictionaryFolder, 'EN US', 'en-us');
@@ -244,7 +259,8 @@ STR;
$this->assertEquals('label1', Dict::S('label1'));
}
public function testInitLangIfNeeded_ApcFromCache_PropertyInUserDictionnary(){
public function testInitLangIfNeeded_ApcFromCache_PropertyInUserDictionnary()
{
$this->oApcService->expects($this->any())
->method('function_exists')
->willReturn(true);
@@ -262,7 +278,8 @@ STR;
$this->assertEquals('fr1', Dict::S('label1'));
}
public function testInitLangIfNeeded_ApcStore_PropertyInUserDictionnary(){
public function testInitLangIfNeeded_ApcStore_PropertyInUserDictionnary()
{
$this->oApcService->expects($this->any())
->method('function_exists')
->willReturn(true);
@@ -341,7 +358,8 @@ STR;
$this->assertEquals('en2', Dict::S('label2'));
}
public function testInitLangIfNeeded_Apc_PropertyInDictDefaultLanguageDictionnary(){
public function testInitLangIfNeeded_Apc_PropertyInDictDefaultLanguageDictionnary()
{
$this->oApcService->expects($this->any())
->method('function_exists')
->willReturn(true);
@@ -362,7 +380,8 @@ STR;
$this->assertEquals('en3', Dict::S('label3'));
}
public function testInitLangIfNeeded_ApcCorrupted_PropertyInDictDefaultLanguageDictionnary(){
public function testInitLangIfNeeded_ApcCorrupted_PropertyInDictDefaultLanguageDictionnary()
{
$this->oApcService->expects($this->any())
->method('function_exists')
->willReturn(true);
@@ -380,7 +399,8 @@ STR;
$this->assertEquals('label3', Dict::S('label3'));
}
public function testInitLangIfNeeded_Apc_PropertyNotFound(){
public function testInitLangIfNeeded_Apc_PropertyNotFound()
{
$this->oApcService->expects($this->any())
->method('function_exists')
->willReturn(true);

View File

@@ -30,9 +30,6 @@ use Combodo\iTop\Test\UnitTest\ItopTestCase;
use Dict;
use Exception;
/**
* @runClassInSeparateProcess
*/
class dictTest extends ItopTestCase
{
private $sEnvName;
@@ -42,7 +39,9 @@ class dictTest extends ItopTestCase
$this->RequireOnceItopFile('core'.DIRECTORY_SEPARATOR.'apc-service.class.inc.php');
$this->sEnvName = time();
// This id will be used as path to the dictionary files
// It must be unique enough for the magic of Dict to operate (due to the use of require_once to load dictionaries)
$this->sEnvName = uniqid();
$sDictionaryFolder = APPROOT."env-$this->sEnvName".DIRECTORY_SEPARATOR."dictionaries";
@mkdir($sDictionaryFolder, 0777, true);
@@ -68,6 +67,9 @@ PHP;
file_put_contents($sDictionaryFolder.DIRECTORY_SEPARATOR."en-en.dict.php", $sContent);
$_SESSION['itop_env'] = $this->sEnvName;
// Preserve the dictionary for test that will be executed later on
static::BackupStaticProperties('Dict');
}
protected function tearDown(): void
@@ -78,6 +80,8 @@ PHP;
rmdir(APPROOT."env-$this->sEnvName".DIRECTORY_SEPARATOR."dictionaries");
rmdir(APPROOT."env-$this->sEnvName");
static::RestoreStaticProperties('Dict');
parent::tearDown();
}
@@ -93,6 +97,9 @@ PHP;
public function testInitLangIfNeeded_NoApc()
{
// Reset the dictionary
static::SetNonPublicStaticProperty('Dict', 'm_aData', []);
$oApcService = $this->createMock(\ApcService::class);
Dict::SetApcService($oApcService);
Dict::EnableCache('toto');

View File

@@ -9,7 +9,6 @@ use SubMFCompiler;
use utils;
/**
* @runClassInSeparateProcess
* @covers \MFCompiler::UseLatestPrecompiledFile
*/
class MFCompilerTest extends ItopTestCase {
@@ -57,23 +56,25 @@ class MFCompilerTest extends ItopTestCase {
self::$aFoldersToCleanup = [ $sTempTargetDir, $sExtensionTargetDir, $sDatamodel2xTargetDir ];
// Sometime in the past
$iTimeStart = time() - 100;
self::$aRessources['sPostCompilation1'] = tempnam($sTempTargetDir, $sPrefix);
sleep(1);
touch(self::$aRessources['sPostCompilation1'], $iTimeStart+=2);
//datamodel XML file in extension folder
self::$aRessources['sPrecompiledInExtensionFile1'] = tempnam($sExtensionTargetDir, $sPrefix);
touch(self::$aRessources['sPrecompiledInExtensionFile1'], $iTimeStart+=2);
self::$aRessources['sPrecompiledInExtensionFileUri1'] = "UseLatestPrecompiledFileProvider" . DIRECTORY_SEPARATOR . basename(self::$aRessources['sPrecompiledInExtensionFile1']);
//datamodel XML file in source dir /datamodels/2.x folder
self::$aRessources['sPrecompiledInDataModelXXFile1'] = tempnam($sDatamodel2xTargetDir, $sPrefix);
touch(self::$aRessources['sPrecompiledInDataModelXXFile1'], $iTimeStart+=2);
self::$aRessources['sPrecompiledInDataModelXXFileUri1'] = "UseLatestPrecompiledFileProvider" . DIRECTORY_SEPARATOR . basename(self::$aRessources['sPrecompiledInDataModelXXFile1']);
sleep(1);
//generate ressources from a previous setup: called postcompiled
self::$aRessources['sPostCompilation2'] = tempnam($sTempTargetDir, $sPrefix);
sleep(1);
touch(self::$aRessources['sPostCompilation2'], $iTimeStart+=2);
//simulate copy of /data/models.2.x or extensions ressources during setup in a temp directory
self::$aRessources['sCopiedExtensionFile1'] = $sTempTargetDir . DIRECTORY_SEPARATOR . basename(self::$aRessources['sPrecompiledInExtensionFile1']);
@@ -118,9 +119,8 @@ class MFCompilerTest extends ItopTestCase {
* @param ?string $sExpectedReturn
*/
public function testUseLatestPrecompiledFile(string $sTempTargetDir, string $sPrecompiledFileUri, string $sPostCompilationLatestPrecompiledFile, string $sThemeDir, ?string $sExpectedReturn, bool $bDisableThemePrecompilationViaConf = false){
if ($bDisableThemePrecompilationViaConf){
utils::GetConfig()->Set('theme.enable_precompilation', false);
}
// Enable or disable precompilation depending on the test case
utils::GetConfig()->Set('theme.enable_precompilation', !$bDisableThemePrecompilationViaConf);
$sRes = $this->oMFCompiler->UseLatestPrecompiledFile($sTempTargetDir, $sPrecompiledFileUri, $sPostCompilationLatestPrecompiledFile, $sThemeDir);
$this->assertEquals($sExpectedReturn, $sRes);
}

View File

@@ -63,7 +63,7 @@ class StatusIncTest extends ItopTestCase {
}
/**
* @runInSeparateProcess
* @runInSeparateProcess Required because Status constructor invokes MetaModel::Startup... which does nothing when already loaded
*/
public function testStatusStartupWrongDbPwd()
{

View File

@@ -18,14 +18,6 @@ class StatusTest extends ItopTestCase
require_once APPROOT.'core/config.class.inc.php'; // for constants
}
public function testStatusWrongUrl() {
$sPath = APPROOT.'/status_wrong.php';
exec("php $sPath", $aOutput, $iRet);
$this->assertNotEquals(0, $iRet, "Problem executing status page: $sPath, $iRet, aOutput:\n" . var_export($aOutput, true));
}
protected function GetPHPCommand()
{
$this->RequireOnceItopFile('application/utils.inc.php');
@@ -33,23 +25,14 @@ class StatusTest extends ItopTestCase
return $oConfig->Get('php_path');
}
public function testStatusGood() {
$sPath = APPROOT.'/webservices/status.php';
$sPHP = $this->GetPHPCommand();
exec("$sPHP $sPath", $aOutput, $iRet);
$this->assertEquals(0, $iRet, "Problem executing status page: $sPath, $iRet, aOutput:\n".var_export($aOutput, true));
}
/**
*
*/
public function testStatusGoodWithJson()
public function testStatusPageRepliesAsExpected()
{
$sPath = APPROOT.'/webservices/status.php';
$sPHP = $this->GetPHPCommand();
exec("$sPHP $sPath", $aOutput, $iRet);
$this->assertEquals(0, $iRet, "Problem executing status page: $sPath, $iRet, aOutput:\n".var_export($aOutput, true));
$sAdditionalInfo = "aOutput:\n".var_export($aOutput, true).'.';
//Check response

View File

@@ -8,9 +8,6 @@ use Exception;
use MetaModel;
/**
* @runTestsInSeparateProcesses
*/
class CliResetSessionTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;

View File

@@ -12,8 +12,6 @@ use utils;
* @group itopRequestMgmt
* @group restApi
* @group defaultProfiles
*
* @runClassInSeparateProcess
*/
class RestTest extends ItopDataTestCase
{