mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 18:48:51 +02:00
Merge branch 'develop' into feature/fast-theme-compilation2
This commit is contained in:
@@ -713,7 +713,7 @@ class ItopDataTestCase extends ItopTestCase
|
||||
$iId = $oLnk->Get('functionalci_id');
|
||||
if (!empty($aWaitedCIList))
|
||||
{
|
||||
$this->assertTrue(array_key_exists($iId, $aWaitedCIList));
|
||||
$this->assertArrayHasKey($iId, $aWaitedCIList);
|
||||
$this->assertEquals($aWaitedCIList[$iId], $oLnk->Get('impact_code'));
|
||||
}
|
||||
}
|
||||
@@ -737,7 +737,7 @@ class ItopDataTestCase extends ItopTestCase
|
||||
$iId = $oLnk->Get('contact_id');
|
||||
if (!empty($aWaitedContactList))
|
||||
{
|
||||
$this->assertTrue(array_key_exists($iId, $aWaitedContactList));
|
||||
$this->assertArrayHasKey($iId, $aWaitedContactList);
|
||||
foreach ($aWaitedContactList[$iId] as $sAttCode => $oValue)
|
||||
{
|
||||
if (MetaModel::IsValidAttCode(get_class($oTicket), $sAttCode))
|
||||
@@ -756,5 +756,29 @@ class ItopDataTestCase extends ItopTestCase
|
||||
$this->iTestOrgId = $oOrg->GetKey();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Assert that a series of operations will trigger a given number of MySL queries
|
||||
*
|
||||
* @param $iExpectedCount Number of MySQL queries that should be executed
|
||||
* @param callable $oFunction Operations to perform
|
||||
*
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLQueryHasNoResultException
|
||||
*/
|
||||
protected static function assertDBQueryCount($iExpectedCount, callable $oFunction)
|
||||
{
|
||||
$iInitialCount = (int) CMDBSource::QueryToScalar("SHOW SESSION STATUS LIKE 'Queries'", 1);
|
||||
$oFunction();
|
||||
$iFinalCount = (int) CMDBSource::QueryToScalar("SHOW SESSION STATUS LIKE 'Queries'", 1);
|
||||
$iCount = $iFinalCount - 1 - $iInitialCount;
|
||||
if ($iCount != $iExpectedCount)
|
||||
{
|
||||
static::fail("Expected $iExpectedCount queries. $iCount have been executed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise PHP Unit will consider that no assertion has been made
|
||||
static::assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
68
test/core/CSVParserTest.php
Normal file
68
test/core/CSVParserTest.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Core;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
use CSVParser;
|
||||
|
||||
|
||||
class CSVParserTest extends ItopTestCase
|
||||
{
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
require_once(APPROOT.'core/csvparser.class.inc.php');
|
||||
require_once(APPROOT.'core/coreexception.class.inc.php');
|
||||
}
|
||||
|
||||
public function testFile()
|
||||
{
|
||||
$sSeparator = ';';
|
||||
$sDelimiter = '?';
|
||||
$sDataFile = '?field1?;?field2?;?field3?
|
||||
?line 0, col 0?;?line 0, col 1?;?line 0, col 2?
|
||||
a;b;c
|
||||
a;b;<NULL>
|
||||
? a ? ; ? b ? ; ? c ?
|
||||
a ; b ; c
|
||||
??;??;??
|
||||
;;
|
||||
?a"?;?b?;?c?
|
||||
?a1
|
||||
a2?;?b?;?c?
|
||||
?a1,a2?;?b?;?c?
|
||||
?a?;?b?;?c1,",c2
|
||||
,c3?
|
||||
?a?;?b?;?ouf !?
|
||||
spaces trimmed out ; 1234; mac@enroe.com ';
|
||||
|
||||
$aExpectedResult = array(
|
||||
array('line 0, col 0', 'line 0, col 1', 'line 0, col 2'),
|
||||
array('a', 'b', 'c'),
|
||||
array('a', 'b', null),
|
||||
array(' a ', ' b ', ' c '),
|
||||
array('a', 'b', 'c'),
|
||||
array('', '', ''),
|
||||
array('', '', ''),
|
||||
array('a"', 'b', 'c'),
|
||||
array("a1\na2", 'b', 'c'),
|
||||
array('a1,a2', 'b', 'c'),
|
||||
array('a', 'b', "c1,\",c2\n,c3"),
|
||||
array('a', 'b', 'ouf !'),
|
||||
array('spaces trimmed out', '1234', 'mac@enroe.com'),
|
||||
);
|
||||
|
||||
$oCSVParser = new CSVParser($sDataFile, $sSeparator, $sDelimiter);
|
||||
$aData = $oCSVParser->ToArray(1, null, 0);
|
||||
|
||||
foreach ($aData as $iRow => $aRow)
|
||||
{
|
||||
foreach ($aRow as $iCol => $cellValue)
|
||||
{
|
||||
$this->assertSame($aExpectedResult[$iRow][$iCol], $cellValue, "Line $iRow, Column $iCol");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ class DBObjectTest extends ItopDataTestCase
|
||||
|
||||
/**
|
||||
* Test default page name
|
||||
* @covers DBObject::GetUIPage
|
||||
*/
|
||||
public function testGetUIPage()
|
||||
{
|
||||
@@ -81,6 +82,9 @@ class DBObjectTest extends ItopDataTestCase
|
||||
array('PHP_INT_MIN', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers DBObject::GetOriginal
|
||||
*/
|
||||
public function testGetOriginal()
|
||||
{
|
||||
$oObject = $this->CreateUserRequest(190664);
|
||||
@@ -88,4 +92,114 @@ class DBObjectTest extends ItopDataTestCase
|
||||
static::assertNull($oObject->GetOriginal('sla_tto_passed'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers DBObject::NewObject
|
||||
* @covers DBObject::Get
|
||||
* @covers DBObject::Set
|
||||
*/
|
||||
public function testAttributeRefresh_FriendlyName()
|
||||
{
|
||||
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));
|
||||
|
||||
static::assertEquals('John Foo', $oObject->Get('friendlyname'));
|
||||
$oObject->Set('name', 'Who');
|
||||
static::assertEquals('John Who', $oObject->Get('friendlyname'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers MetaModel::GetObject
|
||||
* @covers DBObject::Get
|
||||
* @covers DBObject::Set
|
||||
*/
|
||||
public function testAttributeRefresh_FriendlyNameFromDB()
|
||||
{
|
||||
$oObject = \MetaModel::NewObject('Person', array('name' => 'Gary', 'first_name' => 'Romain', 'org_id' => 3, 'location_id' => 2));
|
||||
$oObject->DBInsert();
|
||||
$iObjKey = $oObject->GetKey();
|
||||
|
||||
$oObject = \MetaModel::GetObject('Person', $iObjKey);
|
||||
|
||||
static::assertEquals('Romain Gary', $oObject->Get('friendlyname'));
|
||||
$oObject->Set('name', 'Duris');
|
||||
static::assertEquals('Romain Duris', $oObject->Get('friendlyname'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers DBObject::NewObject
|
||||
* @covers DBObject::Get
|
||||
* @covers DBObject::Set
|
||||
*/
|
||||
public function testAttributeRefresh_ObsolescenceFlag()
|
||||
{
|
||||
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));
|
||||
|
||||
static::assertEquals(false, (bool)$oObject->Get('obsolescence_flag'));
|
||||
$oObject->Set('status', 'inactive');
|
||||
static::assertEquals(true, (bool)$oObject->Get('obsolescence_flag'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers DBObject::NewObject
|
||||
* @covers DBObject::Get
|
||||
* @covers DBObject::Set
|
||||
*/
|
||||
public function testAttributeRefresh_ExternalKeysAndFields()
|
||||
{
|
||||
static::assertDBQueryCount(0, function() use (&$oObject){
|
||||
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));
|
||||
});
|
||||
static::assertDBQueryCount(2, function() use (&$oObject){
|
||||
static::assertEquals('Demo', $oObject->Get('org_id_friendlyname'));
|
||||
static::assertEquals('Grenoble', $oObject->Get('location_id_friendlyname'));
|
||||
});
|
||||
|
||||
// External key given as an id
|
||||
static::assertDBQueryCount(1, function() use (&$oObject){
|
||||
$oObject->Set('org_id', 2);
|
||||
static::assertEquals('IT Department', $oObject->Get('org_id_friendlyname'));
|
||||
});
|
||||
|
||||
// External key given as an object
|
||||
static::assertDBQueryCount(1, function() use (&$oBordeaux){
|
||||
$oBordeaux = \MetaModel::GetObject('Location', 1);
|
||||
});
|
||||
|
||||
static::assertDBQueryCount(0, function() use (&$oBordeaux, &$oObject){
|
||||
$oObject->Set('location_id', $oBordeaux);
|
||||
static::assertEquals('IT Department', $oObject->Get('org_id_friendlyname'));
|
||||
static::assertEquals('IT Department', $oObject->Get('org_name'));
|
||||
static::assertEquals('Bordeaux', $oObject->Get('location_id_friendlyname'));
|
||||
});
|
||||
}
|
||||
|
||||
public function testSetExtKeyUnsetDependentAttribute()
|
||||
{
|
||||
$oObject = \MetaModel::NewObject('Person', array('name' => 'Foo', 'first_name' => 'John', 'org_id' => 3, 'location_id' => 2));
|
||||
$oOrg = \MetaModel::GetObject('Organization', 2);
|
||||
$oObject->Set('org_id', $oOrg);
|
||||
static::assertEquals(0, $oObject->Get('location_id'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group Integration
|
||||
*/
|
||||
public function testModelExpressions()
|
||||
{
|
||||
foreach (\MetaModel::GetClasses() as $sClass)
|
||||
{
|
||||
if (\MetaModel::IsAbstract($sClass)) continue;
|
||||
|
||||
$oObject = \MetaModel::NewObject($sClass);
|
||||
foreach (\MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ($oAttDef->IsBasedOnOQLExpression())
|
||||
{
|
||||
$this->debug("$sClass::$sAttCode");
|
||||
static::assertDBQueryCount(0, function() use (&$oObject, &$oAttDef){
|
||||
$oObject->EvaluateExpression($oAttDef->GetOQLExpression());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
535
test/core/ExpressionEvaluateTest.php
Normal file
535
test/core/ExpressionEvaluateTest.php
Normal file
@@ -0,0 +1,535 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Core;
|
||||
|
||||
|
||||
use CMDBSource;
|
||||
use Combodo\iTop\Test\UnitTest\iTopDataTestCase;
|
||||
use DateInterval;
|
||||
use DateTime;
|
||||
use Expression;
|
||||
use FunctionExpression;
|
||||
use MetaModel;
|
||||
use ScalarExpression;
|
||||
|
||||
class ExpressionEvaluateTest extends iTopDataTestCase
|
||||
{
|
||||
const USE_TRANSACTION = false;
|
||||
|
||||
/**
|
||||
* @covers Expression::GetParameters()
|
||||
* @dataProvider GetParametersProvider
|
||||
*
|
||||
* @param $sExpression
|
||||
* @param $sParentFilter
|
||||
* @param $aExpectedParameters
|
||||
*
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function testGetParameters($sExpression, $sParentFilter, $aExpectedParameters)
|
||||
{
|
||||
$oExpression = Expression::FromOQL($sExpression);
|
||||
$aParameters = $oExpression->GetParameters($sParentFilter);
|
||||
sort($aExpectedParameters);
|
||||
sort($aParameters);
|
||||
static::assertEquals($aExpectedParameters, $aParameters);
|
||||
}
|
||||
|
||||
public function GetParametersProvider()
|
||||
{
|
||||
return array(
|
||||
array('1 AND 0 OR :hello + :world', null, array('hello', 'world')),
|
||||
array('1 AND 0 OR :hello + :world', 'this', array()),
|
||||
array(':this->left + :this->right', null, array('this->left', 'this->right')),
|
||||
array(':this->left + :this->right', 'this', array('left', 'right')),
|
||||
array(':this->left + :this->right', 'that', array()),
|
||||
array(':this_left + :this_right', 'this', array()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 100x quicker to execute than testExpressionEvaluate
|
||||
*
|
||||
* @covers Expression::Evaluate()
|
||||
* @covers Expression::FromOQL()
|
||||
* @relies-on-dataProvider VariousExpressions
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function _testExpressionEvaluateAllAtOnce()
|
||||
{
|
||||
$aTestCases = $this->VariousExpressionsProvider();
|
||||
foreach ($aTestCases as $sCaseId => $aTestArgs)
|
||||
{
|
||||
$this->debug("Case $sCaseId:");
|
||||
$this->testVariousExpressions($aTestArgs[0], $aTestArgs[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Expression::Evaluate()
|
||||
* @covers Expression::FromOQL()
|
||||
* @dataProvider VariousExpressionsProvider
|
||||
*
|
||||
* @param string $sExpression
|
||||
* @param string $expectedValue
|
||||
*
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testVariousExpressions($sExpression, $expectedValue)
|
||||
{
|
||||
$oExpression = Expression::FromOQL($sExpression);
|
||||
$value = $oExpression->Evaluate(array());
|
||||
static::assertEquals($expectedValue, $value);
|
||||
}
|
||||
|
||||
public function VariousExpressionsProvider()
|
||||
{
|
||||
if (false)
|
||||
{
|
||||
$aExpressions = array(
|
||||
// Test case to isolate for troubleshooting purposes
|
||||
array('1+1', 2),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aExpressions = array(
|
||||
// The bare minimum
|
||||
array('"blah"', 'blah'),
|
||||
array('"\\\\"', '\\'),
|
||||
// Arithmetics
|
||||
array('2+2', 4),
|
||||
array('2+2-2', 2),
|
||||
array('2*(3+4)', 14),
|
||||
array('(2*3)+4', 10),
|
||||
array('2*3+4', 10),
|
||||
// Strings
|
||||
array("CONCAT('hello', 'world')", 'helloworld'),
|
||||
// Not yet parsed - array("CONCAT_WS(' ', 'hello', 'world')", 'hello world'),
|
||||
array("SUBSTR('abcdef', 2, 3)", 'bcd'),
|
||||
array("TRIM(' Sin dolor ')", 'Sin dolor'),
|
||||
// Comparison operators
|
||||
array('1 = 1', 1),
|
||||
array('1 != 1', 0),
|
||||
array('0 = 1', 0),
|
||||
array('0 != 1', 1),
|
||||
array('2 > 1', 1),
|
||||
array('2 < 1', 0),
|
||||
array('1 > 2', 0),
|
||||
array('2 > 1', 1),
|
||||
array('2 >= 1', 1),
|
||||
array('2 >= 2', 1),
|
||||
array("'the quick brown dog' LIKE '%QUICK%'", 1),
|
||||
array("'the quick brown dog' LIKE '%SLOW%'", 0),
|
||||
array("'the quick brown dog' LIKE '%QU_CK%'", 1),
|
||||
array("'the quick brown dog' LIKE '%QU_ICK%'", 0),
|
||||
array('"400 (km/h)" LIKE "400%"', 1),
|
||||
array('"400 (km/h)" LIKE "100%"', 0),
|
||||
array('"2020-06-12" > "2020-06-11"', 1),
|
||||
array('"2020-06-12" < "2020-06-11"', 0),
|
||||
array('" 2020-06-12" > "2020-06-11"', 0), // Leading spaces => a string
|
||||
array('" 2020-06-12 " > "2020-06-11"', 0), // Trailing spaces => a string
|
||||
array('"2020-06-12 17:35:13" > "2020-06-12 17:35:12"', 1),
|
||||
array('"2020-06-12 17:35:13" < "2020-06-12 17:35:12"', 0),
|
||||
array('"2020-06-12 17:35:13" > "2020-06-12"', 1),
|
||||
array('"2020-06-12 17:35:13" < "2020-06-12"', 0),
|
||||
array('"2020-06-12 00:00:00" = "2020-06-12"', 0),
|
||||
// Logical operators
|
||||
array('0 AND 0', 0),
|
||||
array('1 AND 0', 0),
|
||||
array('0 AND 1', 0),
|
||||
array('1 AND 1', 1),
|
||||
array('0 OR 0', 0),
|
||||
array('0 OR 1', 1),
|
||||
array('1 OR 0', 1),
|
||||
array('1 OR 1', 1),
|
||||
array('1 AND 0 OR 1', 1),
|
||||
// Casting
|
||||
array('1 AND "blah"', 0),
|
||||
array('1 AND "1"', 1),
|
||||
array('1 AND "2"', 1),
|
||||
array('1 AND "0"', 0),
|
||||
array('1 AND "-1"', 1),
|
||||
// Null
|
||||
array('NULL', null),
|
||||
array('1 AND NULL', null),
|
||||
array('CONCAT("Great but...", NULL)', null),
|
||||
array('COALESCE(NULL, 123)', 123),
|
||||
array('COALESCE(321, 123)', 321),
|
||||
array('ISNULL(NULL)', 1),
|
||||
array('ISNULL(123)', 0),
|
||||
// Date functions
|
||||
array("DATE('2020-03-12 13:18:30')", '2020-03-12'),
|
||||
array("DATE_FORMAT('2009-10-04 22:23:00', '%Y %m %d %H %i %s')", '2009 10 04 22 23 00'),
|
||||
array("DATE(NOW()) = CURRENT_DATE()", 1), // Could fail if executed around midnight!
|
||||
array("TO_DAYS('2020-01-02')", 737791),
|
||||
array("FROM_DAYS(737791)", '2020-01-02'),
|
||||
array("YEAR('2020-05-03')", 2020),
|
||||
array("MONTH('2020-05-03')", 5),
|
||||
array("DAY('2020-05-03')", 3),
|
||||
array("DATE_ADD('2020-02-28 18:00:00', INTERVAL 1 HOUR)", '2020-02-28 19:00:00'),
|
||||
array("DATE_ADD('2020-02-28 18:00:00', INTERVAL 1 DAY)", '2020-02-29 18:00:00'),
|
||||
array("DATE_SUB('2020-03-01 18:00:00', INTERVAL 1 HOUR)", '2020-03-01 17:00:00'),
|
||||
array("DATE_SUB('2020-03-01 18:00:00', INTERVAL 1 DAY)", '2020-02-29 18:00:00'),
|
||||
// Misc. functions
|
||||
array('IF(1, 123, 567)', 123),
|
||||
array('IF(0, 123, 567)', 567),
|
||||
array('ELT(3, "a", "b", "c")', 'c'),
|
||||
array('ELT(0, "a", "b", "c")', null),
|
||||
array('ELT(4, "a", "b", "c")', null),
|
||||
array('INET_ATON("128.0.0.1")', 2147483649),
|
||||
array('INET_NTOA(2147483649)', '128.0.0.1'),
|
||||
);
|
||||
}
|
||||
|
||||
// Build a comprehensive index
|
||||
$aRet = array();
|
||||
foreach ($aExpressions as $aExp)
|
||||
{
|
||||
$aRet[$aExp[0]] = $aExp;
|
||||
}
|
||||
return $aRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Expression::Evaluate()
|
||||
* @dataProvider NotYetParsableExpressionsProvider
|
||||
*
|
||||
* @param string $sExpression
|
||||
* @param string $expectedValue
|
||||
*/
|
||||
public function testNotYetParsableExpressions($sExpression, $expectedValue)
|
||||
{
|
||||
$sNewExpression = "return $sExpression;";
|
||||
$oExpression = eval($sNewExpression);
|
||||
$res = $oExpression->Evaluate(array());
|
||||
static::assertEquals($expectedValue, $res);
|
||||
}
|
||||
|
||||
public function NotYetParsableExpressionsProvider()
|
||||
{
|
||||
$aExpressions = array(
|
||||
array("new \\FunctionExpression('CONCAT_WS', array(new \\ScalarExpression(' '), new \\ScalarExpression('Hello'), new \ScalarExpression('world!')))", 'Hello world!'),
|
||||
array("new \\ScalarExpression('windows\\system32')", 'windows\\system32'),
|
||||
array("new \\BinaryExpression(new \\ScalarExpression('100%'), 'LIKE', new \\ScalarExpression('___\%'))", 1),
|
||||
array("new \\BinaryExpression(new \ScalarExpression('1000'), 'LIKE', new \ScalarExpression('___\%'))", 0),
|
||||
// Net yet parsed - array("TIME(NOW()) = CURRENT_TIME()", 1), // Not relevant
|
||||
// Not yet parsed - array("DATE_ADD('2020-02-28 18:00:00', INTERVAL 1 WEEK)", '2020-03-06 18:00:00'),
|
||||
// Not yet parsed - array("DATE_SUB('2020-03-01 18:00:00', INTERVAL 1 WEEK)", '2020-02-23 18:00:00'),
|
||||
// Not yet parsed - array('ROUND(1.2345, 2)', 1.23),
|
||||
// Not yet parsed - array('FLOOR(1.2)', 1),
|
||||
);
|
||||
// Build a comprehensive index
|
||||
$aRet = array();
|
||||
foreach ($aExpressions as $aExp)
|
||||
{
|
||||
$aRet[$aExp[0]] = $aExp;
|
||||
}
|
||||
return $aRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the test data would give the same result when evaluated by MySQL
|
||||
* It uses the data provider ExpressionProvider, and checks every test case in one single query
|
||||
*
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function testMySQLEvaluateAllAtOnce()
|
||||
{
|
||||
// Expressions given as an OQL
|
||||
$aTests = array_values($this->VariousExpressionsProvider());
|
||||
|
||||
// Expressions given as a PHP statement
|
||||
foreach (array_values($this->NotYetParsableExpressionsProvider()) as $i => $aTest)
|
||||
{
|
||||
$sNewExpression = "return {$aTest[0]};";
|
||||
$oExpression = eval($sNewExpression);
|
||||
$sExpression = $oExpression->RenderExpression(true);
|
||||
$aTests[] = array($sExpression, $aTest[1]);
|
||||
}
|
||||
|
||||
$aExpressions = array();
|
||||
foreach ($aTests as $i => $aTest)
|
||||
{
|
||||
$aExpressions[] = "{$aTest[0]} as test_$i";
|
||||
}
|
||||
|
||||
$sSelects = implode(', ', $aExpressions);
|
||||
$sQuery = "SELECT $sSelects";
|
||||
|
||||
$this->debug($sQuery);
|
||||
$aResults = CMDBSource::QueryToArray($sQuery);
|
||||
|
||||
foreach ($aTests as $i => $aTest)
|
||||
{
|
||||
$value = $aResults[0]["test_$i"];
|
||||
$expectedValue = $aTest[1];
|
||||
$this->debug("Test #$i: {$aTests[$i][0]} => ".var_export($value, true));
|
||||
static::assertEquals($expectedValue, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers DBObject::EvaluateExpression
|
||||
* @dataProvider ExpressionsWithObjectFieldsProvider
|
||||
*
|
||||
* @param $sClass
|
||||
* @param $aValues
|
||||
* @param $sExpression
|
||||
* @param $expected
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function testExpressionsWithObjectFields($sClass, $aValues, $sExpression, $expected)
|
||||
{
|
||||
$oObject = MetaModel::NewObject($sClass, $aValues);
|
||||
$oExpression = Expression::FromOQL($sExpression);
|
||||
|
||||
$res = $oObject->EvaluateExpression($oExpression);
|
||||
|
||||
static::assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function ExpressionsWithObjectFieldsProvider()
|
||||
{
|
||||
return array(
|
||||
array('Location', array('name' => 'Grenoble', 'org_id' => 2), 'org_id', 2),
|
||||
array('Location', array('name' => 'Grenoble', 'org_id' => 2), 'CONCAT(SUBSTR(name, 4), " cause")', 'noble cause'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider ExpressionWithParametersProvider
|
||||
*
|
||||
* @param $sExpression
|
||||
* @param $aParameters
|
||||
* @param $expected
|
||||
*
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testExpressionWithParameters($sExpression, $aParameters, $expected)
|
||||
{
|
||||
$oExpression = Expression::FromOQL($sExpression);
|
||||
$res = $oExpression->Evaluate($aParameters);
|
||||
static::assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function ExpressionWithParametersProvider()
|
||||
{
|
||||
return array(
|
||||
array('CONCAT(SUBSTR(name, 4), " cause")', array('name' => 'noble'), 'le cause'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Expression::IfTrue
|
||||
*
|
||||
* @covers Expression::FromOQL
|
||||
* @covers Expression::IsTrue
|
||||
* @dataProvider TrueExpressionsProvider
|
||||
*
|
||||
* @param $sExpression
|
||||
* @param $bExpectTrue
|
||||
*
|
||||
* @throws \OQLException
|
||||
*/
|
||||
public function testTrueExpressions($sExpression, $bExpectTrue)
|
||||
{
|
||||
$oExpression = Expression::FromOQL($sExpression);
|
||||
|
||||
$res = $oExpression->IsTrue();
|
||||
if ($bExpectTrue)
|
||||
{
|
||||
static::assertTrue($res, 'arg: '.$sExpression);
|
||||
}
|
||||
else
|
||||
{
|
||||
static::assertFalse($res, 'arg: '.$sExpression);
|
||||
}
|
||||
}
|
||||
|
||||
public function TrueExpressionsProvider()
|
||||
{
|
||||
$aExpressions = array(
|
||||
array('1', true),
|
||||
array('0 OR 0', false),
|
||||
array('1 AND 1', true),
|
||||
array('1 AND (1 OR 0)', true)
|
||||
);
|
||||
// Build a comprehensive index
|
||||
$aRet = array();
|
||||
foreach ($aExpressions as $aExp)
|
||||
{
|
||||
$aRet[$aExp[0]] = $aExp;
|
||||
}
|
||||
return $aRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers FunctionExpression::Evaluate()
|
||||
* @dataProvider TimeFormatsProvider
|
||||
*
|
||||
* @param $sFormat
|
||||
* @param $bProcessed
|
||||
* @param $sValueOrException
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLQueryHasNoResultException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testTimeFormat($sFormat, $bProcessed, $sValueOrException)
|
||||
{
|
||||
$sDate = '2009-06-04 21:23:24';
|
||||
$oExpression = new FunctionExpression('DATE_FORMAT', array(new ScalarExpression($sDate), new ScalarExpression("%$sFormat")));
|
||||
if ($bProcessed)
|
||||
{
|
||||
$sqlValue = CMDBSource::QueryToScalar("SELECT DATE_FORMAT('$sDate', '%$sFormat')");
|
||||
static::assertEquals($sqlValue, $sValueOrException, 'Check test against MySQL');
|
||||
|
||||
$res = $oExpression->Evaluate(array());
|
||||
static::assertEquals($sValueOrException, $res, 'Check evaluation');
|
||||
}
|
||||
else
|
||||
{
|
||||
static::expectException($sValueOrException);
|
||||
$oExpression->Evaluate(array());
|
||||
}
|
||||
}
|
||||
|
||||
public function TimeFormatsProvider()
|
||||
{
|
||||
$aTests = array(
|
||||
array('a', true, 'Thu'),
|
||||
array('b', true, 'Jun'),
|
||||
array('c', true, '6'),
|
||||
array('D', true, '4th'),
|
||||
array('d', true, '04'),
|
||||
array('e', true, '4'),
|
||||
array('f', false, 'NotYetEvaluatedExpression'), // microseconds: no way!
|
||||
array('H', true, '21'),
|
||||
array('h', true, '09'),
|
||||
array('I', true, '09'),
|
||||
array('i', true, '23'),
|
||||
array('j', true, '155'), // day of the year
|
||||
array('k', true, '21'),
|
||||
array('l', true, '9'),
|
||||
array('M', true, 'June'),
|
||||
array('m', true, '06'),
|
||||
array('p', true, 'PM'),
|
||||
array('r', true, '09:23:24 PM'),
|
||||
array('S', true, '24'),
|
||||
array('s', true, '24'),
|
||||
array('T', true, '21:23:24'),
|
||||
array('U', false, 'NotYetEvaluatedExpression'), // Week sunday based (mode 0)
|
||||
array('u', false, 'NotYetEvaluatedExpression'), // Week monday based (mode 1)
|
||||
array('V', false, 'NotYetEvaluatedExpression'), // Week sunday based (mode 2)
|
||||
array('v', true, '23'), // Week monday based (mode 3 - ISO-8601)
|
||||
array('W', true, 'Thursday'),
|
||||
array('w', true, '4'),
|
||||
array('X', false, 'NotYetEvaluatedExpression'),
|
||||
array('x', true, '2009'), // to be used with %v (ISO - 8601)
|
||||
array('Y', true, '2009'),
|
||||
array('y', true, '09'),
|
||||
);
|
||||
$aRes = array();
|
||||
foreach ($aTests as $aTest)
|
||||
{
|
||||
$aRes["Format %{$aTest[0]}"] = $aTest;
|
||||
}
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Systematically check all supported format specs, for a given date
|
||||
*
|
||||
* @covers FunctionExpression::Evaluate()
|
||||
* @dataProvider EveryTimeFormatProvider
|
||||
*
|
||||
* @param $sDate
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testEveryTimeFormat($sDate)
|
||||
{
|
||||
$aFormats = $this->TimeFormatsProvider();
|
||||
$aSelects = array();
|
||||
foreach ($aFormats as $sFormatDesc => $aFormatSpec)
|
||||
{
|
||||
$sFormat = $aFormatSpec[0];
|
||||
$bProcessed = $aFormatSpec[1];
|
||||
if ($bProcessed)
|
||||
{
|
||||
$aSelects["%$sFormat"] = "DATE_FORMAT('$sDate', '%$sFormat') AS `$sFormat`";
|
||||
}
|
||||
}
|
||||
$sSelects = "SELECT ".implode(', ', $aSelects);
|
||||
$aRes = CMDBSource::QueryToArray($sSelects);
|
||||
$aRow = $aRes[0];
|
||||
foreach ($aFormats as $sFormatDesc => $aFormatSpec)
|
||||
{
|
||||
$sFormat = $aFormatSpec[0];
|
||||
$bProcessed = $aFormatSpec[1];
|
||||
if ($bProcessed)
|
||||
{
|
||||
$oExpression = new FunctionExpression('DATE_FORMAT', array(new ScalarExpression($sDate), new ScalarExpression("%$sFormat")));
|
||||
$res = $oExpression->Evaluate(array());
|
||||
static::assertEquals($aRow[$sFormat], $res, "Format %$sFormat not matching MySQL for '$sDate'");
|
||||
}
|
||||
}
|
||||
}
|
||||
public function EveryTimeFormatProvider()
|
||||
{
|
||||
return array(
|
||||
array('1971-07-19 8:40:00'),
|
||||
array('1999-12-31 23:59:59'),
|
||||
array('2000-01-01 00:00:00'),
|
||||
array('2009-06-04 21:23:24'),
|
||||
array('2020-02-29 23:59:59'),
|
||||
array('2030-10-21 23:59:59'),
|
||||
array('2050-12-21 23:59:59'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Systematically check all supported format specs, for a range of dates
|
||||
*
|
||||
* @covers FunctionExpression::Evaluate()
|
||||
* @dataProvider EveryTimeFormatOnDateRangeProvider
|
||||
*
|
||||
* @param $sStartDate
|
||||
* @param $sInterval
|
||||
* @param $iRepeat
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testEveryTimeFormatOnDateRange($sStartDate, $sInterval, $iRepeat)
|
||||
{
|
||||
$oDate = new DateTime($sStartDate);
|
||||
for ($i = 0 ; $i < $iRepeat ; $i++)
|
||||
{
|
||||
$sDate = date_format($oDate, 'Y-m-d, H:i:s');
|
||||
$this->debug("Checking '$sDate'");
|
||||
$this->testEveryTimeFormat($sDate);
|
||||
$oDate->add(new DateInterval($sInterval));
|
||||
}
|
||||
}
|
||||
|
||||
public function EveryTimeFormatOnDateRangeProvider()
|
||||
{
|
||||
return array(
|
||||
'10 years, day by day' => array('2000-01-01', 'P1D', 365 * 10),
|
||||
'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),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -277,5 +277,42 @@ class HTMLDOMSanitizerTest extends ItopTestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider CallInlineImageProcessImageTagProvider
|
||||
*/
|
||||
public function testDoSanitizeCallInlineImageProcessImageTag($sHtml, $iExpectedCount)
|
||||
{
|
||||
require_once APPROOT.'test/core/sanitizer/InlineImageMock.php';
|
||||
|
||||
$oSanitizer = new HTMLDOMSanitizer();
|
||||
$oSanitizer->DoSanitize($sHtml);
|
||||
|
||||
$iCalledCount = \InlineImage::GetCallCounter();
|
||||
$this->assertEquals($iExpectedCount, $iCalledCount);
|
||||
}
|
||||
|
||||
public function CallInlineImageProcessImageTagProvider()
|
||||
{
|
||||
return array(
|
||||
'no image' => array(
|
||||
'html' => '<p>bar</p>',
|
||||
'expected' => 0,
|
||||
),
|
||||
'basic image' => array(
|
||||
'html' => '<img />',
|
||||
'expected' => 1,
|
||||
),
|
||||
'nested images within forbidden tags' => array(
|
||||
'html' => '<html><body><img /><iframe baz="1"><div baz="baz"><article baz="1" biz="2">baz<img /><img /></article>rab</div> oof<img /></iframe><img /></body></html>',
|
||||
'expected' => 2,
|
||||
),
|
||||
// This test will be restored with the ticket n°2556
|
||||
// 'nested images within forbidden and removed tags' => array(
|
||||
// 'html' => '<html><body><img /><iframe baz="1"><div baz="baz"><object baz="1" biz="2">baz<img /><img /></object>rab</div> oof<img /></iframe><img /></body></html>',
|
||||
// 'expected' => 2,
|
||||
// ),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -83,4 +83,230 @@ class MetaModelTest extends ItopDataTestCase
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers MetaModel::GetDependentAttributes()
|
||||
* @dataProvider GetDependentAttributesProvider
|
||||
*
|
||||
* @param string $sClass
|
||||
* @param string $sAttCode
|
||||
* @param array $aExpectedAttCodes
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testGetDependentAttributes($sClass, $sAttCode, array $aExpectedAttCodes)
|
||||
{
|
||||
$aRes = MetaModel::GetDependentAttributes($sClass, $sAttCode);
|
||||
// The order doesn't matter
|
||||
sort($aRes);
|
||||
sort($aExpectedAttCodes);
|
||||
static::assertEquals($aExpectedAttCodes, $aRes);
|
||||
}
|
||||
|
||||
public function GetDependentAttributesProvider()
|
||||
{
|
||||
$aRawCases = array(
|
||||
array('Person', 'org_id', array('location_id', 'org_name', 'org_id_friendlyname', 'org_id_obsolescence_flag')),
|
||||
array('Person', 'name', array('friendlyname')),
|
||||
array('Person', 'status', array('obsolescence_flag')),
|
||||
);
|
||||
$aRet = array();
|
||||
foreach ($aRawCases as $i => $aData)
|
||||
{
|
||||
$aRet[$aData[0].'::'.$aData[1]] = $aData;
|
||||
}
|
||||
return $aRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers MetaModel::GetPrerequisiteAttributes()
|
||||
* @dataProvider GetPrerequisiteAttributesProvider
|
||||
*
|
||||
* @param string $sClass
|
||||
* @param string $sAttCode
|
||||
* @param array $aExpectedAttCodes
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testGetPrerequisiteAttributes($sClass, $sAttCode, array $aExpectedAttCodes)
|
||||
{
|
||||
$aRes = MetaModel::GetPrerequisiteAttributes($sClass, $sAttCode);
|
||||
// The order doesn't matter
|
||||
sort($aRes);
|
||||
sort($aExpectedAttCodes);
|
||||
static::assertEquals($aRes, $aExpectedAttCodes);
|
||||
}
|
||||
|
||||
public function GetPrerequisiteAttributesProvider()
|
||||
{
|
||||
$aRawCases = array(
|
||||
array('Person', 'friendlyname', array('name', 'first_name')),
|
||||
array('Person', 'obsolescence_flag', array('status')),
|
||||
array('Person', 'org_id_friendlyname', array('org_id')),
|
||||
array('Person', 'org_id', array()),
|
||||
array('Person', 'org_name', array('org_id')),
|
||||
);
|
||||
$aRet = array();
|
||||
foreach ($aRawCases as $i => $aData)
|
||||
{
|
||||
$aRet[$aData[0].'::'.$aData[1]] = $aData;
|
||||
}
|
||||
return $aRet;
|
||||
}
|
||||
|
||||
/**
|
||||
* To be removed as soon as the dependencies on external fields are obsoleted
|
||||
* @Group Integration
|
||||
*/
|
||||
public function testManualVersusAutomaticDependenciesOnExtKeys()
|
||||
{
|
||||
foreach (\MetaModel::GetClasses() as $sClass)
|
||||
{
|
||||
if (\MetaModel::IsAbstract($sClass)) continue;
|
||||
|
||||
foreach (\MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if (\MetaModel::GetAttributeOrigin($sClass, $sAttCode) != $sClass) continue;
|
||||
if (!$oAttDef instanceof \AttributeExternalKey) continue;
|
||||
|
||||
$aManual = $oAttDef->Get('depends_on');
|
||||
$aAuto = \MetaModel::GetPrerequisiteAttributes($sClass, $sAttCode);
|
||||
// The order doesn't matter
|
||||
sort($aAuto);
|
||||
sort($aManual);
|
||||
static::assertEquals($aManual, $aAuto, "Class: $sClass, Attribute: $sAttCode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dataProvider enumPluginsProvider
|
||||
*
|
||||
* @param $expectedResults
|
||||
* @param $m_aExtensionClassNames
|
||||
* @param $m_aExtensionClasses
|
||||
* @param $interface
|
||||
* @param null $sFilterInstanceOf
|
||||
*/
|
||||
public function testEnumPlugins($expectedInstanciationCalls, $expectedResults, $m_aExtensionClassNames, $m_aExtensionClasses, $interface, $sFilterInstanceOf=null)
|
||||
{
|
||||
$pluginInstanciationManager = new \PluginInstanciationManager();
|
||||
$res = $pluginInstanciationManager->InstantiatePlugins($m_aExtensionClassNames, $interface);
|
||||
|
||||
$mPluginInstanciationManager = $this->createMock(\PluginInstanciationManager::class);
|
||||
$mPluginInstanciationManager->expects($this->exactly($expectedInstanciationCalls))
|
||||
->method('InstantiatePlugins')
|
||||
->willReturn($res);
|
||||
$m_PluginManager = new \PluginManager($m_aExtensionClassNames, $m_aExtensionClasses, $mPluginInstanciationManager);
|
||||
|
||||
//warning: called twice on purpose
|
||||
$m_PluginManager->EnumPlugins($interface, $sFilterInstanceOf);
|
||||
$pluginInstances = $m_PluginManager->EnumPlugins($interface, $sFilterInstanceOf);
|
||||
|
||||
$this->assertCount(sizeof($expectedResults), $pluginInstances);
|
||||
foreach($pluginInstances as $pluginInstance)
|
||||
{
|
||||
if ($sFilterInstanceOf!==null)
|
||||
{
|
||||
$this->assertTrue($pluginInstance instanceof $sFilterInstanceOf);
|
||||
}
|
||||
}
|
||||
$index=0;
|
||||
foreach($expectedResults as $expectedInterface)
|
||||
{
|
||||
$this->assertTrue(is_a($pluginInstances[$index], $expectedInterface));
|
||||
$index++;
|
||||
}
|
||||
}
|
||||
|
||||
public function enumPluginsProvider(){
|
||||
$aInterfaces = [
|
||||
"empty conf" => [ 0, [], [], [], 'Wizzard'],
|
||||
"simple instance retrieval" => [ 1, [Gryffindor::class], [ 'Wizzard' => [ Gryffindor::class]], [], 'Wizzard'],
|
||||
"check instanceof parameter" => [ 1, [Gryffindor::class, Slytherin::class], [ 'Wizzard' => [ Gryffindor::class, Slytherin::class]], [], 'Wizzard'],
|
||||
"try to retrieve a non instanciable object" => [ 1, [Gryffindor::class], [ 'Wizzard' => [ Gryffindor::class, Muggle::class]], [], 'Wizzard', Gryffindor::class ],
|
||||
];
|
||||
return $aInterfaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getPluginsProvider
|
||||
*
|
||||
* @param $expectedInstanciationCalls
|
||||
* @param $expectedResults
|
||||
* @param $m_aExtensionClassNames
|
||||
* @param $m_aExtensionClasses
|
||||
* @param $interface
|
||||
* @param $className
|
||||
*/
|
||||
public function testGetPlugins($expectedInstanciationCalls, $expectedResults, $m_aExtensionClassNames, $m_aExtensionClasses, $interface, $className)
|
||||
{
|
||||
$pluginInstanciationManager = new \PluginInstanciationManager();
|
||||
$res = $pluginInstanciationManager->InstantiatePlugins($m_aExtensionClassNames, $interface);
|
||||
|
||||
$mPluginInstanciationManager = $this->createMock(\PluginInstanciationManager::class);
|
||||
$mPluginInstanciationManager->expects($this->exactly($expectedInstanciationCalls))
|
||||
->method('InstantiatePlugins')
|
||||
->willReturn($res);
|
||||
$m_PluginManager = new \PluginManager($m_aExtensionClassNames, $m_aExtensionClasses, $mPluginInstanciationManager);
|
||||
|
||||
//warning: called twice on purpose
|
||||
$m_PluginManager->GetPlugins($interface, $className);
|
||||
$pluginInstance = $m_PluginManager->GetPlugins($interface, $className);
|
||||
|
||||
if (sizeof($expectedResults)==0)
|
||||
{
|
||||
$this->assertNull($pluginInstance);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->assertTrue($pluginInstance instanceof $className);
|
||||
$this->assertTrue(is_a($pluginInstance, $expectedResults[0]));
|
||||
}
|
||||
|
||||
public function getPluginsProvider(){
|
||||
$aInterfaces = [
|
||||
"empty conf" => [ 0, [], [], [], 'Wizzard', Gryffindor::class],
|
||||
"simple instance retrieval" => [ 1, [Gryffindor::class], [ 'Wizzard' => [ Gryffindor::class]], [], 'Wizzard', Gryffindor::class],
|
||||
"check instanceof parameter" => [ 1, [Gryffindor::class], [ 'Wizzard' => [ Gryffindor::class, Slytherin::class]], [], 'Wizzard', Gryffindor::class],
|
||||
"try to retrieve a non instanciable object" => [ 1, [Gryffindor::class], [ 'Wizzard' => [ Gryffindor::class, Muggle::class]], [], 'Wizzard', Gryffindor::class ],
|
||||
];
|
||||
return $aInterfaces;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
abstract class Wizzard
|
||||
{
|
||||
|
||||
/**
|
||||
* Wizzard constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class Gryffindor extends Wizzard
|
||||
{
|
||||
|
||||
}
|
||||
class Hufflepuff extends Wizzard
|
||||
{
|
||||
|
||||
}
|
||||
class Ravenclaw extends Wizzard
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class Slytherin extends Wizzard
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class Muggle
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
39
test/core/sanitizer/InlineImageMock.php
Normal file
39
test/core/sanitizer/InlineImageMock.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* 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/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mock class used by @see \Combodo\iTop\Test\UnitTest\Core\HTMLDOMSanitizerTest
|
||||
*
|
||||
*/
|
||||
class InlineImage
|
||||
{
|
||||
private static $iCallCounter = 0;
|
||||
|
||||
public static function ProcessImageTag(DOMNode $oNode)
|
||||
{
|
||||
self::$iCallCounter++;
|
||||
}
|
||||
|
||||
public static function GetCallCounter()
|
||||
{
|
||||
return self::$iCallCounter;
|
||||
}
|
||||
}
|
||||
@@ -123,87 +123,6 @@ class TestSQLQuery extends TestScenarioOnDB
|
||||
}
|
||||
}
|
||||
|
||||
class TestCSVParser extends TestFunction
|
||||
{
|
||||
static public function GetName() {return 'Check CSV parsing';}
|
||||
static public function GetDescription() {return 'Loads a set of CSV data';}
|
||||
|
||||
public function DoExecute()
|
||||
{
|
||||
$sDataFile = '?field1?;?field2?;?field3?
|
||||
?a?;?b?;?c?
|
||||
a;b;c
|
||||
? a ? ; ? b ? ; ? c ?
|
||||
a ; b ; c
|
||||
??;??;??
|
||||
;;
|
||||
?a"?;?b?;?c?
|
||||
?a1
|
||||
a2?;?b?;?c?
|
||||
?a1,a2?;?b?;?c?
|
||||
?a?;?b?;?c1,",c2
|
||||
,c3?
|
||||
?a?;?b?;?ouf !?
|
||||
Espace sur la fin ; 1234; e@taloc.com ';
|
||||
|
||||
self::DumpVariable($sDataFile);
|
||||
|
||||
$aExpectedResult = array(
|
||||
//array('field1', 'field2', 'field3'),
|
||||
array('a', 'b', 'c'),
|
||||
array('a', 'b', 'c'),
|
||||
array(' a ', ' b ', ' c '),
|
||||
array('a', 'b', 'c'),
|
||||
array('', '', ''),
|
||||
array('', '', ''),
|
||||
array('a"', 'b', 'c'),
|
||||
array("a1\na2", 'b', 'c'),
|
||||
array('a1,a2', 'b', 'c'),
|
||||
array('a', 'b', "c1,\",c2\n,c3"),
|
||||
array('a', 'b', 'ouf !'),
|
||||
array('Espace sur la fin', '1234', 'e@taloc.com'),
|
||||
);
|
||||
|
||||
$oCSVParser = new CSVParser($sDataFile, ';', '?');
|
||||
$aData = $oCSVParser->ToArray(1, null, 0);
|
||||
|
||||
$iIssues = 0;
|
||||
|
||||
echo "<table border=\"1\">\n";
|
||||
foreach ($aData as $iRow => $aRow)
|
||||
{
|
||||
echo "<tr>\n";
|
||||
foreach ($aRow as $iCol => $sCell)
|
||||
{
|
||||
if (empty($sCell))
|
||||
{
|
||||
$sCellValue = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCellValue = htmlentities($sCell, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
|
||||
if (!isset($aExpectedResult[$iRow][$iCol]))
|
||||
{
|
||||
$iIssues++;
|
||||
$sCellValue = "<span style =\"color: red; background-color: grey;\">$sCellValue</span>";
|
||||
}
|
||||
elseif ($aExpectedResult[$iRow][$iCol] != $sCell)
|
||||
{
|
||||
$iIssues++;
|
||||
$sCellValue = "<span style =\"color: red; background-color: lightgrey;\">$sCellValue</span>, expecting '<span style =\"color: green; background-color: lightgrey;\">".$aExpectedResult[$iRow][$iCol]."</span>'";
|
||||
}
|
||||
|
||||
echo "<td><pre>$sCellValue</pre></td>";
|
||||
}
|
||||
echo "</tr>\n";
|
||||
}
|
||||
echo "</table>\n";
|
||||
return ($iIssues > 0);
|
||||
}
|
||||
}
|
||||
|
||||
class TestGenericItoMyModel extends TestBizModelGeneric
|
||||
{
|
||||
static public function GetName()
|
||||
@@ -485,7 +404,7 @@ class TestMyBizModel extends TestBizModel
|
||||
echo "Max depth = $iMaxDepth</br>\n";
|
||||
|
||||
$oObj = MetaModel::GetObject("cmdbContact", 18);
|
||||
$aRels = $oObj->GetRelatedObjects("Potes", $iMaxDepth);
|
||||
$aRels = $oObj->GetRelatedObjectsDown("Potes", $iMaxDepth);
|
||||
echo $oObj->Get('name')." has some 'Potes'...</br>\n";
|
||||
foreach ($aRels as $sClass => $aObjs)
|
||||
{
|
||||
@@ -581,391 +500,6 @@ class TestMyBizModel extends TestBizModel
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test a complex biz model on the fly
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
abstract class MyFarm extends TestBizModel
|
||||
{
|
||||
static public function GetConfigFile() {return '/config-test-farm.php';}
|
||||
|
||||
protected function DoPrepare()
|
||||
{
|
||||
parent::DoPrepare();
|
||||
$this->ResetDB();
|
||||
MetaModel::DBCheckIntegrity();
|
||||
}
|
||||
|
||||
protected function InsertMammal($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId, $sName, $iHeight, $sBirth)
|
||||
{
|
||||
$oNew = MetaModel::NewObject('Mammal');
|
||||
$oNew->Set('species', $sSpecies);
|
||||
$oNew->Set('sex', $sSex);
|
||||
$oNew->Set('speed', $iSpeed);
|
||||
$oNew->Set('mother', $iMotherid);
|
||||
$oNew->Set('father', $iFatherId);
|
||||
$oNew->Set('name', $sName);
|
||||
$oNew->Set('height', $iHeight);
|
||||
$oNew->Set('birth', $sBirth);
|
||||
return $this->ObjectToDB($oNew);
|
||||
}
|
||||
|
||||
protected function InsertBird($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId)
|
||||
{
|
||||
$oNew = MetaModel::NewObject('Bird');
|
||||
$oNew->Set('species', $sSpecies);
|
||||
$oNew->Set('sex', $sSex);
|
||||
$oNew->Set('speed', $iSpeed);
|
||||
$oNew->Set('mother', $iMotherid);
|
||||
$oNew->Set('father', $iFatherId);
|
||||
return $this->ObjectToDB($oNew);
|
||||
}
|
||||
|
||||
protected function InsertFlyingBird($sSpecies, $sSex, $iSpeed, $iMotherid, $iFatherId, $iFlyingSpeed)
|
||||
{
|
||||
$oNew = MetaModel::NewObject('FlyingBird');
|
||||
$oNew->Set('species', $sSpecies);
|
||||
$oNew->Set('sex', $sSex);
|
||||
$oNew->Set('speed', $iSpeed);
|
||||
$oNew->Set('mother', $iMotherid);
|
||||
$oNew->Set('father', $iFatherId);
|
||||
$oNew->Set('flyingspeed', $iFlyingSpeed);
|
||||
return $this->ObjectToDB($oNew);
|
||||
}
|
||||
|
||||
private function InsertGroup($sName, $iLeaderId)
|
||||
{
|
||||
$oNew = MetaModel::NewObject('Group');
|
||||
$oNew->Set('name', $sName);
|
||||
$oNew->Set('leader', $iLeaderId);
|
||||
$iId = $oNew->DBInsertNoReload();
|
||||
return $iId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestQueriesOnFarm extends MyFarm
|
||||
{
|
||||
static public function GetName()
|
||||
{
|
||||
return 'Farm test';
|
||||
}
|
||||
|
||||
static public function GetDescription()
|
||||
{
|
||||
return 'A series of tests on the farm business model (SQL generation)';
|
||||
}
|
||||
|
||||
protected function CheckQuery($sQuery, $bIsCorrectQuery)
|
||||
{
|
||||
if ($bIsCorrectQuery)
|
||||
{
|
||||
echo "<h4 style=\"color:green;\">$sQuery</h4>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "<h4 style=\"color:red;\">$sQuery</h3>\n";
|
||||
}
|
||||
try
|
||||
{
|
||||
//$oOql = new OqlInterpreter($sQuery);
|
||||
//$oTrash = $oOql->ParseQuery();
|
||||
//self::DumpVariable($oTrash, true);
|
||||
$oMyFilter = DBObjectSearch::FromOQL($sQuery);
|
||||
}
|
||||
catch (OQLException $oOqlException)
|
||||
{
|
||||
if ($bIsCorrectQuery)
|
||||
{
|
||||
echo "<p>More info on this unexpected failure:<br/>".$oOqlException->getHtmlDesc()."</p>\n";
|
||||
throw $oOqlException;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Everything is fine :-)
|
||||
echo "<p>More info on this expected failure:\n";
|
||||
echo "<ul>\n";
|
||||
echo "<li>".get_class($oOqlException)."</li>\n";
|
||||
echo "<li>".$oOqlException->getMessage()."</li>\n";
|
||||
echo "<li>".$oOqlException->getHtmlDesc()."</li>\n";
|
||||
echo "</ul>\n";
|
||||
echo "</p>\n";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// The query was correctly parsed, was it expected to be correct ?
|
||||
if (!$bIsCorrectQuery)
|
||||
{
|
||||
throw new UnitTestException("The query '$sQuery' was parsed with success, while it shouldn't (?)");
|
||||
return false;
|
||||
}
|
||||
echo "<p>To OQL: ".$oMyFilter->ToOQL()."</p>";
|
||||
|
||||
$this->search_and_show_list($oMyFilter);
|
||||
|
||||
//echo "<p>first pass<p>\n";
|
||||
//self::DumpVariable($oMyFilter, true);
|
||||
$sQuery1 = $oMyFilter->MakeSelectQuery();
|
||||
//echo "<p>second pass<p>\n";
|
||||
//self::DumpVariable($oMyFilter, true);
|
||||
//$sQuery1 = $oMyFilter->MakeSelectQuery();
|
||||
|
||||
$sSerialize = $oMyFilter->serialize();
|
||||
echo "<p>Serialized:$sSerialize</p>\n";
|
||||
$oFilter2 = DBObjectSearch::unserialize($sSerialize);
|
||||
try
|
||||
{
|
||||
$sQuery2 = $oFilter2->MakeSelectQuery();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
echo "<p>Could not compute the query after unserialize</p>\n";
|
||||
echo "<p>Query 1: $sQuery1</p>\n";
|
||||
MyHelpers::var_cmp_html($oMyFilter, $oFilter2);
|
||||
throw $e;
|
||||
}
|
||||
//if ($oFilter2 != $oMyFilter) no, they may differ while the resulting query is the same!
|
||||
if ($sQuery1 != $sQuery2)
|
||||
{
|
||||
echo "<p>serialize/unserialize mismatch :-(</p>\n";
|
||||
MyHelpers::var_cmp_html($sQuery1, $sQuery2);
|
||||
MyHelpers::var_cmp_html($oMyFilter, $oFilter2);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function DoExecute()
|
||||
{
|
||||
// $this->ReportError("Found two different OQL expression out of the (same?) filter: <em>$sExpr1</em> != <em>$sExpr2</em>");
|
||||
// $this->ReportSuccess('Found '.$oSet->Count()." objects of class $sClassName");
|
||||
echo "<h3>Create protagonists...</h3>";
|
||||
|
||||
$iId1 = $this->InsertMammal('human', 'male', 10, 0, 0, 'romanoff', 192, '1971-07-19');
|
||||
$iId2 = $this->InsertMammal('human', 'female', 9, 0, 0, 'rouanita', 165, '1983-01-23');
|
||||
$this->InsertMammal('human', 'female', 3, $iId2, $iId1, 'pomme', 169, '2008-02-23');
|
||||
$this->InsertMammal('pig', 'female', 3, 0, 0, 'grouinkette', 85, '2006-06-01');
|
||||
$this->InsertMammal('donkey', 'female', 3, 0, 0, 'muleta', 124, '2003-11-11');
|
||||
|
||||
$this->InsertBird('rooster', 'male', 12, 0, 0);
|
||||
$this->InsertFlyingBird('pie', 'female', 11, 0, 0, 35);
|
||||
|
||||
// Benchmarking
|
||||
//
|
||||
if (false)
|
||||
{
|
||||
define ('COUNT_BENCHMARK', 10);
|
||||
echo "<h3>Parsing a long query, ".COUNT_BENCHMARK." times</h3>";
|
||||
$sQuery = "SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.birth < DATE_SUB(CURRENT_DATE(), INTERVAL 10 YEAR) AND Dad.height * 2 <= ROUND(TO_DAYS(Dad.birth) / (3 + 1) * 5 - 3)";
|
||||
|
||||
$fStart = MyHelpers::getmicrotime();
|
||||
for($i=0 ; $i < COUNT_BENCHMARK ; $i++)
|
||||
{
|
||||
$oMyFilter = DBObjectSearch::FromOQL($sQuery);
|
||||
}
|
||||
$fDuration = MyHelpers::getmicrotime() - $fStart;
|
||||
$fParsingDuration = $fDuration / COUNT_BENCHMARK;
|
||||
echo "<p>Mean time by op: $fParsingDuration</p>";
|
||||
}
|
||||
|
||||
echo "<h3>Test queries...</h3>";
|
||||
|
||||
$aQueries = array(
|
||||
'SELECT Animal' => true,
|
||||
'SELECT Animal WHERE Animal.pkey = 1' => false,
|
||||
'SELECT Animal WHERE Animal.id = 1' => true,
|
||||
'SELECT Aniiimal' => false,
|
||||
'SELECTe Animal' => false,
|
||||
'SELECT * FROM Animal' => false,
|
||||
'SELECT Animal AS zoo WHERE zoo.species = \'human\'' => true,
|
||||
'SELECT Animal AS zoo WHERE species = \'human\'' => true,
|
||||
'SELECT Animal AS zoo WHERE espece = \'human\'' => false,
|
||||
'SELECT Animal AS zoo WHERE zoo.species IN (\'human\', "pig")' => true,
|
||||
'SELECT Animal AS zoo WHERE CONCATENATION(zoo.species, zoo.sex) LIKE "hum%male"' => false,
|
||||
'SELECT Animal AS zoo WHERE CONCAT(zoo.species, zoo.sex) LIKE "hum%male"' => true,
|
||||
'SELECT Animal AS zoo WHERE zoo.species NOT IN (\'human\', "pig")' => true,
|
||||
'SELECT Animal AS zoo WHERE zoo.kind = \'human\'' => false,
|
||||
'SELECT Animal WHERE Animal.species = \'human\' AND Animal.sex = \'female\'' => true,
|
||||
'SELECT Mammal AS x WHERE (x.species = \'human\' AND x.name LIKE \'ro%\') OR (x.species = \'donkey\' AND x.name LIKE \'po%\')' => true,
|
||||
'SELECT Mammal AS x WHERE x.species = \'human\' AND x.name LIKE \'ro%\' OR x.species = \'donkey\' AND x.name LIKE \'po%\'' => true,
|
||||
'SELECT Mammal AS m WHERE MONTH(m.birth) = 7' => true,
|
||||
'SELECT Mammal AS m WHERE DAY(m.birth) = 19' => true,
|
||||
'SELECT Mammal AS m WHERE YEAR(m.birth) = 1971' => true,
|
||||
'SELECT Mammal AS m WHERE m.birth < DATE_SUB(CURRENT_DATE(), INTERVAL 10 YEAR)' => true,
|
||||
'SELECT Mammal AS m WHERE m.birth > DATE_SUB(NOW(), INTERVAL 2000 DAY)' => true,
|
||||
'SELECT Mammal AS m WHERE (TO_DAYS(NOW()) - TO_DAYS(m.birth)) > 2000' => true,
|
||||
'SELECT Mammal AS m WHERE m.name = IF(FLOOR(ROUND(m.height)) > 2, "pomme", "romain")' => true,
|
||||
'SELECT Mammal AS m WHERE (1 + 2' => false,
|
||||
'SELECT Mammal AS m WHERE (1 + 2 * 4 / 23) > 0' => true,
|
||||
'SELECT Mammal AS m WHERE (4 / 23 * 2 + 1) > 0' => true,
|
||||
'SELECT Mammal AS m WHERE 1/0' => true,
|
||||
'SELECT Mammal AS m WHERE MONTH(m.birth) = 7' => true,
|
||||
'SELECT Animal JOIN Group ON Group.leader = Animal.id' => true,
|
||||
'SELECT Group JOIN Animal ON Group.leader = Animal.id' => true,
|
||||
'SELECT Animal AS A JOIN Group AS G1 ON G1.leader = A.id' => true,
|
||||
'SELECT Animal AS A JOIN Group AS G ON FooClass.leader = A.id' => false,
|
||||
'SELECT Animal AS A JOIN Group AS G ON G.leader = FooClass.id' => false,
|
||||
'SELECT Animal AS A JOIN Group AS G ON G.masterchief = A.id' => false,
|
||||
'SELECT Animal AS A JOIN Group AS G ON A.id = G.leader' => false,
|
||||
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE A.sex=\'male\' OR G.qwerty = 123' => false,
|
||||
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE A.sex=\'male\' OR G.name LIKE "a%"' => true,
|
||||
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE A.id = 1' => true,
|
||||
'SELECT Animal AS A JOIN Group AS G ON G.leader = A.id WHERE id = 1' => false,
|
||||
'SELECT Animal AS A JOIN Group AS G ON A.member = G.id' => false,
|
||||
'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id' => true,
|
||||
'SELECT Mammal AS M JOIN Group AS G ON A.member = G.id' => false,
|
||||
'SELECT Mammal AS myAlias JOIN Group AS myAlias ON myAlias.member = myAlias.id' => false,
|
||||
'SELECT Mammal AS Mammal JOIN Group AS Mammal ON Mammal.member = Mammal.id' => false,
|
||||
'SELECT Group AS G WHERE G.leader_name LIKE "%"' => true,
|
||||
'SELECT Group AS G WHERE G.leader_speed < 100000' => true,
|
||||
'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id WHERE G.leader_name LIKE "%"' => true,
|
||||
'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id WHERE G.leader_speed < 100000' => true,
|
||||
'SELECT Mammal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id' => true,
|
||||
'SELECT Mammal AS Child JOIN Animal AS Dad ON Child.father = Dad.id' => true,
|
||||
'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id' => true,
|
||||
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id' => true,
|
||||
'SELECT Animal AS Dad JOIN Animal AS Child ON Child.father = Dad.id' => true,
|
||||
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id' => true,
|
||||
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.id = 1' => true,
|
||||
'SELECT Animal AS Child JOIN Animal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\'' => false,
|
||||
'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id' => true,
|
||||
'SELECT Animal AS Child JOIN Mammal AS Dad ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\' OR Mum.speed = 0' => true,
|
||||
'SELECT Animal AS Dad JOIN Animal AS Child ON Child.father = Dad.id JOIN Animal AS Mum ON Child.mother = Mum.id' => true,
|
||||
'SELECT Mammal AS Dad JOIN Mammal AS Child ON Child.father = Dad.id' => true,
|
||||
'SELECT Mammal AS Dad JOIN Mammal AS Child ON Child.father = Dad.id JOIN Mammal AS Mum ON Child.mother = Mum.id WHERE Dad.name = \'romanoff\' OR Mum.name=\'chloe\' OR Child.name=\'bizounours\'' => true,
|
||||
// Specifying multiple objects
|
||||
'SELECT Animal FROM Animal' => true,
|
||||
'SELECT yelele FROM Animal' => false,
|
||||
'SELECT Animal FROM Animal AS A' => false,
|
||||
'SELECT A FROM Animal AS A' => true,
|
||||
);
|
||||
//$aQueries = array(
|
||||
// 'SELECT Mammal AS M JOIN Group AS G ON M.member = G.id WHERE G.leader_name LIKE "%"' => true,
|
||||
//);
|
||||
foreach($aQueries as $sQuery => $bIsCorrect)
|
||||
{
|
||||
$this->CheckQuery($sQuery, $bIsCorrect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test data load
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TestBulkChangeOnFarm extends TestBizModel
|
||||
{
|
||||
static public function GetName()
|
||||
{
|
||||
return 'Farm test - data load';
|
||||
}
|
||||
|
||||
static public function GetDescription()
|
||||
{
|
||||
return 'Bulk load';
|
||||
}
|
||||
|
||||
static public function GetConfigFile() {return '/config-test-farm.php';}
|
||||
|
||||
protected function DoPrepare()
|
||||
{
|
||||
parent::DoPrepare();
|
||||
$this->ResetDB();
|
||||
MetaModel::DBCheckIntegrity();
|
||||
}
|
||||
|
||||
protected function DoExecute()
|
||||
{
|
||||
// $this->ReportError("Found two different OQL expression out of the (same?) filter: <em>$sExpr1</em> != <em>$sExpr2</em>");
|
||||
// $this->ReportSuccess('Found '.$oSet->Count()." objects of class $sClassName");
|
||||
|
||||
$oParser = new CSVParser("denomination,hauteur,age
|
||||
suzy,123,2009-01-01
|
||||
chita,456,
|
||||
", ',', '"');
|
||||
$aData = $oParser->ToArray(1, array('_name', '_height', '_birth'));
|
||||
self::DumpVariable($aData);
|
||||
|
||||
$oBulk = new BulkChange(
|
||||
'Mammal',
|
||||
$aData,
|
||||
// attributes
|
||||
array('name' => '_name', 'height' => '_height', 'birth' => '_birth'),
|
||||
// ext keys
|
||||
array(),
|
||||
// reconciliation
|
||||
array('name')
|
||||
);
|
||||
|
||||
$oMyChange = MetaModel::NewObject("CMDBChange");
|
||||
$oMyChange->Set("date", time());
|
||||
$oMyChange->Set("userinfo", "Testor");
|
||||
$iChangeId = $oMyChange->DBInsert();
|
||||
// echo "Created new change: $iChangeId</br>";
|
||||
|
||||
echo "<h3>Planned for loading...</h3>";
|
||||
$aRes = $oBulk->Process();
|
||||
self::DumpVariable($aRes);
|
||||
echo "<h3>Go for loading...</h3>";
|
||||
$aRes = $oBulk->Process($oMyChange);
|
||||
self::DumpVariable($aRes);
|
||||
|
||||
return;
|
||||
|
||||
$oRawData = array(
|
||||
'Mammal',
|
||||
array('species', 'sex', 'speed', 'mother', 'father', 'name', 'height', 'birth'),
|
||||
"human,male,23,0,0,romulus,192,1971
|
||||
human,male,23,0,0,remus,154,-50
|
||||
human,male,23,0,0,julius,160,-49
|
||||
human,female,23,0,0,cleopatra,142,-50
|
||||
pig,female,23,0,0,confucius,50,2003"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test data load
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TestFullTextSearchOnFarm extends MyFarm
|
||||
{
|
||||
static public function GetName()
|
||||
{
|
||||
return 'Farm test - full text search';
|
||||
}
|
||||
|
||||
static public function GetDescription()
|
||||
{
|
||||
return 'Focus on the full text search feature';
|
||||
}
|
||||
|
||||
protected function DoExecute()
|
||||
{
|
||||
echo "<h3>Create protagonists...</h3>";
|
||||
|
||||
$iId1 = $this->InsertMammal('human', 'male', 10, 0, 0, 'romanoff', 192, '1971-07-19');
|
||||
$iId2 = $this->InsertMammal('human', 'female', 9, 0, 0, 'rouanita', 165, '1983-01-23');
|
||||
$this->InsertMammal('human', 'female', 3, $iId2, $iId1, 'pomme', 169, '2008-02-23');
|
||||
$this->InsertMammal('pig', 'female', 3, 0, 0, 'grouinkette', 85, '2006-06-01');
|
||||
$this->InsertMammal('donkey', 'female', 3, 0, 0, 'muleta', 124, '2003-11-11');
|
||||
|
||||
$this->InsertBird('rooster', 'male', 12, 0, 0);
|
||||
$this->InsertFlyingBird('pie', 'female', 11, 0, 0, 35);
|
||||
|
||||
echo "<h3>Search...</h3>";
|
||||
$oSearch = new DBObjectSearch('Mammal');
|
||||
$oSearch->AddCondition_FullText('manof');
|
||||
//$oResultSet = new DBObjectSet($oSearch);
|
||||
$this->search_and_show_list($oSearch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test queries
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user