mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-25 11:38:44 +02:00
N°5608 - Move unit tests to a dedicated folder and start reorganizing to match iTop folder structure
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 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
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
|
||||
/**
|
||||
* @covers utils
|
||||
*/
|
||||
class DashboardLayoutTest extends ItopTestCase
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetDashletCoordinatesProvider()
|
||||
{
|
||||
return array(
|
||||
'OneColLayout-Cell0' => array('DashboardLayoutOneCol', 0, array(0, 0)),
|
||||
'OneColLayout-Cell1' => array('DashboardLayoutOneCol', 1, array(0, 1)),
|
||||
'TwoColsLayout-Cell0' => array('DashboardLayoutTwoCols', 0, array(0, 0)),
|
||||
'TwoColsLayout-Cell1' => array('DashboardLayoutTwoCols', 1, array(1, 0)),
|
||||
'TwoColsLayout-Cell2' => array('DashboardLayoutTwoCols', 2, array(0, 1)),
|
||||
'TwoColsLayout-Cell3' => array('DashboardLayoutTwoCols', 3, array(1, 1)),
|
||||
'ThreeColsLayout-Cell0' => array('DashboardLayoutThreeCols', 0, array(0, 0)),
|
||||
'ThreeColsLayout-Cell1' => array('DashboardLayoutThreeCols', 1, array(1, 0)),
|
||||
'ThreeColsLayout-Cell2' => array('DashboardLayoutThreeCols', 2, array(2, 0)),
|
||||
'ThreeColsLayout-Cell3' => array('DashboardLayoutThreeCols', 3, array(0, 1)),
|
||||
'ThreeColsLayout-Cell4' => array('DashboardLayoutThreeCols', 4, array(1, 1)),
|
||||
'ThreeColsLayout-Cell5' => array('DashboardLayoutThreeCols', 5, array(2, 1)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDashboardLayoutClass
|
||||
* @param int $iCellIdx
|
||||
* @param array $aExpectedCoordinates
|
||||
* @dataProvider GetDashletCoordinatesProvider
|
||||
* @since N°2735
|
||||
*/
|
||||
public function testGetDashletCoordinates($sDashboardLayoutClass, $iCellIdx, $aExpectedCoordinates)
|
||||
{
|
||||
$oDashboardLayout = new $sDashboardLayoutClass();
|
||||
$aDashletCoordinates = $oDashboardLayout->GetDashletCoordinates($iCellIdx);
|
||||
|
||||
$this->assertEquals($aExpectedCoordinates,$aDashletCoordinates);
|
||||
}
|
||||
}
|
||||
499
test/php-unit-tests/tests/application/UtilsTest.php
Normal file
499
test/php-unit-tests/tests/application/UtilsTest.php
Normal file
@@ -0,0 +1,499 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2018 Dennis Lassiter
|
||||
*
|
||||
* 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/>
|
||||
*
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
|
||||
/**
|
||||
* @covers utils
|
||||
*/
|
||||
class UtilsTest extends ItopTestCase
|
||||
{
|
||||
public function testEndsWith()
|
||||
{
|
||||
$this->assertFalse(utils::EndsWith('a', 'bbbb'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider memoryLimitDataProvider
|
||||
*/
|
||||
public function testIsMemoryLimit($expected, $memoryLimit, $requiredMemory)
|
||||
{
|
||||
$this->assertSame($expected, utils::IsMemoryLimitOk($memoryLimit, $requiredMemory));
|
||||
}
|
||||
|
||||
/**
|
||||
* DataProvider for testIsMemoryLimitOk
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function memoryLimitDataProvider()
|
||||
{
|
||||
return [
|
||||
'current -1, required 1024' => [true, -1, 1024],
|
||||
'current 1024, required 1024' => [true, 1024, 1024],
|
||||
'current 2048, required 1024' => [true, 2048, 1024],
|
||||
'current 1024, required 2048' => [false, 1024, 2048],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider realPathDataProvider
|
||||
* @covers utils::RealPath()
|
||||
*/
|
||||
public function testRealPath($sPath, $sBasePath, $expected)
|
||||
{
|
||||
$this->assertSame($expected, utils::RealPath($sPath, $sBasePath), "utils::RealPath($sPath, $sBasePath) does not match $expected");
|
||||
}
|
||||
|
||||
public function realPathDataProvider()
|
||||
{
|
||||
parent::setUp(); // if not called, APPROOT won't be defined :(
|
||||
|
||||
$sSep = DIRECTORY_SEPARATOR;
|
||||
$sItopRootRealPath = realpath(APPROOT).$sSep;
|
||||
$sLicenseFileName = 'license.txt';
|
||||
if (!is_file(APPROOT.$sLicenseFileName))
|
||||
{
|
||||
$sLicenseFileName = 'LICENSE';
|
||||
}
|
||||
|
||||
return [
|
||||
$sLicenseFileName => [APPROOT.$sLicenseFileName, APPROOT, $sItopRootRealPath.$sLicenseFileName],
|
||||
'unexisting file' => [APPROOT.'license_DOES_NOT_EXIST.txt', APPROOT, false],
|
||||
'/'.$sLicenseFileName => [APPROOT.$sSep.$sLicenseFileName, APPROOT, $sItopRootRealPath.$sLicenseFileName],
|
||||
'%2f'.$sLicenseFileName => [APPROOT.'%2f'. $sLicenseFileName, APPROOT, false],
|
||||
'../'.$sLicenseFileName => [APPROOT.'..'.$sSep.$sLicenseFileName, APPROOT, false],
|
||||
'%2e%2e%2f'.$sLicenseFileName => [APPROOT.'%2e%2e%2f'.$sLicenseFileName, APPROOT, false],
|
||||
'application/utils.inc.php with basepath=APPROOT' => [
|
||||
APPROOT.'application/utils.inc.php',
|
||||
APPROOT,
|
||||
$sItopRootRealPath.'application'.$sSep.'utils.inc.php',
|
||||
],
|
||||
'application/utils.inc.php with basepath=APPROOT/application' => [
|
||||
APPROOT.'application/utils.inc.php',
|
||||
APPROOT.'application',
|
||||
$sItopRootRealPath.'application'.$sSep.'utils.inc.php',
|
||||
],
|
||||
'basepath containing / and \\' => [
|
||||
APPROOT.'sources/form/form.class.inc.php',
|
||||
APPROOT.'sources/form\\form.class.inc.php',
|
||||
$sItopRootRealPath.'sources'.$sSep.'form'.$sSep.'form.class.inc.php',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider LocalPathProvider
|
||||
*
|
||||
* @param $sAbsolutePath
|
||||
* @param $expected
|
||||
*/
|
||||
public function testLocalPath($sAbsolutePath, $expected)
|
||||
{
|
||||
$this->assertSame($expected, utils::LocalPath($sAbsolutePath));
|
||||
|
||||
}
|
||||
|
||||
public function LocalPathProvider()
|
||||
{
|
||||
return array(
|
||||
'index.php' => array(
|
||||
'sAbsolutePath' => APPROOT.'index.php',
|
||||
'expected' => 'index.php',
|
||||
),
|
||||
'non existing' => array(
|
||||
'sAbsolutePath' => APPROOT.'nonexisting/nonexisting',
|
||||
'expected' => false,
|
||||
),
|
||||
'outside' => array(
|
||||
'sAbsolutePath' => '/tmp',
|
||||
'expected' => false,
|
||||
),
|
||||
'application/cmdbabstract.class.inc.php' => array(
|
||||
'sAbsolutePath' => APPROOT.'application/cmdbabstract.class.inc.php',
|
||||
'expected' => 'application/cmdbabstract.class.inc.php',
|
||||
),
|
||||
'dir' => array(
|
||||
'sAbsolutePath' => APPROOT.'application/.',
|
||||
'expected' => 'application',
|
||||
),
|
||||
'root' => array(
|
||||
'sAbsolutePath' => APPROOT.'.',
|
||||
'expected' => '',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider appRootUrlProvider
|
||||
* @covers utils::GetAppRootUrl
|
||||
*/
|
||||
public function testGetAppRootUrl($sReturnValue, $sCurrentScript, $sAppRoot, $sAbsoluteUrl)
|
||||
{
|
||||
$this->assertEquals($sReturnValue, utils::GetAppRootUrl($sCurrentScript, $sAppRoot, $sAbsoluteUrl));
|
||||
}
|
||||
|
||||
public function appRootUrlProvider()
|
||||
{
|
||||
return array(
|
||||
'Setup index (windows antislash)' => array('http://localhost/', 'C:\Dev\wamp64\www\itop-dev\setup\index.php', 'C:\Dev\wamp64\www\itop-dev', 'http://localhost/setup/'),
|
||||
'Setup index (windows slash)' => array('http://127.0.0.1/', 'C:/web/setup/index.php', 'C:/web', 'http://127.0.0.1/setup/'),
|
||||
'Setup index (windows slash, drive letter case difference)' => array('http://127.0.0.1/', 'c:/web/setup/index.php', 'C:/web', 'http://127.0.0.1/setup/'),
|
||||
);
|
||||
}
|
||||
|
||||
public function GetAbsoluteUrlAppRootPersistency() {
|
||||
$this->setUp();
|
||||
|
||||
return [
|
||||
'ForceTrustProxy 111' => [
|
||||
'bBehindReverseProxy' => false,
|
||||
'bForceTrustProxy1' => true,
|
||||
'sExpectedAppRootUrl1' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy2' => true,
|
||||
'sExpectedAppRootUrl2' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy3' => true,
|
||||
'sExpectedAppRootUrl3' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'ForceTrustProxy 101' => [
|
||||
'bBehindReverseProxy' => false,
|
||||
'bForceTrustProxy1' => true,
|
||||
'sExpectedAppRootUrl1' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy2' => false,
|
||||
'sExpectedAppRootUrl2' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy3' => true,
|
||||
'sExpectedAppRootUrl3' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'ForceTrustProxy 011' => [
|
||||
'bBehindReverseProxy' => false,
|
||||
'bForceTrustProxy1' => false,
|
||||
'sExpectedAppRootUrl1' => 'http://example.com/',
|
||||
'bForceTrustProxy2' => true,
|
||||
'sExpectedAppRootUrl2' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy3' => true,
|
||||
'sExpectedAppRootUrl3' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'ForceTrustProxy 110' => [
|
||||
'bBehindReverseProxy' => false,
|
||||
'bForceTrustProxy1' => true,
|
||||
'sExpectedAppRootUrl1' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy2' => true,
|
||||
'sExpectedAppRootUrl2' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy3' => false,
|
||||
'sExpectedAppRootUrl3' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'ForceTrustProxy 010' => [
|
||||
'bBehindReverseProxy' => false,
|
||||
'bForceTrustProxy1' => false,
|
||||
'sExpectedAppRootUrl1' => 'http://example.com/',
|
||||
'bForceTrustProxy2' => true,
|
||||
'sExpectedAppRootUrl2' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy3' => false,
|
||||
'sExpectedAppRootUrl3' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'ForceTrustProxy 001' => [
|
||||
'bBehindReverseProxy' => false,
|
||||
'bForceTrustProxy1' => false,
|
||||
'sExpectedAppRootUrl1' => 'http://example.com/',
|
||||
'bForceTrustProxy2' => false,
|
||||
'sExpectedAppRootUrl2' => 'http://example.com/',
|
||||
'bForceTrustProxy3' => true,
|
||||
'sExpectedAppRootUrl3' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'ForceTrustProxy 000' => [
|
||||
'bBehindReverseProxy' => false,
|
||||
'bForceTrustProxy1' => false,
|
||||
'sExpectedAppRootUrl1' => 'http://example.com/',
|
||||
'bForceTrustProxy2' => false,
|
||||
'sExpectedAppRootUrl2' => 'http://example.com/',
|
||||
'bForceTrustProxy3' => false,
|
||||
'sExpectedAppRootUrl3' => 'http://example.com/',
|
||||
],
|
||||
'BehindReverseProxy ForceTrustProxy 010' => [
|
||||
'bBehindReverseProxy' => true,
|
||||
'bForceTrustProxy1' => false,
|
||||
'sExpectedAppRootUrl1' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy2' => true,
|
||||
'sExpectedAppRootUrl2' => 'https://proxy.com:4443/',
|
||||
'bForceTrustProxy3' => false,
|
||||
'sExpectedAppRootUrl3' => 'https://proxy.com:4443/',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
* @dataProvider GetAbsoluteUrlAppRootPersistency
|
||||
*/
|
||||
public function testGetAbsoluteUrlAppRootPersistency($bBehindReverseProxy,$bForceTrustProxy1 ,$sExpectedAppRootUrl1,$bForceTrustProxy2 , $sExpectedAppRootUrl2,$bForceTrustProxy3 , $sExpectedAppRootUrl3)
|
||||
{
|
||||
utils::GetConfig()->Set('behind_reverse_proxy', $bBehindReverseProxy);
|
||||
utils::GetConfig()->Set('app_root_url', '');
|
||||
|
||||
//should match http://example.com/ when not trusting the proxy
|
||||
//should match https://proxy.com:4443/ when trusting the proxy
|
||||
$_SERVER = [
|
||||
'REMOTE_ADDR' => '127.0.0.1', //is not set, disable IsProxyTrusted
|
||||
'SERVER_NAME' => 'example.com',
|
||||
'SERVER_PORT' => '80',
|
||||
'REQUEST_URI' => '/index.php?baz=1',
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
'SCRIPT_FILENAME' => APPROOT.'index.php',
|
||||
'QUERY_STRING' => 'baz=1',
|
||||
'HTTP_X_FORWARDED_HOST' => 'proxy.com',
|
||||
'HTTP_X_FORWARDED_PORT' => '4443',
|
||||
'HTTP_X_FORWARDED_PROTO' => 'https',
|
||||
'HTTPS' => null,
|
||||
];
|
||||
|
||||
$this->assertEquals($sExpectedAppRootUrl1, utils::GetAbsoluteUrlAppRoot($bForceTrustProxy1));
|
||||
|
||||
$this->assertEquals($sExpectedAppRootUrl2, utils::GetAbsoluteUrlAppRoot($bForceTrustProxy2));
|
||||
|
||||
$this->assertEquals($sExpectedAppRootUrl3, utils::GetAbsoluteUrlAppRoot($bForceTrustProxy3));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dataProvider GetDefaultUrlAppRootProvider
|
||||
*/
|
||||
public function testGetDefaultUrlAppRoot($bForceTrustProxy, $bConfTrustProxy, $aServerVars, $sExpectedAppRootUrl)
|
||||
{
|
||||
$_SERVER = $aServerVars;
|
||||
utils::GetConfig()->Set('behind_reverse_proxy', $bConfTrustProxy);
|
||||
$sAppRootUrl = utils::GetDefaultUrlAppRoot($bForceTrustProxy);
|
||||
$this->assertEquals($sExpectedAppRootUrl, $sAppRootUrl);
|
||||
}
|
||||
|
||||
public function GetDefaultUrlAppRootProvider()
|
||||
{
|
||||
$this->setUp();
|
||||
|
||||
$baseServerVar = [
|
||||
'REMOTE_ADDR' => '127.0.0.1', //is not set, disable IsProxyTrusted
|
||||
'SERVER_NAME' => 'example.com',
|
||||
'HTTP_X_FORWARDED_HOST' => null,
|
||||
'SERVER_PORT' => '80',
|
||||
'HTTP_X_FORWARDED_PORT' => null,
|
||||
'REQUEST_URI' => '/index.php?baz=1',
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
'SCRIPT_FILENAME' => APPROOT.'index.php',
|
||||
'QUERY_STRING' => 'baz=1',
|
||||
'HTTP_X_FORWARDED_PROTO' => null,
|
||||
'HTTP_X_FORWARDED_PROTOCOL' => null,
|
||||
'HTTPS' => null,
|
||||
];
|
||||
|
||||
return [
|
||||
'no proxy, http' => [
|
||||
'bForceTrustProxy' => false,
|
||||
'bConfTrustProxy' => false,
|
||||
'aServerVars' => array_merge($baseServerVar, []),
|
||||
'sExpectedAppRootUrl' => 'http://example.com/',
|
||||
],
|
||||
'no proxy, subPath, http' => [
|
||||
'bForceTrustProxy' => false,
|
||||
'bConfTrustProxy' => false,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'REQUEST_URI' => '/foo/index.php?baz=1',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'http://example.com/foo/',
|
||||
],
|
||||
'IIS lack REQUEST_URI' => [
|
||||
'bForceTrustProxy' => false,
|
||||
'bConfTrustProxy' => false,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'REQUEST_URI' => null,
|
||||
'SCRIPT_NAME' => '/foo/index.php',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'http://example.com/foo/',
|
||||
],
|
||||
'no proxy, https' => [
|
||||
'bForceTrustProxy' => false,
|
||||
'bConfTrustProxy' => false,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'SERVER_PORT' => '443',
|
||||
'HTTPS' => 'on',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'https://example.com/',
|
||||
],
|
||||
'no proxy, https on 4443' => [
|
||||
'bForceTrustProxy' => false,
|
||||
'bConfTrustProxy' => false,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'SERVER_PORT' => '4443',
|
||||
'HTTPS' => 'on',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'https://example.com:4443/',
|
||||
],
|
||||
'with proxy, not enabled' => [
|
||||
'bForceTrustProxy' => false,
|
||||
'bConfTrustProxy' => false,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'HTTP_X_FORWARDED_HOST' => 'proxy.com',
|
||||
'HTTP_X_FORWARDED_PORT' => '4443',
|
||||
'HTTP_X_FORWARDED_PROTO' => 'https',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'http://example.com/',
|
||||
],
|
||||
'with proxy, enabled HTTP_X_FORWARDED_PROTO' => [
|
||||
'bForceTrustProxy' => false,
|
||||
'bConfTrustProxy' => true,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'HTTP_X_FORWARDED_HOST' => 'proxy.com',
|
||||
'HTTP_X_FORWARDED_PORT' => '4443',
|
||||
'HTTP_X_FORWARDED_PROTO' => 'https',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'with proxy, enabled - alt HTTP_X_FORWARDED_PROTO COL' => [
|
||||
'bForceTrustProxy' => false,
|
||||
'bConfTrustProxy' => true,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'HTTP_X_FORWARDED_HOST' => 'proxy.com',
|
||||
'HTTP_X_FORWARDED_PORT' => '4443',
|
||||
'HTTP_X_FORWARDED_PROTOCOL' => 'https',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'with proxy, disabled, forced' => [
|
||||
'bForceTrustProxy' => true,
|
||||
'bConfTrustProxy' => false,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'HTTP_X_FORWARDED_HOST' => 'proxy.com',
|
||||
'HTTP_X_FORWARDED_PORT' => '4443',
|
||||
'HTTP_X_FORWARDED_PROTO' => 'https',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'with proxy, enabled, forced' => [
|
||||
'bForceTrustProxy' => true,
|
||||
'bConfTrustProxy' => true,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'HTTP_X_FORWARDED_HOST' => 'proxy.com',
|
||||
'HTTP_X_FORWARDED_PORT' => '4443',
|
||||
'HTTP_X_FORWARDED_PROTO' => 'https',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'https://proxy.com:4443/',
|
||||
],
|
||||
|
||||
'with proxy, disabled, forced, no remote addr' => [
|
||||
'bForceTrustProxy' => true,
|
||||
'bConfTrustProxy' => false,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'REMOTE_ADDR' => null,
|
||||
'HTTP_X_FORWARDED_HOST' => 'proxy.com',
|
||||
'HTTP_X_FORWARDED_PORT' => '4443',
|
||||
'HTTP_X_FORWARDED_PROTO' => 'https',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'https://proxy.com:4443/',
|
||||
],
|
||||
'with proxy, enabled, no remote addr' => [
|
||||
'bForceTrustProxy' => false,
|
||||
'bConfTrustProxy' => true,
|
||||
'aServerVars' => array_merge($baseServerVar, [
|
||||
'REMOTE_ADDR' => null,
|
||||
'HTTP_X_FORWARDED_HOST' => 'proxy.com',
|
||||
'HTTP_X_FORWARDED_PORT' => '4443',
|
||||
'HTTP_X_FORWARDED_PROTO' => 'https',
|
||||
]),
|
||||
'sExpectedAppRootUrl' => 'http://example.com/',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sExpressionToConvert
|
||||
* @param int $iExpectedConvertedValue
|
||||
*
|
||||
* @dataProvider ConvertToBytesProvider
|
||||
*/
|
||||
public function testConvertToBytes($sExpressionToConvert, $iExpectedConvertedValue)
|
||||
{
|
||||
$iCurrentConvertedValue = utils::ConvertToBytes($sExpressionToConvert);
|
||||
self::assertEquals($iExpectedConvertedValue, $iCurrentConvertedValue, 'Converted value wasn\'t the one expected !');
|
||||
self::assertSame($iExpectedConvertedValue, $iCurrentConvertedValue, 'Value was converted but not of the expected type');
|
||||
}
|
||||
|
||||
public function ConvertToBytesProvider()
|
||||
{
|
||||
return [
|
||||
'123 int value' => ['123', 123],
|
||||
'-1 no limit' => ['-1', -1],
|
||||
'56k' => ['56k', 56 * 1024],
|
||||
'512M' => ['512M', 512 * 1024 * 1024],
|
||||
'2G' => ['2G', 2 * 1024 * 1024 * 1024],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sanitizer.
|
||||
*
|
||||
* @param $type string type of sanitizer
|
||||
* @param $valueToSanitize ? value to sanitize
|
||||
* @param $expectedResult ? expected result
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider sanitizerDataProvider
|
||||
*/
|
||||
public function testSanitizer($type, $valueToSanitize, $expectedResult)
|
||||
{
|
||||
$this->assertEquals($expectedResult, utils::Sanitize($valueToSanitize, null, $type), 'url sanitize failed');
|
||||
}
|
||||
|
||||
/**
|
||||
* DataProvider for testSanitizer
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sanitizerDataProvider()
|
||||
{
|
||||
return [
|
||||
'good integer' => ['integer', '2565', '2565'],
|
||||
'bad integer' => ['integer', 'a2656', '2656'],
|
||||
/**
|
||||
* 'class' filter needs a loaded datamodel... and is only an indirection to \MetaModel::IsValidClass so might very important to test !
|
||||
* If we switch this class to ItopDataTestCase then we are seeing :
|
||||
* - the class now takes 18s to process instead of... 459ms when using ItopTestCase !!!
|
||||
* - multiple errors are thrown in testGetAbsoluteUrlAppRootPersistency :(
|
||||
* We decided it wasn't worse the effort to test the 'class' filter !
|
||||
*/
|
||||
// 'good class' => ['class', 'UserRequest', 'UserRequest'],
|
||||
// 'bad class' => ['class', 'MyUserRequest',null],
|
||||
'good string' => ['string', 'Is Peter smart and funny?', 'Is Peter smart and funny?'],
|
||||
'bad string' => ['string', 'Is Peter <smart> & funny?', 'Is Peter <smart> & funny?'],
|
||||
'good transaction_id' => ['transaction_id', '8965.-dd', '8965.-dd'],
|
||||
'bad transaction_id' => ['transaction_id', '8965.-dd+', null],
|
||||
'good parameter' => ['parameter', 'JU8965-dd=_', 'JU8965-dd=_'],
|
||||
'bad parameter' => ['parameter', '8965.-dd+', null],
|
||||
'good field_name' => ['field_name', 'Name->bUzz38', 'Name->bUzz38'],
|
||||
'bad field_name' => ['field_name', 'name-buzz', null],
|
||||
'good context_param' => ['context_param', '%dssD25_=%:+-', '%dssD25_=%:+-'],
|
||||
'bad context_param' => ['context_param', '%dssD,25_=%:+-', null],
|
||||
'good element_identifier' => ['element_identifier', 'AD05nb', 'AD05nb'],
|
||||
'bad element_identifier' => ['element_identifier', 'AD05nb+', 'AD05nb'],
|
||||
'good url' => ['url', 'https://www.w3schools.com', 'https://www.w3schools.com'],
|
||||
'bad url' => ['url', 'https://www.w3schoo<6F><6F>ls.co<63>m', 'https://www.w3schools.com'],
|
||||
'raw_data' => ['raw_data', '<Test>\s😃😃😃', '<Test>\s😃😃😃'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
use Combodo\iTop\Composer\iTopComposer;
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
|
||||
/**
|
||||
* Copyright (C) 2010-2020 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/>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
class iTopComposerTest extends ItopTestCase
|
||||
{
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
clearstatcache();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider IsTestDirProvider
|
||||
* @return void
|
||||
*/
|
||||
public function testIsTestDir($sDirName, $bIsTest)
|
||||
{
|
||||
$isTestDir = iTopComposer::IsTestDir($sDirName);
|
||||
$this->assertIsInt($isTestDir);
|
||||
if (true === $bIsTest) {
|
||||
$this->assertTrue(($isTestDir > 0));
|
||||
} else {
|
||||
$this->assertSame(0, $isTestDir);
|
||||
}
|
||||
}
|
||||
|
||||
public function IsTestDirProvider()
|
||||
{
|
||||
return [
|
||||
'test' => ['test', true],
|
||||
'Test' => ['Test', true],
|
||||
'tests' => ['tests', true],
|
||||
'Tests' => ['Tests', true],
|
||||
'testaa' => ['testaa', false],
|
||||
'Testaa' => ['Testaa', false],
|
||||
'testsaa' => ['testsaa', false],
|
||||
'Testsaa' => ['Testsaa', false],
|
||||
];
|
||||
}
|
||||
|
||||
public function testListAllTestDir()
|
||||
{
|
||||
$oiTopComposer = new iTopComposer();
|
||||
$aDirs = $oiTopComposer->ListAllTestDir();
|
||||
|
||||
$this->assertTrue(is_array($aDirs));
|
||||
|
||||
foreach ($aDirs as $sDir) {
|
||||
$sDirName = basename($sDir);
|
||||
$this->assertRegExp(iTopComposer::TEST_DIR_REGEXP, $sDirName, "Directory not matching test dir : $sDir");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function testListDeniedTestDir()
|
||||
{
|
||||
$oiTopComposer = new iTopComposer();
|
||||
$aDirs = $oiTopComposer->ListDeniedTestDir();
|
||||
|
||||
$this->assertTrue(is_array($aDirs));
|
||||
|
||||
$aDeniedDirWrongFormat = [];
|
||||
foreach ($aDirs as $sDir)
|
||||
{
|
||||
if (false === iTopComposer::IsTestDir($sDir)) {
|
||||
$aDeniedDirWrongFormat[] = $sDir;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertEmpty($aDeniedDirWrongFormat,
|
||||
'There are elements in \Combodo\iTop\Composer\iTopComposer::ListDeniedTestDir that are not test dirs :'.var_export($aDeniedDirWrongFormat, true));
|
||||
}
|
||||
|
||||
public function testListAllowedTestDir()
|
||||
{
|
||||
$oiTopComposer = new iTopComposer();
|
||||
$aDirs = $oiTopComposer->ListAllowedTestDir();
|
||||
|
||||
$this->assertTrue(is_array($aDirs));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is NOT a unit test, this test the iTop instance running the test ...
|
||||
*/
|
||||
public function testNoDeniedDirIsPresentForNow()
|
||||
{
|
||||
$oiTopComposer = new iTopComposer();
|
||||
|
||||
$aDeniedButStillPresent = $oiTopComposer->ListDeniedButStillPresent();
|
||||
|
||||
$this->assertEmpty(
|
||||
$aDeniedButStillPresent,
|
||||
'The iTop instance running this test must not contain any denied test directory, found: '.var_export($aDeniedButStillPresent, true)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is NOT a unit test, this test the iTop instance running the test ...
|
||||
*/
|
||||
public function testAllDirCovered()
|
||||
{
|
||||
$oiTopComposer = new iTopComposer();
|
||||
$aAllowedAndDeniedDirs = array_merge(
|
||||
$oiTopComposer->ListAllowedTestDir(),
|
||||
$oiTopComposer->ListDeniedTestDir()
|
||||
);
|
||||
|
||||
$aExistingDirs = $oiTopComposer->ListAllTestDir();
|
||||
|
||||
$aMissing = array_diff($aExistingDirs, $aAllowedAndDeniedDirs);
|
||||
$aExtra = array_diff($aAllowedAndDeniedDirs, $aExistingDirs);
|
||||
|
||||
$this->assertEmpty(
|
||||
$aMissing,
|
||||
'Test dirs exists in /lib !'."\n"
|
||||
.' They must be declared either in the allowed or denied list in '.iTopComposer::class." (see N°2651).\n"
|
||||
.' List of dirs:'."\n".var_export($aMissing, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 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
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
* @covers utils
|
||||
*/
|
||||
class privUITransactionFileTest extends ItopDataTestCase
|
||||
{
|
||||
/** @var int ID of the "support agent" pofile in the sample data */
|
||||
const SAMPLE_DATA_SUPPORT_PROFILE_ID = 5;
|
||||
const USER1_TEST_LOGIN = 'user1_support_test_privUITransaction';
|
||||
const USER2_TEST_LOGIN = 'user2_support_test_privUITransaction';
|
||||
|
||||
/**
|
||||
* @dataProvider cleanupOldTransactionsProvider
|
||||
*/
|
||||
public function testCleanupOldTransactions($iCleanableCreated, $iPreservableCreated, $sCleanablePrefix, $sPreservablePrefix)
|
||||
{
|
||||
MetaModel::GetConfig()->Set('transactions_gc_threshold', 100);
|
||||
|
||||
$iBaseLimit = time() - 24*3600; //24h
|
||||
|
||||
$sBaseDir = sys_get_temp_dir();
|
||||
$sDir = "$sBaseDir/privUITransactionFileTest/cleanupOldTransactions";
|
||||
if (is_dir($sDir)) {
|
||||
$this->rm($sDir);
|
||||
}
|
||||
mkdir("$sDir", 0777, true);
|
||||
|
||||
for ($i = 0; $i < $iCleanableCreated; $i++) {
|
||||
touch("$sDir/{$sCleanablePrefix}$i", $iBaseLimit - 10*60);
|
||||
}
|
||||
for ($i = 0; $i < $iPreservableCreated; $i++) {
|
||||
touch("$sDir/{$sPreservablePrefix}$i", $iBaseLimit + 10*60);
|
||||
}
|
||||
|
||||
$iCleanableCount = count(glob("$sDir/{$sCleanablePrefix}*"));
|
||||
$iPreservableCount = count(glob("$sDir/{$sPreservablePrefix}*"));
|
||||
$this->assertEquals($iCleanableCreated, $iCleanableCount);
|
||||
$this->assertEquals($iPreservableCreated, $iPreservableCount);
|
||||
|
||||
$aArgs = [
|
||||
'sTransactionDir' => "$sDir",
|
||||
];
|
||||
$oprivUITransactionFile = new privUITransactionFile();
|
||||
$this->InvokeNonPublicMethod(get_class($oprivUITransactionFile), 'CleanupOldTransactions', $oprivUITransactionFile, $aArgs);
|
||||
|
||||
$iCleanableCount = count(glob("$sDir/{$sCleanablePrefix}*"));
|
||||
$iPreservableCount = count(glob("$sDir/{$sPreservablePrefix}*"));
|
||||
$this->assertEquals(0, $iCleanableCount);
|
||||
$this->assertEquals($iPreservableCreated, $iPreservableCount);
|
||||
}
|
||||
|
||||
public function cleanupOldTransactionsProvider()
|
||||
{
|
||||
$iBaseLimit = time() - 60 * 10; //ten minutes ago
|
||||
|
||||
$sBaseDir = sys_get_temp_dir();
|
||||
$sDir = "$sBaseDir/privUITransactionFileTest/cleanupOldTransactions";
|
||||
|
||||
return [
|
||||
'linux - no content' => [
|
||||
'iCleanableCreated' => 0,
|
||||
'iPreservableCreated' => 0,
|
||||
'sCleanablePrefix' => 'cleanable-',
|
||||
'sPreservablePrefix' => 'preservable-',
|
||||
],
|
||||
'linux - cleanable content' => [
|
||||
'iCleanableCreated' => 2,
|
||||
'iPreservableCreated' => 0,
|
||||
'sCleanablePrefix' => 'cleanable-',
|
||||
'sPreservablePrefix' => 'preservable-',
|
||||
],
|
||||
'linux - preseved content' => [
|
||||
'iCleanableCreated' => 0,
|
||||
'iPreservableCreated' => 2,
|
||||
'sCleanablePrefix' => 'cleanable-',
|
||||
'sPreservablePrefix' => 'preservable-',
|
||||
],
|
||||
'win - no content' => [
|
||||
'iCleanableCreated' => 0,
|
||||
'iPreservableCreated' => 0,
|
||||
'sCleanablePrefix' => 'cle',
|
||||
'sPreservablePrefix' => 'pre',
|
||||
],
|
||||
'win - cleanable content' => [
|
||||
'iCleanableCreated' => 2,
|
||||
'iPreservableCreated' => 0,
|
||||
'sCleanablePrefix' => 'cle',
|
||||
'sPreservablePrefix' => 'pre',
|
||||
],
|
||||
'win - preseved content' => [
|
||||
'iCleanableCreated' => 0,
|
||||
'iPreservableCreated' => 2,
|
||||
'sCleanablePrefix' => 'cle',
|
||||
'sPreservablePrefix' => 'pre',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function rm($sDir) {
|
||||
$aFiles = array_diff(scandir($sDir), ['.','..']);
|
||||
foreach ($aFiles as $sFile) {
|
||||
if ((is_dir("$sDir/$sFile"))) {
|
||||
$this->rm("$sDir/$sFile");
|
||||
} else {
|
||||
unlink("$sDir/$sFile");
|
||||
}
|
||||
}
|
||||
return rmdir($sDir);
|
||||
}
|
||||
|
||||
const USER_TEST_LOGIN = 'support_test_privUITransaction';
|
||||
|
||||
/**
|
||||
* @throws \SecurityException
|
||||
* @uses self::SAMPLE_DATA_SUPPORT_PROFILE_ID
|
||||
* @uses self::USER1_TEST_LOGIN
|
||||
* @uses self::USER2_TEST_LOGIN
|
||||
*/
|
||||
public function testIsTransactionValid()
|
||||
{
|
||||
$this->CreateUser(static::USER1_TEST_LOGIN, self::SAMPLE_DATA_SUPPORT_PROFILE_ID);
|
||||
$this->CreateUser(static::USER2_TEST_LOGIN, self::SAMPLE_DATA_SUPPORT_PROFILE_ID);
|
||||
|
||||
// create token in the user1 context
|
||||
$bUser1Login1 = UserRights::Login(self::USER1_TEST_LOGIN);
|
||||
$this->assertTrue($bUser1Login1, 'Login with user1 throw an error');
|
||||
$sTransactionIdUserSupport = privUITransactionFile::GetNewTransactionId();
|
||||
$bResult = privUITransactionFile::IsTransactionValid($sTransactionIdUserSupport, false);
|
||||
$this->assertTrue($bResult, 'Token created by support user must be valid in the support user context');
|
||||
|
||||
// test token in the user2 context
|
||||
$bUser2Login = UserRights::Login(self::USER2_TEST_LOGIN);
|
||||
$this->assertTrue($bUser2Login, 'Login with user2 throw an error');
|
||||
$bResult = privUITransactionFile::IsTransactionValid($sTransactionIdUserSupport, false);
|
||||
$this->assertFalse($bResult, 'Token created by support user must be invalid in the admin user context');
|
||||
$bResult = privUITransactionFile::RemoveTransaction($sTransactionIdUserSupport);
|
||||
$this->assertFalse($bResult, 'Token created by support user cannot be removed in the admin user context');
|
||||
|
||||
// test other methods in the user1 context
|
||||
$bUser1Login2 = UserRights::Login(self::USER1_TEST_LOGIN);
|
||||
$this->assertTrue($bUser1Login2, 'Login with user1 throw an error');
|
||||
$bResult = privUITransactionFile::RemoveTransaction($sTransactionIdUserSupport);
|
||||
$this->assertTrue($bResult, 'Token created by support user must be removed in the support user context');
|
||||
|
||||
// test when no user logged (combodo-unauthenticated-form module for example)
|
||||
UserRights::_ResetSessionCache();
|
||||
$sTransactionIdUnauthenticatedUser = privUITransactionFile::GetNewTransactionId();
|
||||
$bResult = privUITransactionFile::IsTransactionValid($sTransactionIdUnauthenticatedUser, false);
|
||||
$this->assertTrue($bResult, 'Token created by unauthenticated user must be valid when no user logged');
|
||||
$bResult = privUITransactionFile::RemoveTransaction($sTransactionIdUnauthenticatedUser);
|
||||
$this->assertTrue($bResult, 'Token created by unauthenticated user must be removed when no user logged');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,729 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2018 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/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Eric
|
||||
* Date: 08/03/2018
|
||||
* Time: 16:46
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application\Search;
|
||||
|
||||
use AttributeDate;
|
||||
use AttributeDateTime;
|
||||
use AttributeDefinition;
|
||||
use Combodo\iTop\Application\Search\CriterionConversion\CriterionToOQL;
|
||||
use Combodo\iTop\Application\Search\CriterionConversion\CriterionToSearchForm;
|
||||
use Combodo\iTop\Application\Search\CriterionParser;
|
||||
use Combodo\iTop\Application\Search\SearchForm;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use DBObjectSearch;
|
||||
use DBObjectSet;
|
||||
use DBSearch;
|
||||
use Dict;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class CriterionConversionTest extends ItopDataTestCase
|
||||
{
|
||||
const CREATE_TEST_ORG = true;
|
||||
|
||||
/**
|
||||
* @dataProvider ToOqlProvider
|
||||
*
|
||||
* @param $sClass
|
||||
* @param $sJSONCriterion
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testToOql($sClass, $sJSONCriterion, $sExpectedOQL)
|
||||
{
|
||||
$oSearch = new DBObjectSearch($sClass);
|
||||
$sOql = CriterionToOQL::Convert(
|
||||
$oSearch, json_decode($sJSONCriterion, true)
|
||||
);
|
||||
|
||||
$this->debug($sOql);
|
||||
$this->assertEquals($sExpectedOQL, $sOql);
|
||||
}
|
||||
|
||||
public function ToOqlProvider()
|
||||
{
|
||||
return array(
|
||||
'>' => array(
|
||||
'UserRequest',
|
||||
'{
|
||||
"ref": "UserRequest.start_date",
|
||||
"values": [
|
||||
{
|
||||
"value": "2017-01-01",
|
||||
"label": "2017-01-01 00:00:00"
|
||||
}
|
||||
],
|
||||
"operator": ">",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`UserRequest`.`start_date` > '2017-01-01')"
|
||||
),
|
||||
'contains' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto",
|
||||
"label": "toto"
|
||||
}
|
||||
],
|
||||
"operator": "contains",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` LIKE '%toto%')"
|
||||
),
|
||||
'starts_with' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto",
|
||||
"label": "toto"
|
||||
}
|
||||
],
|
||||
"operator": "starts_with",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` LIKE 'toto%')"
|
||||
),
|
||||
'ends_with' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto",
|
||||
"label": "toto"
|
||||
}
|
||||
],
|
||||
"operator": "ends_with",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` LIKE '%toto')"
|
||||
),
|
||||
'empty' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "empty",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` = '')"
|
||||
),
|
||||
'not_empty' => array(
|
||||
'Contact',
|
||||
'{
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "not_empty",
|
||||
"oql": ""
|
||||
}',
|
||||
"(`Contact`.`name` != '')"
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider ToSearchFormProvider
|
||||
*
|
||||
* @param $aCriterion
|
||||
* @param $sExpectedOperator
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
function testToSearchForm($aCriterion, $sExpectedOperator)
|
||||
{
|
||||
$oSearchForm = new SearchForm();
|
||||
/** @var \DBObjectSearch $oSearch */
|
||||
$oSearch = DBSearch::FromOQL("SELECT Contact");
|
||||
$aFields = $oSearchForm->GetFields(new DBObjectSet($oSearch));
|
||||
$aRes = CriterionToSearchForm::Convert($aCriterion, $aFields, $oSearch->GetJoinedClasses());
|
||||
$this->debug($aRes);
|
||||
$this->assertEquals($sExpectedOperator, $aRes[0]['operator']);
|
||||
}
|
||||
|
||||
function ToSearchFormProvider()
|
||||
{
|
||||
return array(
|
||||
'=' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"ref": "Contact.name",
|
||||
"widget": "string",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto",
|
||||
"label": "toto"
|
||||
}
|
||||
],
|
||||
"operator": "=",
|
||||
"oql": "(`Contact`.`name` = \'toto\')"
|
||||
}
|
||||
]', true),
|
||||
'='
|
||||
),
|
||||
'starts_with' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"ref": "Contact.name",
|
||||
"widget": "string",
|
||||
"values": [
|
||||
{
|
||||
"value": "toto%",
|
||||
"label": "toto%"
|
||||
}
|
||||
],
|
||||
"operator": "LIKE",
|
||||
"oql": "(`Contact`.`name` LIKE \'toto%\')"
|
||||
}
|
||||
]', true),
|
||||
'starts_with'
|
||||
),
|
||||
'ends_with' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"ref": "Contact.name",
|
||||
"widget": "string",
|
||||
"values": [
|
||||
{
|
||||
"value": "%toto",
|
||||
"label": "%toto"
|
||||
}
|
||||
],
|
||||
"operator": "LIKE",
|
||||
"oql": "(`Contact`.`name` LIKE \'%toto\')"
|
||||
}
|
||||
]', true),
|
||||
'ends_with'
|
||||
),
|
||||
'contains' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"widget": "string",
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "%toto%",
|
||||
"label": "%toto%"
|
||||
}
|
||||
],
|
||||
"operator": "LIKE",
|
||||
"oql": "(`Contact`.`name` LIKE \'%toto%\')"
|
||||
}
|
||||
]', true),
|
||||
'contains'
|
||||
),
|
||||
'empty1' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"widget": "string",
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "LIKE",
|
||||
"oql": "(`Contact`.`name` LIKE \'\')"
|
||||
}
|
||||
]', true),
|
||||
'empty'
|
||||
),
|
||||
'empty2' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"widget": "string",
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "=",
|
||||
"oql": "(`Contact`.`name` = \'\')"
|
||||
}
|
||||
]', true),
|
||||
'empty'
|
||||
),
|
||||
'not_empty' => array(
|
||||
json_decode('[
|
||||
{
|
||||
"widget": "string",
|
||||
"ref": "Contact.name",
|
||||
"values": [
|
||||
{
|
||||
"value": "",
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"operator": "!=",
|
||||
"oql": "(`Contact`.`name` != \'\')"
|
||||
}
|
||||
]', true),
|
||||
'not_empty'
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider OqlProvider
|
||||
*
|
||||
* @param $sOQL
|
||||
*
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @param $aExpectedCriterion
|
||||
*
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \OQLException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
function testOqlToSearchToOql($sOQL, $sExpectedOQL, $aExpectedCriterion)
|
||||
{
|
||||
// For tests on tags
|
||||
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag1', 'First');
|
||||
$this->CreateTagData(TAG_CLASS, TAG_ATTCODE, 'tag2', 'Second');
|
||||
|
||||
$this->OqlToSearchToOqlAltLanguage($sOQL, $sExpectedOQL, $aExpectedCriterion, "EN US");
|
||||
}
|
||||
|
||||
function OqlProvider()
|
||||
{
|
||||
return array(
|
||||
'no criteria' => array(
|
||||
'OQL' => 'SELECT WebApplication',
|
||||
'ExpectedOQL' => "SELECT `WebApplication` FROM WebApplication AS `WebApplication` WHERE 1",
|
||||
'ExpectedCriterion' => array(),
|
||||
),
|
||||
'string starts' => array(
|
||||
'OQL' => "SELECT Contact WHERE name LIKE 'toto%'",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`name` LIKE 'toto%')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'starts_with', 'values' => array(array('value' => 'toto')))),
|
||||
),
|
||||
'string ends' => array(
|
||||
'OQL' => "SELECT Contact WHERE name LIKE '%toto'",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`name` LIKE '%toto')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'ends_with', 'values' => array(array('value' => 'toto')))),
|
||||
),
|
||||
'string contains 1' => array(
|
||||
'OQL' => "SELECT Contact WHERE name LIKE '%toto%'",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`name` LIKE '%toto%')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'contains', 'values' => array(array('value' => 'toto')))),
|
||||
),
|
||||
'string contains 2' => array(
|
||||
'OQL' => "SELECT Person AS B WHERE B.name LIKE '%A%'",
|
||||
'ExpectedOQL' => "SELECT `B` FROM Person AS `B` WHERE (`B`.`name` LIKE '%A%')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'contains', 'values' => array(array('value' => 'A')))),
|
||||
),
|
||||
'string NOT contains' => array(
|
||||
'OQL' => "SELECT Person AS B WHERE B.name NOT LIKE '%A%'",
|
||||
'ExpectedOQL' => "SELECT `B` FROM Person AS `B` WHERE (`B`.`name` NOT LIKE '%A%')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'NOT LIKE', 'values' => array(array('value' => '%A%')))),
|
||||
),
|
||||
'string regexp' => array(
|
||||
'OQL' => "SELECT Server WHERE name REGEXP '^dbserver[0-9]+\\\\\\\\..+\\\\\\\\.[a-z]{2,3}$'",
|
||||
'ExpectedOQL' => "SELECT `Server` FROM Server AS `Server` WHERE (`Server`.`name` REGEXP '^dbserver[0-9]+\\\\\\\\..+\\\\\\\\.[a-z]{2,3}$')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'string', 'operator' => 'REGEXP')),
|
||||
),
|
||||
'enum + key =' => array(
|
||||
'OQL' => "SELECT Contact WHERE status = 'active' AND org_id = 3",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` JOIN Organization AS `Organization` ON `Contact`.org_id = `Organization`.id JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE ((`Organization1`.`id` = '3') AND (`Contact`.`status` = 'active'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key', 'operator' => 'IN'), array('widget' => 'enum', 'operator' => 'IN')),
|
||||
),
|
||||
'enum =' => array(
|
||||
'OQL' => "SELECT Contact WHERE status = 'active'",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`status` = 'active')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'operator' => 'IN', 'values' => array(array('value' => 'active')))),
|
||||
),
|
||||
'enum IN' => array(
|
||||
'OQL' => "SELECT Contact WHERE status IN ('active', 'inactive')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE 1",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'operator' => 'IN', 'values' => array(array('value' => 'active'), array('value' => 'inactive')))),
|
||||
),
|
||||
'enum NOT IN 1' => array(
|
||||
'OQL' => "SELECT Contact WHERE status NOT IN ('active')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`status` = 'inactive')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'operator' => 'IN', 'values' => array(array('value' => 'inactive')))),
|
||||
),
|
||||
'enum NOT IN 2' => array(
|
||||
'OQL' => "SELECT Person AS p JOIN UserRequest AS u ON u.agent_id = p.id WHERE u.status != 'closed'",
|
||||
'ExpectedOQL' => "SELECT `p` FROM Person AS `p` JOIN UserRequest AS `u` ON `u`.agent_id = `p`.id WHERE (`u`.`status` != 'closed')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'enum undefined 1' => array(
|
||||
'OQL' => "SELECT FunctionalCI WHERE ((business_criticity = 'high') OR ISNULL(business_criticity)) AND 1",
|
||||
'ExpectedOQL' => "SELECT `FunctionalCI` FROM FunctionalCI AS `FunctionalCI` WHERE (((`FunctionalCI`.`business_criticity` = 'high') OR ISNULL(`FunctionalCI`.`business_criticity`)) AND 1)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'has_undefined' => true, 'operator' => 'IN', 'values' => array(array('value' => 'high'), array('value' => 'null')))),
|
||||
),
|
||||
'enum undefined 2' => array(
|
||||
'OQL' => "SELECT FunctionalCI WHERE ((business_criticity IN ('high', 'medium')) OR ISNULL(business_criticity)) AND 1",
|
||||
'ExpectedOQL' => "SELECT `FunctionalCI` FROM FunctionalCI AS `FunctionalCI` WHERE (((`FunctionalCI`.`business_criticity` IN ('high', 'medium')) OR ISNULL(`FunctionalCI`.`business_criticity`)) AND 1)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'has_undefined' => true, 'operator' => 'IN', 'values' => array(array('value' => 'high'), array('value' => 'medium'), array('value' => 'null')))),
|
||||
),
|
||||
'enum undefined 3' => array(
|
||||
'OQL' => "SELECT FunctionalCI WHERE ISNULL(business_criticity)",
|
||||
'ExpectedOQL' => "SELECT `FunctionalCI` FROM FunctionalCI AS `FunctionalCI` WHERE ISNULL(`FunctionalCI`.`business_criticity`)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'enum', 'has_undefined' => true, 'operator' => 'IN', 'values' => array(array('value' => 'null')))),
|
||||
),
|
||||
'key NOT IN' => array(
|
||||
'OQL' => "SELECT Contact WHERE org_id NOT IN ('1')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` WHERE (`Contact`.`org_id` NOT IN ('1'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw', 'operator' => 'NOT IN')),
|
||||
),
|
||||
'key IN' => array(
|
||||
'OQL' => "SELECT Contact WHERE org_id IN ('1')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` JOIN Organization AS `Organization` ON `Contact`.org_id = `Organization`.id JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE (`Organization1`.`id` = '1')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key', 'operator' => 'IN')),
|
||||
),
|
||||
'key IN 2' => array(
|
||||
'OQL' => "SELECT Contact WHERE org_id IN ('1', '999999')",
|
||||
'ExpectedOQL' => "SELECT `Contact` FROM Contact AS `Contact` JOIN Organization AS `Organization` ON `Contact`.org_id = `Organization`.id JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE (`Organization1`.`id` = '1')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key', 'operator' => 'IN')),
|
||||
),
|
||||
'key empty' => array(
|
||||
'OQL' => "SELECT Person WHERE location_id = '0'",
|
||||
'ExpectedOQL' => "SELECT `Person` FROM Person AS `Person` WHERE (`Person`.`location_id` = '0')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'external_key', 'operator' => 'IN', 'values' => array(array('value' => '0')))),
|
||||
),
|
||||
'Double field' => array(
|
||||
'OQL' => "SELECT UserRequest AS u WHERE u.close_date > u.start_date",
|
||||
'ExpectedOQL' => "SELECT `u` FROM UserRequest AS `u` WHERE (`u`.`close_date` > `u`.`start_date`)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'Num between 1' => array(
|
||||
'OQL' => "SELECT Server WHERE nb_u >= 0 AND 1 >= nb_u",
|
||||
'ExpectedOQL' => "SELECT `Server` FROM Server AS `Server` WHERE ((`Server`.`nb_u` >= '0') AND (`Server`.`nb_u` <= '1'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'numeric', 'operator' => 'between')),
|
||||
),
|
||||
'Num ISNULL' => array(
|
||||
'OQL' => "SELECT Server WHERE ISNULL(nb_u)",
|
||||
'ExpectedOQL' => "SELECT `Server` FROM Server AS `Server` WHERE ISNULL(`Server`.`nb_u`)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'numeric', 'operator' => 'empty')),
|
||||
),
|
||||
'Hierarchical below 1' => array(
|
||||
'OQL' => "SELECT Person AS P JOIN Organization AS Node ON P.org_id = Node.id JOIN Organization AS Root ON Node.parent_id BELOW Root.id WHERE Root.id=1",
|
||||
'ExpectedOQL' => "SELECT `P` FROM Person AS `P` JOIN Organization AS `Node` ON `P`.org_id = `Node`.id JOIN Organization AS `Root` ON `Node`.parent_id BELOW `Root`.id WHERE (`Root`.`id` = '1')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key')),
|
||||
),
|
||||
'Hierarchical below 2' => array(
|
||||
'OQL' => "SELECT `Organization` FROM Organization AS `Organization` JOIN Organization AS `Organization1` ON `Organization`.parent_id = `Organization1`.id JOIN Organization AS `Organization11` ON `Organization1`.parent_id BELOW `Organization11`.id WHERE (((`Organization11`.`id` IN ('1', '2')) OR (`Organization`.`parent_id` = '0')) AND 1)",
|
||||
'ExpectedOQL' => "SELECT `Organization` FROM Organization AS `Organization` JOIN Organization AS `Organization1` ON `Organization`.parent_id = `Organization1`.id JOIN Organization AS `Organization11` ON `Organization1`.parent_id BELOW `Organization11`.id WHERE (((`Organization11`.`id` IN ('1', '2')) OR (`Organization`.`parent_id` = '0')) AND 1)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key')),
|
||||
),
|
||||
'IP range' => array(
|
||||
'OQL' => "SELECT DatacenterDevice AS dev WHERE INET_ATON(dev.managementip) > INET_ATON('10.22.32.224') AND INET_ATON(dev.managementip) < INET_ATON('10.22.32.255')",
|
||||
'ExpectedOQL' => "SELECT `dev` FROM DatacenterDevice AS `dev` WHERE ((INET_ATON(`dev`.`managementip`) < INET_ATON('10.22.32.255')) AND (INET_ATON(`dev`.`managementip`) > INET_ATON('10.22.32.224')))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'TagSet Matches' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE ".TAG_ATTCODE." MATCHES 'tag1'",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE `".TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag1 _\'',
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
'TagSet Matches2' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE ".TAG_ATTCODE." MATCHES 'tag1 tag2'",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE `".TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag1 tag2 _\'',
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
'TagSet Undefined' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE ".TAG_ATTCODE." = ''",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE (`".TAG_CLASS."`.`".TAG_ATTCODE."` = '')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
'TagSet Undefined and tag' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE (((".TAG_ATTCODE." MATCHES 'tag1 tag2') OR (".TAG_ATTCODE." = '')) AND 1)",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE ((`".TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag1 tag2 _\' OR (`'.TAG_CLASS."`.`".TAG_ATTCODE."` = '')) AND 1)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
'TagSet equals' => array(
|
||||
'OQL' => "SELECT ".TAG_CLASS." WHERE ".TAG_ATTCODE." = 'tag1 tag2'",
|
||||
'ExpectedOQL' => "SELECT `".TAG_CLASS."` FROM ".TAG_CLASS." AS `".TAG_CLASS."` WHERE (`".TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag1 _\' AND `'.TAG_CLASS."`.`".TAG_ATTCODE.'` MATCHES \'tag2 _\')',
|
||||
'ExpectedCriterion' => array(array('widget' => 'tag_set')),
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider OqlProviderDates
|
||||
*
|
||||
* @param $sOQL
|
||||
*
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @param $aExpectedCriterion
|
||||
*
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \OQLException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
function testOqlToForSearchToOqlAltLanguageFR($sOQL, $sExpectedOQL, $aExpectedCriterion)
|
||||
{
|
||||
\MetaModel::GetConfig()->Set('date_and_time_format', array('default' => array('date' => 'Y-m-d', 'time' => 'H:i:s', 'date_time' => '$date $time')));
|
||||
$this->OqlToSearchToOqlAltLanguage($sOQL, $sExpectedOQL, $aExpectedCriterion, "FR FR");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dataProvider OqlProviderDates
|
||||
*
|
||||
* @param $sOQL
|
||||
*
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @param $aExpectedCriterion
|
||||
*
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \OQLException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
function testOqlToForSearchToOqlAltLanguageEN($sOQL, $sExpectedOQL, $aExpectedCriterion)
|
||||
{
|
||||
\MetaModel::GetConfig()->Set('date_and_time_format', array('default' => array('date' => 'Y-m-d', 'time' => 'H:i:s', 'date_time' => '$date $time')));
|
||||
$this->OqlToSearchToOqlAltLanguage($sOQL, $sExpectedOQL, $aExpectedCriterion, "EN US");
|
||||
}
|
||||
|
||||
function OqlProviderDates()
|
||||
{
|
||||
return array(
|
||||
|
||||
'Date relative 1' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE DATE_SUB(NOW(), INTERVAL 14 DAY) < start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (DATE_SUB(NOW(), INTERVAL 14 DAY) < `UserRequest`.`start_date`)",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'Date relative 2' => array(
|
||||
'OQL' => "SELECT Contract AS c WHERE c.end_date > NOW() AND c.end_date < DATE_ADD(NOW(), INTERVAL 30 DAY)",
|
||||
'ExpectedOQL' => "SELECT `c` FROM Contract AS `c` WHERE ((`c`.`end_date` < DATE_ADD(NOW(), INTERVAL 30 DAY)) AND (`c`.`end_date` > NOW()))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw'), array('widget' => 'raw')),
|
||||
),
|
||||
'Date relative 3' => array(
|
||||
'OQL' => "SELECT UserRequest AS u WHERE u.close_date > DATE_ADD(u.start_date, INTERVAL 8 HOUR)",
|
||||
'ExpectedOQL' => "SELECT `u` FROM UserRequest AS `u` WHERE (`u`.`close_date` > DATE_ADD(`u`.`start_date`, INTERVAL 8 HOUR))",
|
||||
'ExpectedCriterion' => array(),
|
||||
),
|
||||
'Date relative 4' => array(
|
||||
'OQL' => "SELECT UserRequest AS u WHERE u.start_date < DATE_SUB(NOW(), INTERVAL 60 MINUTE) AND u.status = 'new'",
|
||||
'ExpectedOQL' => "SELECT `u` FROM UserRequest AS `u` WHERE ((`u`.`start_date` < DATE_SUB(NOW(), INTERVAL 60 MINUTE)) AND (`u`.`status` = 'new'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
'Date between 1' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date > '2017-01-01 00:00:00' AND '2018-01-01 00:00:00' >= start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:01') AND (`UserRequest`.`start_date` <= '2018-01-01 00:00:00'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 2' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date > '2017-01-01 00:00:00' AND status = 'active' AND org_id = 3 AND '2018-01-01 00:00:00' >= start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` JOIN Organization AS `Organization` ON `UserRequest`.org_id = `Organization`.id JOIN Organization AS `Organization1` ON `Organization`.parent_id BELOW `Organization1`.id WHERE ((((`Organization1`.`id` = '3') AND (`UserRequest`.`start_date` >= '2017-01-01 00:00:01')) AND (`UserRequest`.`start_date` <= '2018-01-01 00:00:00')) AND (`UserRequest`.`status` = 'active'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'hierarchical_key', 'operator' => 'IN'), array('widget' => 'date_time', 'operator' => 'between_dates'), array('widget' => 'enum', 'operator' => 'IN')),
|
||||
),
|
||||
'Date between 3' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 00:00:00' >= start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:00') AND (`UserRequest`.`start_date` <= '2017-01-01 00:00:00'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 4' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 01:00:00' > start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:00') AND (`UserRequest`.`start_date` <= '2017-01-01 00:59:59'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 5' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-02 00:00:00' > start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:00') AND (`UserRequest`.`start_date` <= '2017-01-01 23:59:59'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 6' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01' AND '2017-01-02' >= start_date",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2017-01-01 00:00:00') AND (`UserRequest`.`start_date` <= '2017-01-02 00:00:00'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date between 7' => array(
|
||||
'OQL' => "SELECT CustomerContract WHERE ((start_date >= '2018-03-01') AND (start_date < '2018-04-01'))",
|
||||
'ExpectedOQL' => "SELECT `CustomerContract` FROM CustomerContract AS `CustomerContract` WHERE ((`CustomerContract`.`start_date` >= '2018-03-01') AND (`CustomerContract`.`start_date` <= '2018-03-31'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date =' => array(
|
||||
'OQL' => "SELECT CustomerContract WHERE (start_date = '2018-03-01')",
|
||||
'ExpectedOQL' => "SELECT `CustomerContract` FROM CustomerContract AS `CustomerContract` WHERE ((`CustomerContract`.`start_date` >= '2018-03-01') AND (`CustomerContract`.`start_date` <= '2018-03-01'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date =2' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE (DATE_FORMAT(start_date, '%Y-%m-%d') = '2018-03-21')",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` >= '2018-03-21 00:00:00') AND (`UserRequest`.`start_date` <= '2018-03-21 23:59:59'))",
|
||||
'ExpectedCriterion' => array(array('widget' => 'date_time', 'operator' => 'between_dates')),
|
||||
),
|
||||
'Date =3' => array(
|
||||
'OQL' => "SELECT UserRequest WHERE (DATE_FORMAT(`UserRequest`.`start_date`, '%w') = '4')",
|
||||
'ExpectedOQL' => "SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE (DATE_FORMAT(`UserRequest`.`start_date`, '%w') = '4')",
|
||||
'ExpectedCriterion' => array(array('widget' => 'raw')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $sOQL
|
||||
*
|
||||
* @param $sExpectedOQL
|
||||
*
|
||||
* @param $aExpectedCriterion
|
||||
*
|
||||
* @param $sLanguageCode
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionUnknownLanguage
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \OQLException
|
||||
*/
|
||||
function OqlToSearchToOqlAltLanguage($sOQL, $sExpectedOQL, $aExpectedCriterion, $sLanguageCode )
|
||||
{
|
||||
$this->debug($sOQL);
|
||||
|
||||
|
||||
Dict::SetUserLanguage($sLanguageCode);
|
||||
|
||||
|
||||
$oSearchForm = new SearchForm();
|
||||
$oSearch = DBSearch::FromOQL($sOQL);
|
||||
$aFields = $oSearchForm->GetFields(new DBObjectSet($oSearch));
|
||||
/** @var \DBObjectSearch $oSearch */
|
||||
$aCriterion = $oSearchForm->GetCriterion($oSearch, $aFields);
|
||||
|
||||
$aAndCriterion = $aCriterion['or'][0]['and'];
|
||||
|
||||
$aNewCriterion = array();
|
||||
foreach($aAndCriterion as $aCriteria)
|
||||
{
|
||||
if ($aCriteria['widget'] != AttributeDefinition::SEARCH_WIDGET_TYPE_RAW)
|
||||
{
|
||||
unset($aCriteria['oql']);
|
||||
foreach($aFields as $aCatFields)
|
||||
{
|
||||
if (isset($aCatFields[$aCriteria['ref']]))
|
||||
{
|
||||
$aField = $aCatFields[$aCriteria['ref']];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isset($aField))
|
||||
{
|
||||
$aCriteria['code'] = $aField['code'];
|
||||
$aCriteria['class'] = $aField['class'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($aCriteria['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_DATE_TIME || $aCriteria['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_DATE)
|
||||
{
|
||||
$sAttributeClass = ($aCriteria['widget'] == AttributeDefinition::SEARCH_WIDGET_TYPE_DATE_TIME) ? AttributeDateTime::class : AttributeDate::class;
|
||||
|
||||
/** @var \AttributeDateTime $sAttributeClass */
|
||||
/** @var \DateTimeFormat $oFormat */
|
||||
$oFormat = $sAttributeClass::GetFormat();
|
||||
|
||||
foreach($aCriteria['values'] as $i => $aValue)
|
||||
{
|
||||
if (!empty($aValue['value'])) {
|
||||
$aCriteria['values'][$i]['value'] = $oFormat->Format($aValue['value']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aNewCriterion[] = $aCriteria;
|
||||
}
|
||||
$this->debug($aNewCriterion);
|
||||
|
||||
$this->assertFalse($this->array_diff_assoc_recursive($aExpectedCriterion, $aNewCriterion), 'Criterion array contains critical parts');
|
||||
|
||||
$aCriterion['or'][0]['and'] = $aNewCriterion;
|
||||
|
||||
$oSearch->ResetCondition();
|
||||
$oFilter = CriterionParser::Parse($oSearch->ToOQL(), $aCriterion);
|
||||
|
||||
$sResultOQL = $oFilter->ToOQL();
|
||||
$this->debug($sResultOQL);
|
||||
|
||||
$this->assertEquals($sExpectedOQL, $sResultOQL);
|
||||
}
|
||||
|
||||
|
||||
function array_diff_assoc_recursive($array1, $array2)
|
||||
{
|
||||
foreach($array1 as $key => $value)
|
||||
{
|
||||
if (is_array($value))
|
||||
{
|
||||
if (!isset($array2[$key]))
|
||||
{
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
elseif (!is_array($array2[$key]))
|
||||
{
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
$new_diff = $this->array_diff_assoc_recursive($value, $array2[$key]);
|
||||
if ($new_diff !== false)
|
||||
{
|
||||
$difference[$key] = $new_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (!array_key_exists($key, $array2) || $array2[$key] != $value)
|
||||
{
|
||||
$difference[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return !isset($difference) ? false : $difference;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2018 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/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Eric
|
||||
* Date: 08/03/2018
|
||||
* Time: 11:28
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application\Search;
|
||||
|
||||
use Combodo\iTop\Application\Search\CriterionParser;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class CriterionParserTest extends ItopDataTestCase
|
||||
{
|
||||
public function testParse()
|
||||
{
|
||||
$sBaseOql = 'SELECT UserRequest';
|
||||
$aCriterion = json_decode('{
|
||||
"or": [
|
||||
{
|
||||
"and": [
|
||||
{
|
||||
"ref": "UserRequest.start_date",
|
||||
"values": [
|
||||
{
|
||||
"value": "2017-01-01",
|
||||
"label": "2017-01-01 00:00:00"
|
||||
}
|
||||
],
|
||||
"operator": ">",
|
||||
"oql": ""
|
||||
},
|
||||
{
|
||||
"ref": "UserRequest.start_date",
|
||||
"values": [
|
||||
{
|
||||
"value": "2018-01-01",
|
||||
"label": "2018-01-01 00:00:00"
|
||||
}
|
||||
],
|
||||
"operator": "<",
|
||||
"oql": "(`UserRequest`.`start_date` < \'2018-01-01\')"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
', true);
|
||||
$oSearch = CriterionParser::Parse($sBaseOql, $aCriterion);
|
||||
|
||||
//$this->debug($oSearch);
|
||||
|
||||
$this->assertEquals("SELECT `UserRequest` FROM UserRequest AS `UserRequest` WHERE ((`UserRequest`.`start_date` > '2017-01-01') AND (`UserRequest`.`start_date` < '2018-01-01'))", $oSearch->ToOQL());
|
||||
}
|
||||
}
|
||||
124
test/php-unit-tests/tests/application/search/SearchFormTest.php
Normal file
124
test/php-unit-tests/tests/application/search/SearchFormTest.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2010-2018 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/>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Application\Search;
|
||||
|
||||
use Combodo\iTop\Application\Search\SearchForm;
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use DBObjectSearch;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* @runTestsInSeparateProcesses
|
||||
* @preserveGlobalState disabled
|
||||
* @backupGlobals disabled
|
||||
*/
|
||||
class SearchFormTest extends ItopDataTestCase
|
||||
{
|
||||
const CREATE_TEST_ORG = true;
|
||||
|
||||
/**
|
||||
* @dataProvider GetFieldsProvider
|
||||
* @throws \OQLException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function testGetFields($sOQL)
|
||||
{
|
||||
$oSearchForm = new SearchForm();
|
||||
$oSearch = \DBSearch::FromOQL($sOQL);
|
||||
$aFields = $oSearchForm->GetFields(new \DBObjectSet($oSearch));
|
||||
$this->debug($sOQL);
|
||||
$this->debug(json_encode($aFields, JSON_PRETTY_PRINT));
|
||||
$this->assertTrue(count($aFields['zlist']) > 0);
|
||||
$this->assertTrue(count($aFields['others']) > 0);
|
||||
}
|
||||
|
||||
public function GetFieldsProvider()
|
||||
{
|
||||
return array(
|
||||
array("SELECT Contact"),
|
||||
array("SELECT Contact AS C WHERE C.status = 'active'"),
|
||||
array("SELECT Person"),
|
||||
array(
|
||||
"SELECT Person AS p JOIN UserRequest AS u ON u.agent_id = p.id WHERE u.status != 'closed'",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dataProvider GetCriterionProvider
|
||||
*
|
||||
* @param $sOQL
|
||||
* @param $iOrCount
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \MissingQueryArgument
|
||||
*/
|
||||
public function testGetCriterion($sOQL, $iOrCount)
|
||||
{
|
||||
$oSearchForm = new SearchForm();
|
||||
try
|
||||
{
|
||||
$oSearch = \DBSearch::FromOQL($sOQL);
|
||||
$aFields = $oSearchForm->GetFields(new \DBObjectSet($oSearch));
|
||||
/** @var DBObjectSearch $oSearch */
|
||||
$aCriterion = $oSearchForm->GetCriterion($oSearch, $aFields);
|
||||
} catch (\OQLException $e)
|
||||
{
|
||||
$this->assertTrue(false);
|
||||
|
||||
return;
|
||||
}
|
||||
$aRes = array('base_oql' => $sOQL, 'criterion' => $aCriterion);
|
||||
$this->debug(json_encode($aRes));
|
||||
$this->debug($sOQL);
|
||||
$this->debug(json_encode($aCriterion, JSON_PRETTY_PRINT));
|
||||
$this->assertCount($iOrCount, $aCriterion['or']);
|
||||
}
|
||||
|
||||
public function GetCriterionProvider()
|
||||
{
|
||||
return array(
|
||||
array('OQL' => "SELECT Contact", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status = 'active'", 1),
|
||||
array('OQL' => "SELECT Contact AS C WHERE C.status = 'active'", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status = 'active' AND name LIKE 'toto%'", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status = 'active' AND org_id = 3", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status IN ('active', 'inactive')", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status NOT IN ('active')", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status NOT IN ('active', 'inactive')", 1),
|
||||
array('OQL' => "SELECT Contact WHERE status = 'active' OR name LIKE 'toto%'", 2),
|
||||
array('OQL' => "SELECT UserRequest WHERE DATE_SUB(NOW(), INTERVAL 14 DAY) < start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date > '2017-01-01 00:00:00' AND '2018-01-01 00:00:00' >= start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date > '2017-01-01 00:00:00' AND status = 'active' AND org_id = 3 AND '2018-01-01 00:00:00' >= start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 00:00:00' >= start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-01 01:00:00' > start_date", 1),
|
||||
array('OQL' => "SELECT UserRequest WHERE start_date >= '2017-01-01 00:00:00' AND '2017-01-02 00:00:00' > start_date", 1),
|
||||
array(
|
||||
'OQL' => "SELECT FunctionalCI WHERE ((business_criticity IN ('high', 'medium')) OR ISNULL(business_criticity)) AND 1",
|
||||
1
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user